diff --git a/app/assets/javascripts/artifacts/graphql/queries/get_job_artifacts.query.graphql b/app/assets/javascripts/artifacts/graphql/queries/get_job_artifacts.query.graphql index 89a24d7891e7f85dc869f487bfbdb3358191302c..9777153999eabb4129551d5f15b5035cc091fb2c 100644 --- a/app/assets/javascripts/artifacts/graphql/queries/get_job_artifacts.query.graphql +++ b/app/assets/javascripts/artifacts/graphql/queries/get_job_artifacts.query.graphql @@ -10,6 +10,7 @@ query getJobArtifacts( project(fullPath: $projectPath) { id jobs( + withArtifacts: true statuses: [SUCCESS, FAILED] first: $firstPageSize last: $lastPageSize diff --git a/app/finders/ci/jobs_finder.rb b/app/finders/ci/jobs_finder.rb index 2ad62659451aaccaa89818c3444b1bfd20cc6e4d..1627e41a02d5c726218f56a69724a7b2e90a8ebf 100644 --- a/app/finders/ci/jobs_finder.rb +++ b/app/finders/ci/jobs_finder.rb @@ -16,6 +16,7 @@ def initialize(current_user:, pipeline: nil, project: nil, runner: nil, params: def execute builds = init_collection.order_id_desc + builds = filter_by_with_artifacts(builds) filter_by_scope(builds) rescue Gitlab::Access::AccessDeniedError type.none @@ -72,6 +73,14 @@ def filter_by_scope(builds) end end + def filter_by_with_artifacts(builds) + if params[:with_artifacts] + builds.with_erasable_artifacts + else + builds + end + end + def filter_by_statuses!(builds) unknown_statuses = params[:scope] - ::CommitStatus::AVAILABLE_STATUSES raise ArgumentError, 'Scope contains invalid value(s)' unless unknown_statuses.empty? diff --git a/app/graphql/resolvers/project_jobs_resolver.rb b/app/graphql/resolvers/project_jobs_resolver.rb index d9e51887813a3d82cd503cc8ce57b91693231743..2bf71679dbfbaf80f2cb7cd131e663ee53884b63 100644 --- a/app/graphql/resolvers/project_jobs_resolver.rb +++ b/app/graphql/resolvers/project_jobs_resolver.rb @@ -14,10 +14,18 @@ class ProjectJobsResolver < BaseResolver required: false, description: 'Filter jobs by status.' + argument :with_artifacts, ::GraphQL::Types::Boolean, + required: false, + description: 'Filter by artifacts presence.' + alias_method :project, :object - def resolve_with_lookahead(statuses: nil) - jobs = ::Ci::JobsFinder.new(current_user: current_user, project: project, params: { scope: statuses }).execute + def resolve_with_lookahead(statuses: nil, with_artifacts: nil) + jobs = ::Ci::JobsFinder.new( + current_user: current_user, project: project, params: { + scope: statuses, with_artifacts: with_artifacts + } + ).execute apply_lookahead(jobs) end diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md index 14fced27be4e169b291feb7ecbc128fa691c6992..e93aa09d28a765bcfc09df56f0da75597cb21d2b 100644 --- a/doc/api/graphql/reference/index.md +++ b/doc/api/graphql/reference/index.md @@ -17666,6 +17666,7 @@ four standard [pagination arguments](#connection-pagination-arguments): | Name | Type | Description | | ---- | ---- | ----------- | | <a id="projectjobsstatuses"></a>`statuses` | [`[CiJobStatus!]`](#cijobstatus) | Filter jobs by status. | +| <a id="projectjobswithartifacts"></a>`withArtifacts` | [`Boolean`](#boolean) | Filter by artifacts presence. | ##### `Project.label` diff --git a/spec/finders/ci/jobs_finder_spec.rb b/spec/finders/ci/jobs_finder_spec.rb index 4c94aa4049bc640a233aa300427e1297fa43e2d6..0b3777a2fe8b698e38ff1473a96ae58d539ecb2d 100644 --- a/spec/finders/ci/jobs_finder_spec.rb +++ b/spec/finders/ci/jobs_finder_spec.rb @@ -99,6 +99,33 @@ end end + context 'when artifacts are present for some jobs' do + let_it_be(:job_with_artifacts) { create(:ci_build, :success, pipeline: pipeline, name: 'test') } + let_it_be(:artifact) { create(:ci_job_artifact, job: job_with_artifacts) } + + subject { described_class.new(current_user: user, project: project, params: params).execute } + + before do + project.add_maintainer(user) + end + + context 'when with_artifacts is true' do + let(:params) { { with_artifacts: true } } + + it 'returns only jobs with artifacts' do + expect(subject).to match_array([job_with_artifacts]) + end + end + + context 'when with_artifacts is false' do + let(:params) { { with_artifacts: false } } + + it 'returns all jobs' do + expect(subject).to match_array([successful_job, job_with_artifacts]) + end + end + end + context 'when pipeline is present' do before_all do project.add_maintainer(user) diff --git a/spec/graphql/types/project_type_spec.rb b/spec/graphql/types/project_type_spec.rb index 30fabb8e9e25ae657d0a49a61b8a14cf5e8201cb..4151789372bf3ef79e747fd79f151cee1962d089 100644 --- a/spec/graphql/types/project_type_spec.rb +++ b/spec/graphql/types/project_type_spec.rb @@ -492,7 +492,7 @@ subject { described_class.fields['jobs'] } it { is_expected.to have_graphql_type(Types::Ci::JobType.connection_type) } - it { is_expected.to have_graphql_arguments(:statuses) } + it { is_expected.to have_graphql_arguments(:statuses, :with_artifacts) } end describe 'ci_template field' do