Commit 363669db authored by charlie ablett's avatar charlie ablett

Merge branch 'lm-add-short-sha-and-path-to-pipeline' into 'master'

Makes pipeline be searchable by sha or iid

See merge request gitlab-org/gitlab!54471
parents e990feb0 5e1270ba
......@@ -7,14 +7,34 @@ module Resolvers
alias_method :project, :object
argument :iid, GraphQL::ID_TYPE,
required: true,
description: 'IID of the Pipeline, e.g., "1".'
required: false,
description: 'IID of the Pipeline. For example, "1".'
def resolve(iid:)
BatchLoader::GraphQL.for(iid).batch(key: project) do |iids, loader, args|
finder = ::Ci::PipelinesFinder.new(project, context[:current_user], iids: iids)
argument :sha, GraphQL::STRING_TYPE,
required: false,
description: 'SHA of the Pipeline. For example, "dyd0f15ay83993f5ab66k927w28673882x99100b".'
finder.execute.each { |pipeline| loader.call(pipeline.iid.to_s, pipeline) }
def ready?(iid: nil, sha: nil)
unless iid.present? ^ sha.present?
raise Gitlab::Graphql::Errors::ArgumentError, 'Provide one of an IID or SHA'
end
super
end
def resolve(iid: nil, sha: nil)
if iid
BatchLoader::GraphQL.for(iid).batch(key: project) do |iids, loader, args|
finder = ::Ci::PipelinesFinder.new(project, current_user, iids: iids)
finder.execute.each { |pipeline| loader.call(pipeline.iid.to_s, pipeline) }
end
else
BatchLoader::GraphQL.for(sha).batch(key: project) do |shas, loader, args|
finder = ::Ci::PipelinesFinder.new(project, current_user, shas: shas)
finder.execute.each { |pipeline| loader.call(pipeline.sha.to_s, pipeline) }
end
end
end
end
......
......@@ -95,6 +95,9 @@ module Types
field :path, GraphQL::STRING_TYPE, null: true,
description: "Relative path to the pipeline's page."
field :commit_path, GraphQL::STRING_TYPE, null: true,
description: 'Path to the commit that triggered the pipeline.'
field :project, Types::ProjectType, null: true,
description: 'Project the pipeline belongs to.'
......@@ -109,6 +112,10 @@ module Types
Gitlab::Graphql::Loaders::BatchModelLoader.new(User, object.user_id).find
end
def commit_path
::Gitlab::Routing.url_helpers.project_commit_path(object.project, object.sha)
end
def path
::Gitlab::Routing.url_helpers.project_pipeline_path(object.project, object)
end
......
---
title: Allow search for pipeline by SHA as well as IID via GraphQL
merge_request: 54471
author:
type: changed
......@@ -3196,6 +3196,7 @@ Information about pagination in a connection.
| `active` | Boolean! | Indicates if the pipeline is active. |
| `beforeSha` | String | Base SHA of the source branch. |
| `cancelable` | Boolean! | Specifies if a pipeline can be canceled. |
| `commitPath` | String | Path to the commit that triggered the pipeline. |
| `committedAt` | Time | Timestamp of the pipeline's commit. |
| `configSource` | PipelineConfigSourceEnum | Configuration source of the pipeline (UNKNOWN_SOURCE, REPOSITORY_SOURCE, AUTO_DEVOPS_SOURCE, WEBIDE_SOURCE, REMOTE_SOURCE, EXTERNAL_PROJECT_SOURCE, BRIDGE_SOURCE, PARAMETER_SOURCE, COMPLIANCE_SOURCE) |
| `coverage` | Float | Coverage percentage. |
......
......@@ -14,7 +14,7 @@ RSpec.describe 'getting a requirement list for a project' do
<<~QUERY
edges {
node {
#{all_graphql_fields_for('requirements'.classify)}
#{all_graphql_fields_for('requirements'.classify, max_depth: 1)}
}
}
QUERY
......
......@@ -6,7 +6,7 @@ RSpec.describe Resolvers::ProjectPipelineResolver do
include GraphqlHelpers
let_it_be(:project) { create(:project) }
let_it_be(:pipeline) { create(:ci_pipeline, project: project, iid: '1234') }
let_it_be(:pipeline) { create(:ci_pipeline, project: project, iid: '1234', sha: 'sha') }
let_it_be(:other_pipeline) { create(:ci_pipeline) }
let(:current_user) { create(:user) }
......@@ -30,7 +30,15 @@ RSpec.describe Resolvers::ProjectPipelineResolver do
expect(result).to eq(pipeline)
end
it 'keeps the queries under the threshold' do
it 'resolves pipeline for the passed sha' do
result = batch_sync do
resolve_pipeline(project, { sha: 'sha' })
end
expect(result).to eq(pipeline)
end
it 'keeps the queries under the threshold for iid' do
create(:ci_pipeline, project: project, iid: '1235')
control = ActiveRecord::QueryRecorder.new do
......@@ -45,6 +53,21 @@ RSpec.describe Resolvers::ProjectPipelineResolver do
end.not_to exceed_query_limit(control)
end
it 'keeps the queries under the threshold for sha' do
create(:ci_pipeline, project: project, sha: 'sha2')
control = ActiveRecord::QueryRecorder.new do
batch_sync { resolve_pipeline(project, { sha: 'sha' }) }
end
expect do
batch_sync do
resolve_pipeline(project, { sha: 'sha' })
resolve_pipeline(project, { sha: 'sha2' })
end
end.not_to exceed_query_limit(control)
end
it 'does not resolve a pipeline outside the project' do
result = batch_sync do
resolve_pipeline(other_pipeline.project, { iid: '1234' })
......@@ -53,8 +76,14 @@ RSpec.describe Resolvers::ProjectPipelineResolver do
expect(result).to be_nil
end
it 'errors when no iid is passed' do
expect { resolve_pipeline(project, {}) }.to raise_error(ArgumentError)
it 'errors when no iid or sha is passed' do
expect { resolve_pipeline(project, {}) }
.to raise_error(Gitlab::Graphql::Errors::ArgumentError)
end
it 'errors when both iid and sha are passed' do
expect { resolve_pipeline(project, { iid: '1234', sha: 'sha' }) }
.to raise_error(Gitlab::Graphql::Errors::ArgumentError)
end
context 'when the pipeline is a dangling pipeline' do
......
......@@ -12,7 +12,7 @@ RSpec.describe Types::Ci::PipelineType do
id iid sha before_sha status detailed_status config_source duration
coverage created_at updated_at started_at finished_at committed_at
stages user retryable cancelable jobs source_job downstream
upstream path project active user_permissions warnings
upstream path project active user_permissions warnings commit_path
]
if Gitlab.ee?
......
......@@ -13,7 +13,7 @@ RSpec.describe 'container repository details' do
graphql_query_for(
'containerRepository',
{ id: container_repository_global_id },
all_graphql_fields_for('ContainerRepositoryDetails')
all_graphql_fields_for('ContainerRepositoryDetails', excluded: ['pipeline'])
)
end
......
......@@ -18,7 +18,7 @@ RSpec.describe 'getting container repositories in a group' do
<<~GQL
edges {
node {
#{all_graphql_fields_for('container_repositories'.classify)}
#{all_graphql_fields_for('container_repositories'.classify, max_depth: 1)}
}
}
GQL
......
......@@ -23,7 +23,7 @@ RSpec.describe 'getting projects' do
projects(includeSubgroups: #{include_subgroups}) {
edges {
node {
#{all_graphql_fields_for('Project')}
#{all_graphql_fields_for('Project', max_depth: 1)}
}
}
}
......
......@@ -15,7 +15,7 @@ RSpec.describe 'package details' do
end
let(:depth) { 3 }
let(:excluded) { %w[metadata apiFuzzingCiConfiguration] }
let(:excluded) { %w[metadata apiFuzzingCiConfiguration pipeline] }
let(:query) do
graphql_query_for(:package, { id: package_global_id }, <<~FIELDS)
......
......@@ -16,7 +16,7 @@ RSpec.describe 'getting container repositories in a project' do
<<~GQL
edges {
node {
#{all_graphql_fields_for('container_repositories'.classify)}
#{all_graphql_fields_for('container_repositories'.classify, excluded: ['pipeline'])}
}
}
GQL
......
......@@ -34,7 +34,7 @@ RSpec.describe 'getting notes for a merge request' do
notes {
edges {
node {
#{all_graphql_fields_for('Note')}
#{all_graphql_fields_for('Note', excluded: ['pipeline'])}
}
}
}
......
......@@ -9,7 +9,7 @@ RSpec.describe 'getting merge request information nested in a project' do
let(:current_user) { create(:user) }
let(:merge_request_graphql_data) { graphql_data['project']['mergeRequest'] }
let!(:merge_request) { create(:merge_request, source_project: project) }
let(:mr_fields) { all_graphql_fields_for('MergeRequest') }
let(:mr_fields) { all_graphql_fields_for('MergeRequest', excluded: ['pipeline']) }
let(:query) do
graphql_query_for(
......
......@@ -11,10 +11,14 @@ RSpec.describe 'getting pipeline information nested in a project' do
let(:pipeline_graphql_data) { graphql_data['project']['pipeline'] }
let!(:query) do
graphql_query_for(
'project',
{ 'fullPath' => project.full_path },
query_graphql_field('pipeline', iid: pipeline.iid.to_s)
%(
query {
project(fullPath: "#{project.full_path}") {
pipeline(iid: "#{pipeline.iid}") {
configSource
}
}
}
)
end
......
......@@ -17,7 +17,7 @@ RSpec.shared_context 'exposing regular notes on a noteable in GraphQL' do
notes {
edges {
node {
#{all_graphql_fields_for('Note')}
#{all_graphql_fields_for('Note', max_depth: 1)}
}
}
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment