debian-mirror-gitlab/lib/gitlab/ci/status/composite.rb

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

144 lines
4.8 KiB
Ruby
Raw Normal View History

2019-12-21 20:55:43 +05:30
# frozen_string_literal: true
module Gitlab
module Ci
module Status
class Composite
include Gitlab::Utils::StrongMemoize
# This class accepts an array of arrays/hashes/or objects
2023-05-27 22:25:52 +05:30
# `with_allow_failure` will be removed when deleting ci_remove_ensure_stage_service
2023-06-20 00:43:36 +05:30
def initialize(all_jobs, with_allow_failure: true, dag: false, project: nil)
unless all_jobs.respond_to?(:pluck)
raise ArgumentError, "all_jobs needs to respond to `.pluck`"
2019-12-21 20:55:43 +05:30
end
@status_set = Set.new
@status_key = 0
@allow_failure_key = 1 if with_allow_failure
2020-11-24 15:15:51 +05:30
@dag = dag
2023-06-20 00:43:36 +05:30
@project = project
2019-12-21 20:55:43 +05:30
2023-06-20 00:43:36 +05:30
consume_all_jobs(all_jobs)
2019-12-21 20:55:43 +05:30
end
# The status calculation is order dependent,
# 1. In some cases we assume that that status is exact
# if the we only have given statues,
# 2. In other cases we assume that status is of that type
# based on what statuses are no longer valid based on the
# data set that we have
2023-05-27 22:25:52 +05:30
#
2023-06-20 00:43:36 +05:30
# This method is used for three cases:
# 1. When it is called for a stage or a pipeline (with `all_jobs` from all jobs in a stage or a pipeline),
2023-05-27 22:25:52 +05:30
# then, the returned status is assigned to the stage or pipeline.
2023-06-20 00:43:36 +05:30
# 2. When it is called for a job (with `all_jobs` from all previous jobs or all needed jobs),
2023-05-27 22:25:52 +05:30
# then, the returned status is used to determine if the job is processed or not.
2023-06-20 00:43:36 +05:30
# 3. When it is called for a group (of jobs that are related),
# then, the returned status is used to show the overall status of the group.
2020-03-13 15:44:24 +05:30
# rubocop: disable Metrics/CyclomaticComplexity
# rubocop: disable Metrics/PerceivedComplexity
2019-12-21 20:55:43 +05:30
def status
return if none?
strong_memoize(:status) do
2021-04-17 20:07:23 +05:30
if @dag && any_skipped_or_ignored?
2020-11-24 15:15:51 +05:30
# The DAG job is skipped if one of the needs does not run at all.
'skipped'
elsif only_of?(:skipped, :ignored)
2019-12-21 20:55:43 +05:30
'skipped'
elsif only_of?(:success, :skipped, :success_with_warnings, :ignored)
'success'
elsif only_of?(:created, :success_with_warnings, :ignored)
'created'
elsif only_of?(:preparing, :success_with_warnings, :ignored)
'preparing'
elsif only_of?(:canceled, :success, :skipped, :success_with_warnings, :ignored)
'canceled'
elsif only_of?(:pending, :created, :skipped, :success_with_warnings, :ignored)
'pending'
elsif any_of?(:running, :pending)
'running'
2020-03-13 15:44:24 +05:30
elsif any_of?(:waiting_for_resource)
'waiting_for_resource'
2019-12-21 20:55:43 +05:30
elsif any_of?(:manual)
'manual'
elsif any_of?(:scheduled)
'scheduled'
elsif any_of?(:preparing)
'preparing'
elsif any_of?(:created)
'running'
else
'failed'
end
end
end
2020-03-13 15:44:24 +05:30
# rubocop: enable Metrics/CyclomaticComplexity
# rubocop: enable Metrics/PerceivedComplexity
2019-12-21 20:55:43 +05:30
def warnings?
@status_set.include?(:success_with_warnings)
end
private
def none?
@status_set.empty?
end
def any_of?(*names)
names.any? { |name| @status_set.include?(name) }
end
def only_of?(*names)
matching = names.count { |name| @status_set.include?(name) }
matching > 0 &&
matching == @status_set.size
end
2021-04-17 20:07:23 +05:30
def any_skipped_or_ignored?
2021-09-30 23:02:18 +05:30
any_of?(:skipped) || any_of?(:ignored)
2021-04-17 20:07:23 +05:30
end
2023-06-20 00:43:36 +05:30
def consume_all_jobs(all_jobs)
2019-12-21 20:55:43 +05:30
columns = []
columns[@status_key] = :status
columns[@allow_failure_key] = :allow_failure if @allow_failure_key
2023-06-20 00:43:36 +05:30
all_jobs
2019-12-21 20:55:43 +05:30
.pluck(*columns) # rubocop: disable CodeReuse/ActiveRecord
2023-06-20 00:43:36 +05:30
.each do |job_attrs|
consume_job_status(Array.wrap(job_attrs))
2023-05-27 22:25:52 +05:30
end
2019-12-21 20:55:43 +05:30
end
2023-06-20 00:43:36 +05:30
def consume_job_status(job_attrs)
2023-05-27 22:25:52 +05:30
status_result =
2023-06-20 00:43:36 +05:30
if success_with_warnings?(job_attrs)
2019-12-21 20:55:43 +05:30
:success_with_warnings
2023-06-20 00:43:36 +05:30
elsif ignored_status?(job_attrs)
2019-12-21 20:55:43 +05:30
:ignored
else
2023-06-20 00:43:36 +05:30
job_attrs[@status_key].to_sym
2019-12-21 20:55:43 +05:30
end
2023-05-27 22:25:52 +05:30
@status_set.add(status_result)
2019-12-21 20:55:43 +05:30
end
2023-06-20 00:43:36 +05:30
def success_with_warnings?(job_attrs)
2019-12-21 20:55:43 +05:30
@allow_failure_key &&
2023-06-20 00:43:36 +05:30
job_attrs[@allow_failure_key] &&
::Ci::HasStatus::PASSED_WITH_WARNINGS_STATUSES.include?(job_attrs[@status_key])
2019-12-21 20:55:43 +05:30
end
2023-06-20 00:43:36 +05:30
def ignored_status?(job_attrs)
2019-12-21 20:55:43 +05:30
@allow_failure_key &&
2023-06-20 00:43:36 +05:30
job_attrs[@allow_failure_key] &&
::Ci::HasStatus::IGNORED_STATUSES.include?(job_attrs[@status_key])
2019-12-21 20:55:43 +05:30
end
end
end
end
end