Commit f6dc6fba authored by Furkan Ayhan's avatar Furkan Ayhan Committed by Kamil Trzciński

Fix pipeline status when DAG jobs needs manual jobs

We achieve this with skipping DAG jobs when it needs a manual job.
parent bf1611e8
...@@ -39,7 +39,7 @@ module Ci ...@@ -39,7 +39,7 @@ module Ci
def status_struct def status_struct
strong_memoize(:status_struct) do strong_memoize(:status_struct) do
Gitlab::Ci::Status::Composite Gitlab::Ci::Status::Composite
.new(@jobs) .new(@jobs, project: project)
end end
end end
......
...@@ -32,7 +32,7 @@ module Ci ...@@ -32,7 +32,7 @@ module Ci
end end
def status def status
@status ||= statuses.latest.composite_status @status ||= statuses.latest.composite_status(project: project)
end end
def detailed_status(current_user) def detailed_status(current_user)
......
...@@ -138,7 +138,7 @@ module Ci ...@@ -138,7 +138,7 @@ module Ci
end end
def latest_stage_status def latest_stage_status
statuses.latest.composite_status || 'skipped' statuses.latest.composite_status(project: project) || 'skipped'
end end
end end
end end
...@@ -20,9 +20,11 @@ module Ci ...@@ -20,9 +20,11 @@ module Ci
UnknownStatusError = Class.new(StandardError) UnknownStatusError = Class.new(StandardError)
class_methods do class_methods do
def composite_status # The parameter `project` is only used for the feature flag check, and will be removed with
# https://gitlab.com/gitlab-org/gitlab/-/issues/321972
def composite_status(project: nil)
Gitlab::Ci::Status::Composite Gitlab::Ci::Status::Composite
.new(all, with_allow_failure: columns_hash.key?('allow_failure')) .new(all, with_allow_failure: columns_hash.key?('allow_failure'), project: project)
.status .status
end end
......
...@@ -78,7 +78,7 @@ module Ci ...@@ -78,7 +78,7 @@ module Ci
def status_for_array(statuses, dag:) def status_for_array(statuses, dag:)
result = Gitlab::Ci::Status::Composite result = Gitlab::Ci::Status::Composite
.new(statuses, dag: dag) .new(statuses, dag: dag, project: pipeline.project)
.status .status
result || 'success' result || 'success'
end end
......
---
name: ci_fix_pipeline_status_for_dag_needs_manual
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/53476
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/321972
milestone: '13.10'
type: development
group: group::pipeline authoring
default_enabled: false
...@@ -7,7 +7,10 @@ module Gitlab ...@@ -7,7 +7,10 @@ module Gitlab
include Gitlab::Utils::StrongMemoize include Gitlab::Utils::StrongMemoize
# This class accepts an array of arrays/hashes/or objects # This class accepts an array of arrays/hashes/or objects
def initialize(all_statuses, with_allow_failure: true, dag: false) #
# The parameter `project` is only used for the feature flag check, and will be removed with
# https://gitlab.com/gitlab-org/gitlab/-/issues/321972
def initialize(all_statuses, with_allow_failure: true, dag: false, project: nil)
unless all_statuses.respond_to?(:pluck) unless all_statuses.respond_to?(:pluck)
raise ArgumentError, "all_statuses needs to respond to `.pluck`" raise ArgumentError, "all_statuses needs to respond to `.pluck`"
end end
...@@ -16,6 +19,7 @@ module Gitlab ...@@ -16,6 +19,7 @@ module Gitlab
@status_key = 0 @status_key = 0
@allow_failure_key = 1 if with_allow_failure @allow_failure_key = 1 if with_allow_failure
@dag = dag @dag = dag
@project = project
consume_all_statuses(all_statuses) consume_all_statuses(all_statuses)
end end
...@@ -32,7 +36,7 @@ module Gitlab ...@@ -32,7 +36,7 @@ module Gitlab
return if none? return if none?
strong_memoize(:status) do strong_memoize(:status) do
if @dag && any_of?(:skipped) if @dag && any_skipped_or_ignored?
# The DAG job is skipped if one of the needs does not run at all. # The DAG job is skipped if one of the needs does not run at all.
'skipped' 'skipped'
elsif @dag && !only_of?(:success, :failed, :canceled, :skipped, :success_with_warnings) elsif @dag && !only_of?(:success, :failed, :canceled, :skipped, :success_with_warnings)
...@@ -90,6 +94,14 @@ module Gitlab ...@@ -90,6 +94,14 @@ module Gitlab
matching == @status_set.size matching == @status_set.size
end end
def any_skipped_or_ignored?
if ::Feature.enabled?(:ci_fix_pipeline_status_for_dag_needs_manual, @project, default_enabled: :yaml)
any_of?(:skipped) || any_of?(:ignored)
else
any_of?(:skipped)
end
end
def consume_all_statuses(all_statuses) def consume_all_statuses(all_statuses)
columns = [] columns = []
columns[@status_key] = :status columns[@status_key] = :status
......
...@@ -69,6 +69,8 @@ RSpec.describe Gitlab::Ci::Status::Composite do ...@@ -69,6 +69,8 @@ RSpec.describe Gitlab::Ci::Status::Composite do
%i(manual) | false | 'skipped' | false %i(manual) | false | 'skipped' | false
%i(skipped failed) | false | 'success' | true %i(skipped failed) | false | 'success' | true
%i(skipped failed) | true | 'skipped' | true %i(skipped failed) | true | 'skipped' | true
%i(success manual) | true | 'skipped' | false
%i(success manual) | false | 'success' | false
%i(created failed) | false | 'created' | true %i(created failed) | false | 'created' | true
%i(preparing manual) | false | 'preparing' | false %i(preparing manual) | false | 'preparing' | false
end end
...@@ -80,6 +82,25 @@ RSpec.describe Gitlab::Ci::Status::Composite do ...@@ -80,6 +82,25 @@ RSpec.describe Gitlab::Ci::Status::Composite do
it_behaves_like 'compares status and warnings' it_behaves_like 'compares status and warnings'
end end
context 'when FF ci_fix_pipeline_status_for_dag_needs_manual is disabled' do
before do
stub_feature_flags(ci_fix_pipeline_status_for_dag_needs_manual: false)
end
where(:build_statuses, :dag, :result, :has_warnings) do
%i(success manual) | true | 'pending' | false
%i(success manual) | false | 'success' | false
end
with_them do
let(:all_statuses) do
build_statuses.map { |status| @statuses_with_allow_failure[status] }
end
it_behaves_like 'compares status and warnings'
end
end
end end
end end
end end
...@@ -843,6 +843,19 @@ RSpec.shared_examples 'Pipeline Processing Service' do ...@@ -843,6 +843,19 @@ RSpec.shared_examples 'Pipeline Processing Service' do
create(:ci_build_need, build: deploy, name: 'linux:build') create(:ci_build_need, build: deploy, name: 'linux:build')
end end
it 'makes deploy DAG to be skipped' do
expect(process_pipeline).to be_truthy
expect(stages).to eq(%w(skipped skipped))
expect(all_builds.manual).to contain_exactly(linux_build)
expect(all_builds.skipped).to contain_exactly(deploy)
end
context 'when FF ci_fix_pipeline_status_for_dag_needs_manual is disabled' do
before do
stub_feature_flags(ci_fix_pipeline_status_for_dag_needs_manual: false)
end
it 'makes deploy DAG to be waiting for optional manual to finish' do it 'makes deploy DAG to be waiting for optional manual to finish' do
expect(process_pipeline).to be_truthy expect(process_pipeline).to be_truthy
...@@ -851,6 +864,7 @@ RSpec.shared_examples 'Pipeline Processing Service' do ...@@ -851,6 +864,7 @@ RSpec.shared_examples 'Pipeline Processing Service' do
expect(all_builds.created).to contain_exactly(deploy) expect(all_builds.created).to contain_exactly(deploy)
end end
end end
end
private private
......
...@@ -30,12 +30,12 @@ transitions: ...@@ -30,12 +30,12 @@ transitions:
- event: success - event: success
jobs: [build] jobs: [build]
expect: expect:
pipeline: running pipeline: success
stages: stages:
build: success build: success
test: skipped test: skipped
deploy: created deploy: skipped
jobs: jobs:
build: success build: success
test: manual test: manual
deploy: created deploy: skipped
...@@ -30,12 +30,12 @@ transitions: ...@@ -30,12 +30,12 @@ transitions:
- event: success - event: success
jobs: [build] jobs: [build]
expect: expect:
pipeline: running pipeline: success
stages: stages:
build: success build: success
test: skipped test: skipped
deploy: created deploy: skipped
jobs: jobs:
build: success build: success
test: manual test: manual
deploy: created deploy: skipped
...@@ -54,29 +54,29 @@ transitions: ...@@ -54,29 +54,29 @@ transitions:
stages: stages:
build: success build: success
test: pending test: pending
review: created review: skipped
deploy: created deploy: skipped
jobs: jobs:
build: success build: success
test: pending test: pending
release_test: manual release_test: manual
review: created review: skipped
staging: created staging: skipped
production: created production: skipped
- event: success - event: success
jobs: [test] jobs: [test]
expect: expect:
pipeline: running pipeline: success
stages: stages:
build: success build: success
test: success test: success
review: created review: skipped
deploy: created deploy: skipped
jobs: jobs:
build: success build: success
test: success test: success
release_test: manual release_test: manual
review: created review: skipped
staging: created staging: skipped
production: created production: skipped
...@@ -12,13 +12,13 @@ config: ...@@ -12,13 +12,13 @@ config:
init: init:
expect: expect:
pipeline: created pipeline: skipped
stages: stages:
test: skipped test: skipped
deploy: created deploy: skipped
jobs: jobs:
test: manual test: manual
deploy: created deploy: skipped
transitions: transitions:
- event: enqueue - event: enqueue
...@@ -27,10 +27,10 @@ transitions: ...@@ -27,10 +27,10 @@ transitions:
pipeline: pending pipeline: pending
stages: stages:
test: pending test: pending
deploy: created deploy: skipped
jobs: jobs:
test: pending test: pending
deploy: created deploy: skipped
- event: run - event: run
jobs: [test] jobs: [test]
...@@ -38,21 +38,18 @@ transitions: ...@@ -38,21 +38,18 @@ transitions:
pipeline: running pipeline: running
stages: stages:
test: running test: running
deploy: created deploy: skipped
jobs: jobs:
test: running test: running
deploy: created deploy: skipped
- event: drop - event: drop
jobs: [test] jobs: [test]
expect: expect:
pipeline: running pipeline: success
stages: stages:
test: success test: success
deploy: pending deploy: skipped
jobs: jobs:
test: failed test: failed
deploy: pending deploy: skipped
# TOOD: should we run deploy?
# Further discussions: https://gitlab.com/gitlab-org/gitlab/-/issues/213080
...@@ -13,15 +13,12 @@ config: ...@@ -13,15 +13,12 @@ config:
init: init:
expect: expect:
pipeline: created pipeline: pending
stages: stages:
test: skipped test: skipped
deploy: created deploy: pending
jobs: jobs:
test: manual test: manual
deploy: created deploy: pending
transitions: [] transitions: []
# TODO: should we run `deploy`?
# Further discussions: https://gitlab.com/gitlab-org/gitlab/-/issues/213080
...@@ -13,13 +13,13 @@ config: ...@@ -13,13 +13,13 @@ config:
init: init:
expect: expect:
pipeline: created pipeline: skipped
stages: stages:
test: skipped test: skipped
deploy: created deploy: skipped
jobs: jobs:
test: manual test: manual
deploy: created deploy: skipped
transitions: transitions:
- event: enqueue - event: enqueue
...@@ -28,10 +28,10 @@ transitions: ...@@ -28,10 +28,10 @@ transitions:
pipeline: pending pipeline: pending
stages: stages:
test: pending test: pending
deploy: created deploy: skipped
jobs: jobs:
test: pending test: pending
deploy: created deploy: skipped
- event: drop - event: drop
jobs: [test] jobs: [test]
...@@ -43,6 +43,3 @@ transitions: ...@@ -43,6 +43,3 @@ transitions:
jobs: jobs:
test: failed test: failed
deploy: skipped deploy: skipped
# TODO: should we run `deploy`?
# Further discussions: https://gitlab.com/gitlab-org/gitlab/-/issues/213080
...@@ -19,24 +19,21 @@ init: ...@@ -19,24 +19,21 @@ init:
pipeline: pending pipeline: pending
stages: stages:
test: pending test: pending
deploy: created deploy: skipped
jobs: jobs:
test1: pending test1: pending
test2: manual test2: manual
deploy: created deploy: skipped
transitions: transitions:
- event: success - event: success
jobs: [test1] jobs: [test1]
expect: expect:
pipeline: running pipeline: success
stages: stages:
test: success test: success
deploy: created deploy: skipped
jobs: jobs:
test1: success test1: success
test2: manual test2: manual
deploy: created deploy: skipped
# TODO: should deploy run?
# Further discussions: https://gitlab.com/gitlab-org/gitlab/-/issues/213080
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