Commit d82492cf authored by Alex Kalderimis's avatar Alex Kalderimis

Merge branch 'add-job_artifacts-to-PipelineType' into 'master'

Add jobArtifacts to PipelineType

See merge request gitlab-org/gitlab!72412
parents f54b2cd8 22787ff4
# frozen_string_literal: true
module Resolvers
module Ci
class PipelineJobArtifactsResolver < BaseResolver
type [Types::Ci::JobArtifactType], null: false
alias_method :pipeline, :object
def resolve
find_job_artifacts
end
private
def find_job_artifacts
BatchLoader::GraphQL.for(pipeline).batch do |pipelines, loader|
ActiveRecord::Associations::Preloader.new.preload(pipelines, :job_artifacts) # rubocop: disable CodeReuse/ActiveRecord
pipelines.each { |pl| loader.call(pl, pl.job_artifacts) }
end
end
end
end
end
...@@ -12,6 +12,10 @@ module Types ...@@ -12,6 +12,10 @@ module Types
field :file_type, ::Types::Ci::JobArtifactFileTypeEnum, null: true, field :file_type, ::Types::Ci::JobArtifactFileTypeEnum, null: true,
description: 'File type of the artifact.' description: 'File type of the artifact.'
field :name, GraphQL::Types::String, null: true,
description: 'File name of the artifact.',
method: :filename
def download_path def download_path
::Gitlab::Routing.url_helpers.download_project_job_artifacts_path( ::Gitlab::Routing.url_helpers.download_project_job_artifacts_path(
object.project, object.project,
......
...@@ -108,6 +108,11 @@ module Types ...@@ -108,6 +108,11 @@ module Types
description: 'Name of the job.' description: 'Name of the job.'
end end
field :job_artifacts,
null: true,
description: 'Job artifacts of the pipeline.',
resolver: ::Resolvers::Ci::PipelineJobArtifactsResolver
field :source_job, field :source_job,
type: Types::Ci::JobType, type: Types::Ci::JobType,
null: true, null: true,
......
...@@ -8600,6 +8600,7 @@ Represents the total number of issues and their weights for a particular day. ...@@ -8600,6 +8600,7 @@ Represents the total number of issues and their weights for a particular day.
| ---- | ---- | ----------- | | ---- | ---- | ----------- |
| <a id="cijobartifactdownloadpath"></a>`downloadPath` | [`String`](#string) | URL for downloading the artifact's file. | | <a id="cijobartifactdownloadpath"></a>`downloadPath` | [`String`](#string) | URL for downloading the artifact's file. |
| <a id="cijobartifactfiletype"></a>`fileType` | [`JobArtifactFileType`](#jobartifactfiletype) | File type of the artifact. | | <a id="cijobartifactfiletype"></a>`fileType` | [`JobArtifactFileType`](#jobartifactfiletype) | File type of the artifact. |
| <a id="cijobartifactname"></a>`name` | [`String`](#string) | File name of the artifact. |
### `CiJobTokenScopeType` ### `CiJobTokenScopeType`
...@@ -12472,6 +12473,7 @@ Represents a file or directory in the project repository that has been locked. ...@@ -12472,6 +12473,7 @@ Represents a file or directory in the project repository that has been locked.
| <a id="pipelinefinishedat"></a>`finishedAt` | [`Time`](#time) | Timestamp of the pipeline's completion. | | <a id="pipelinefinishedat"></a>`finishedAt` | [`Time`](#time) | Timestamp of the pipeline's completion. |
| <a id="pipelineid"></a>`id` | [`ID!`](#id) | ID of the pipeline. | | <a id="pipelineid"></a>`id` | [`ID!`](#id) | ID of the pipeline. |
| <a id="pipelineiid"></a>`iid` | [`String!`](#string) | Internal ID of the pipeline. | | <a id="pipelineiid"></a>`iid` | [`String!`](#string) | Internal ID of the pipeline. |
| <a id="pipelinejobartifacts"></a>`jobArtifacts` | [`[CiJobArtifact!]`](#cijobartifact) | Job artifacts of the pipeline. |
| <a id="pipelinepath"></a>`path` | [`String`](#string) | Relative path to the pipeline's page. | | <a id="pipelinepath"></a>`path` | [`String`](#string) | Relative path to the pipeline's page. |
| <a id="pipelineproject"></a>`project` | [`Project`](#project) | Project the pipeline belongs to. | | <a id="pipelineproject"></a>`project` | [`Project`](#project) | Project the pipeline belongs to. |
| <a id="pipelinequeuedduration"></a>`queuedDuration` | [`Duration`](#duration) | How long the pipeline was queued before starting. | | <a id="pipelinequeuedduration"></a>`queuedDuration` | [`Duration`](#duration) | How long the pipeline was queued before starting. |
......
...@@ -4,7 +4,7 @@ require 'spec_helper' ...@@ -4,7 +4,7 @@ require 'spec_helper'
RSpec.describe GitlabSchema.types['CiJobArtifact'] do RSpec.describe GitlabSchema.types['CiJobArtifact'] do
it 'has the correct fields' do it 'has the correct fields' do
expected_fields = [:download_path, :file_type] expected_fields = [:download_path, :file_type, :name]
expect(described_class).to have_graphql_fields(*expected_fields) expect(described_class).to have_graphql_fields(*expected_fields)
end end
......
...@@ -12,7 +12,7 @@ RSpec.describe Types::Ci::PipelineType do ...@@ -12,7 +12,7 @@ RSpec.describe Types::Ci::PipelineType do
id iid sha before_sha complete status detailed_status config_source id iid sha before_sha complete status detailed_status config_source
duration queued_duration duration queued_duration
coverage created_at updated_at started_at finished_at committed_at coverage created_at updated_at started_at finished_at committed_at
stages user retryable cancelable jobs source_job job downstream stages user retryable cancelable jobs source_job job job_artifacts downstream
upstream path project active user_permissions warnings commit commit_path uses_needs upstream path project active user_permissions warnings commit commit_path uses_needs
test_report_summary test_suite ref test_report_summary test_suite ref
] ]
......
...@@ -186,6 +186,69 @@ RSpec.describe 'Query.project(fullPath).pipelines' do ...@@ -186,6 +186,69 @@ RSpec.describe 'Query.project(fullPath).pipelines' do
end end
end end
describe '.job_artifacts' do
let_it_be(:pipeline) { create(:ci_pipeline, project: project) }
let_it_be(:pipeline_job_1) { create(:ci_build, pipeline: pipeline, name: 'Job 1') }
let_it_be(:pipeline_job_artifact_1) { create(:ci_job_artifact, job: pipeline_job_1) }
let_it_be(:pipeline_job_2) { create(:ci_build, pipeline: pipeline, name: 'Job 2') }
let_it_be(:pipeline_job_artifact_2) { create(:ci_job_artifact, job: pipeline_job_2) }
let(:path) { %i[project pipelines nodes jobArtifacts] }
let(:query) do
%(
query {
project(fullPath: "#{project.full_path}") {
pipelines {
nodes {
jobArtifacts {
name
downloadPath
fileType
}
}
}
}
}
)
end
before do
post_graphql(query, current_user: user)
end
it_behaves_like 'a working graphql query'
it 'returns the job_artifacts of a pipeline' do
job_artifacts_graphql_data = graphql_data_at(*path).flatten
expect(
job_artifacts_graphql_data.map { |pip| pip['name'] }
).to contain_exactly(pipeline_job_artifact_1.filename, pipeline_job_artifact_2.filename)
end
it 'avoids N+1 queries' do
first_user = create(:user)
second_user = create(:user)
control_count = ActiveRecord::QueryRecorder.new do
post_graphql(query, current_user: first_user)
end
pipeline_2 = create(:ci_pipeline, project: project)
pipeline_2_job_1 = create(:ci_build, pipeline: pipeline_2, name: 'Pipeline 2 Job 1')
create(:ci_job_artifact, job: pipeline_2_job_1)
pipeline_2_job_2 = create(:ci_build, pipeline: pipeline_2, name: 'Pipeline 2 Job 2')
create(:ci_job_artifact, job: pipeline_2_job_2)
expect do
post_graphql(query, current_user: second_user)
end.not_to exceed_query_limit(control_count)
expect(response).to have_gitlab_http_status(:ok)
end
end
describe '.jobs(securityReportTypes)' do describe '.jobs(securityReportTypes)' do
let_it_be(:query) do let_it_be(:query) do
%( %(
......
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