debian-mirror-gitlab/app/models/ci/bridge.rb

342 lines
8.4 KiB
Ruby
Raw Normal View History

2019-02-15 15:39:39 +05:30
# frozen_string_literal: true
module Ci
2020-03-13 15:44:24 +05:30
class Bridge < Ci::Processable
2019-07-07 11:18:12 +05:30
include Ci::Contextable
2020-03-13 15:44:24 +05:30
include Ci::Metadatable
2019-02-15 15:39:39 +05:30
include Importable
include AfterCommitQueue
2020-04-08 14:13:33 +05:30
include Ci::HasRef
2020-03-13 15:44:24 +05:30
InvalidBridgeTypeError = Class.new(StandardError)
2020-04-08 14:13:33 +05:30
InvalidTransitionError = Class.new(StandardError)
2019-02-15 15:39:39 +05:30
2022-05-07 20:08:51 +05:30
FORWARD_DEFAULTS = {
yaml_variables: true,
pipeline_variables: false
}.freeze
2019-02-15 15:39:39 +05:30
belongs_to :project
2019-03-02 22:35:43 +05:30
belongs_to :trigger_request
2023-03-04 22:38:38 +05:30
2020-06-23 00:09:42 +05:30
has_one :downstream_pipeline, through: :sourced_pipeline, source: :pipeline
2019-02-15 15:39:39 +05:30
validates :ref, presence: true
2020-03-13 15:44:24 +05:30
# rubocop:disable Cop/ActiveRecordSerialize
serialize :options
serialize :yaml_variables, ::Gitlab::Serializer::Ci::Variables
# rubocop:enable Cop/ActiveRecordSerialize
state_machine :status do
2021-03-11 19:13:27 +05:30
after_transition [:created, :manual, :waiting_for_resource] => :pending do |bridge|
2021-11-11 11:23:49 +05:30
next unless bridge.triggers_downstream_pipeline?
2020-03-13 15:44:24 +05:30
bridge.run_after_commit do
2021-11-18 22:05:49 +05:30
::Ci::CreateDownstreamPipelineWorker.perform_async(bridge.id)
2020-03-13 15:44:24 +05:30
end
end
2020-11-24 15:15:51 +05:30
event :pending do
transition all => :pending
end
2020-03-13 15:44:24 +05:30
event :manual do
transition all => :manual
end
event :scheduled do
transition all => :scheduled
end
2021-01-03 14:25:43 +05:30
event :actionize do
transition created: :manual
end
2020-03-13 15:44:24 +05:30
end
2022-07-16 23:28:13 +05:30
def retryable?
2023-04-23 21:23:45 +05:30
return false if failed? && (pipeline_loop_detected? || reached_max_descendant_pipelines_depth?)
super
2022-07-16 23:28:13 +05:30
end
2020-11-24 15:15:51 +05:30
def self.with_preloads
preload(
:metadata,
downstream_pipeline: [project: [:route, { namespace: :route }]],
project: [:namespace]
)
end
2022-07-16 23:28:13 +05:30
def self.clone_accessors
%i[pipeline project ref tag options name
2022-10-11 01:57:18 +05:30
allow_failure stage stage_idx
2022-07-16 23:28:13 +05:30
yaml_variables when description needs_attributes
2022-10-11 01:57:18 +05:30
scheduling_type ci_stage partition_id].freeze
2022-06-21 17:19:12 +05:30
end
2020-03-13 15:44:24 +05:30
def inherit_status_from_downstream!(pipeline)
case pipeline.status
when 'success'
2023-04-23 21:23:45 +05:30
success!
2020-03-13 15:44:24 +05:30
when 'failed', 'canceled', 'skipped'
2023-04-23 21:23:45 +05:30
drop!
2020-03-13 15:44:24 +05:30
else
false
end
end
2020-04-08 14:13:33 +05:30
def has_downstream_pipeline?
2023-03-17 16:20:25 +05:30
sourced_pipeline.present?
2020-04-08 14:13:33 +05:30
end
2020-03-13 15:44:24 +05:30
def downstream_pipeline_params
return child_params if triggers_child_pipeline?
return cross_project_params if downstream_project.present?
{}
end
def downstream_project
strong_memoize(:downstream_project) do
if downstream_project_path
::Project.find_by_full_path(downstream_project_path)
elsif triggers_child_pipeline?
project
end
end
end
def downstream_project_path
strong_memoize(:downstream_project_path) do
2022-08-27 11:52:29 +05:30
project = options&.dig(:trigger, :project)
next unless project
scoped_variables.to_runner_variables.yield_self do |all_variables|
::ExpandVariables.expand(project, all_variables)
end
2020-03-13 15:44:24 +05:30
end
end
2020-04-08 14:13:33 +05:30
def parent_pipeline
pipeline if triggers_child_pipeline?
end
2021-11-11 11:23:49 +05:30
def triggers_downstream_pipeline?
triggers_child_pipeline? || triggers_cross_project_pipeline?
end
2020-03-13 15:44:24 +05:30
def triggers_child_pipeline?
yaml_for_downstream.present?
end
2021-11-11 11:23:49 +05:30
def triggers_cross_project_pipeline?
downstream_project_path.present?
end
2019-02-15 15:39:39 +05:30
def tags
[:bridge]
end
def detailed_status(current_user)
Gitlab::Ci::Status::Bridge::Factory
.new(self, current_user)
.fabricate!
end
2019-03-02 22:35:43 +05:30
def schedulable?
false
end
2021-01-03 14:25:43 +05:30
def playable?
action? && !archived? && manual?
end
2019-03-02 22:35:43 +05:30
def action?
2021-01-03 14:25:43 +05:30
%w[manual].include?(self.when)
end
# rubocop: disable CodeReuse/ServiceClass
# We don't need it but we are taking `job_variables_attributes` parameter
# to make it consistent with `Ci::Build#play` method.
def play(current_user, job_variables_attributes = nil)
Ci::PlayBridgeService
.new(project, current_user)
.execute(self)
2019-03-02 22:35:43 +05:30
end
2021-01-03 14:25:43 +05:30
# rubocop: enable CodeReuse/ServiceClass
2019-03-02 22:35:43 +05:30
def artifacts?
false
end
2019-07-07 11:18:12 +05:30
def runnable?
false
2019-03-02 22:35:43 +05:30
end
2021-03-11 19:13:27 +05:30
def any_unmet_prerequisites?
false
end
2023-01-13 00:05:48 +05:30
def outdated_deployment?
2022-10-11 01:57:18 +05:30
false
end
2019-07-07 11:18:12 +05:30
def expanded_environment_name
2019-02-15 15:39:39 +05:30
end
2021-09-04 01:27:46 +05:30
def persisted_environment
2021-06-08 01:23:25 +05:30
end
2023-04-23 21:23:45 +05:30
def deployment_job?
false
end
2019-02-15 15:39:39 +05:30
def execute_hooks
raise NotImplementedError
end
2019-03-02 22:35:43 +05:30
def to_partial_path
'projects/generic_commit_statuses/generic_commit_status'
end
2020-03-13 15:44:24 +05:30
def yaml_for_downstream
strong_memoize(:yaml_for_downstream) do
includes = options&.dig(:trigger, :include)
YAML.dump('include' => includes) if includes
end
end
def target_ref
branch = options&.dig(:trigger, :branch)
return unless branch
scoped_variables.to_runner_variables.yield_self do |all_variables|
::ExpandVariables.expand(branch, all_variables)
end
end
def dependent?
strong_memoize(:dependent) do
options&.dig(:trigger, :strategy) == 'depend'
end
end
def downstream_variables
2022-07-23 23:45:48 +05:30
calculate_downstream_variables
.reverse # variables priority
.uniq { |var| var[:key] } # only one variable key to pass
.reverse
2020-03-13 15:44:24 +05:30
end
2021-01-03 14:25:43 +05:30
def target_revision_ref
downstream_pipeline_params.dig(:target_revision, :ref)
end
2020-03-13 15:44:24 +05:30
private
def cross_project_params
{
project: downstream_project,
source: :pipeline,
target_revision: {
2021-03-08 18:12:59 +05:30
ref: target_ref || downstream_project.default_branch,
variables_attributes: downstream_variables
2020-03-13 15:44:24 +05:30
},
2020-04-08 14:13:33 +05:30
execute_params: {
ignore_skip_ci: true,
bridge: self
}
2020-03-13 15:44:24 +05:30
}
end
def child_params
parent_pipeline = pipeline
{
project: project,
source: :parent_pipeline,
target_revision: {
ref: parent_pipeline.ref,
checkout_sha: parent_pipeline.sha,
before: parent_pipeline.before_sha,
source_sha: parent_pipeline.source_sha,
2021-03-08 18:12:59 +05:30
target_sha: parent_pipeline.target_sha,
variables_attributes: downstream_variables
2020-03-13 15:44:24 +05:30
},
execute_params: {
ignore_skip_ci: true,
bridge: self,
merge_request: parent_pipeline.merge_request
}
}
end
2022-05-07 20:08:51 +05:30
def calculate_downstream_variables
expand_variables = scoped_variables
.concat(pipeline.persisted_variables)
.to_runner_variables
# The order of this list refers to the priority of the variables
downstream_yaml_variables(expand_variables) +
2022-06-21 17:19:12 +05:30
downstream_pipeline_variables(expand_variables) +
downstream_pipeline_schedule_variables(expand_variables)
2022-05-07 20:08:51 +05:30
end
def downstream_yaml_variables(expand_variables)
return [] unless forward_yaml_variables?
yaml_variables.to_a.map do |hash|
2023-03-17 16:20:25 +05:30
if hash[:raw]
2023-01-13 00:05:48 +05:30
{ key: hash[:key], value: hash[:value], raw: true }
else
{ key: hash[:key], value: ::ExpandVariables.expand(hash[:value], expand_variables) }
end
2022-05-07 20:08:51 +05:30
end
end
def downstream_pipeline_variables(expand_variables)
return [] unless forward_pipeline_variables?
pipeline.variables.to_a.map do |variable|
2023-03-17 16:20:25 +05:30
if variable.raw?
2023-01-13 00:05:48 +05:30
{ key: variable.key, value: variable.value, raw: true }
else
{ key: variable.key, value: ::ExpandVariables.expand(variable.value, expand_variables) }
end
2022-05-07 20:08:51 +05:30
end
end
2022-06-21 17:19:12 +05:30
def downstream_pipeline_schedule_variables(expand_variables)
return [] unless forward_pipeline_variables?
return [] unless pipeline.pipeline_schedule
pipeline.pipeline_schedule.variables.to_a.map do |variable|
2023-03-17 16:20:25 +05:30
if variable.raw?
2023-01-13 00:05:48 +05:30
{ key: variable.key, value: variable.value, raw: true }
else
{ key: variable.key, value: ::ExpandVariables.expand(variable.value, expand_variables) }
end
2022-06-21 17:19:12 +05:30
end
end
2022-05-07 20:08:51 +05:30
def forward_yaml_variables?
strong_memoize(:forward_yaml_variables) do
result = options&.dig(:trigger, :forward, :yaml_variables)
result.nil? ? FORWARD_DEFAULTS[:yaml_variables] : result
end
end
def forward_pipeline_variables?
strong_memoize(:forward_pipeline_variables) do
result = options&.dig(:trigger, :forward, :pipeline_variables)
result.nil? ? FORWARD_DEFAULTS[:pipeline_variables] : result
end
end
2019-02-15 15:39:39 +05:30
end
end
2019-12-04 20:38:33 +05:30
2021-06-08 01:23:25 +05:30
::Ci::Bridge.prepend_mod_with('Ci::Bridge')