153 lines
5.1 KiB
Ruby
153 lines
5.1 KiB
Ruby
|
# frozen_string_literal: true
|
||
|
|
||
|
module Gitlab
|
||
|
module Ci
|
||
|
class Config
|
||
|
module Entry
|
||
|
##
|
||
|
# Entry that represents a CI/CD Bridge job that is responsible for
|
||
|
# defining a downstream project trigger.
|
||
|
#
|
||
|
class Bridge < ::Gitlab::Config::Entry::Node
|
||
|
include ::Gitlab::Config::Entry::Configurable
|
||
|
include ::Gitlab::Config::Entry::Attributable
|
||
|
include ::Gitlab::Config::Entry::Inheritable
|
||
|
|
||
|
ALLOWED_KEYS = %i[trigger stage allow_failure only except
|
||
|
when extends variables needs rules].freeze
|
||
|
|
||
|
validations do
|
||
|
validates :config, allowed_keys: ALLOWED_KEYS
|
||
|
validates :config, presence: true
|
||
|
validates :name, presence: true
|
||
|
validates :name, type: Symbol
|
||
|
validates :config, disallowed_keys: {
|
||
|
in: %i[only except when start_in],
|
||
|
message: 'key may not be used with `rules`'
|
||
|
},
|
||
|
if: :has_rules?
|
||
|
|
||
|
with_options allow_nil: true do
|
||
|
validates :when,
|
||
|
inclusion: { in: %w[on_success on_failure always],
|
||
|
message: 'should be on_success, on_failure or always' }
|
||
|
validates :extends, type: String
|
||
|
validates :rules, array_of_hashes: true
|
||
|
end
|
||
|
|
||
|
validate on: :composed do
|
||
|
unless trigger.present? || bridge_needs.present?
|
||
|
errors.add(:config, 'should contain either a trigger or a needs:pipeline')
|
||
|
end
|
||
|
end
|
||
|
|
||
|
validate on: :composed do
|
||
|
next unless bridge_needs.present?
|
||
|
next if bridge_needs.one?
|
||
|
|
||
|
errors.add(:config, 'should contain at most one bridge need')
|
||
|
end
|
||
|
end
|
||
|
|
||
|
entry :trigger, ::Gitlab::Ci::Config::Entry::Trigger,
|
||
|
description: 'CI/CD Bridge downstream trigger definition.',
|
||
|
inherit: false
|
||
|
|
||
|
entry :needs, ::Gitlab::Ci::Config::Entry::Needs,
|
||
|
description: 'CI/CD Bridge needs dependency definition.',
|
||
|
inherit: false,
|
||
|
metadata: { allowed_needs: %i[job bridge] }
|
||
|
|
||
|
entry :stage, ::Gitlab::Ci::Config::Entry::Stage,
|
||
|
description: 'Pipeline stage this job will be executed into.',
|
||
|
inherit: false
|
||
|
|
||
|
entry :only, ::Gitlab::Ci::Config::Entry::Policy,
|
||
|
description: 'Refs policy this job will be executed for.',
|
||
|
default: ::Gitlab::Ci::Config::Entry::Policy::DEFAULT_ONLY,
|
||
|
inherit: false
|
||
|
|
||
|
entry :except, ::Gitlab::Ci::Config::Entry::Policy,
|
||
|
description: 'Refs policy this job will be executed for.',
|
||
|
inherit: false
|
||
|
|
||
|
entry :rules, ::Gitlab::Ci::Config::Entry::Rules,
|
||
|
description: 'List of evaluable Rules to determine job inclusion.',
|
||
|
inherit: false,
|
||
|
metadata: {
|
||
|
allowed_when: %w[on_success on_failure always never manual delayed].freeze
|
||
|
}
|
||
|
|
||
|
entry :variables, ::Gitlab::Ci::Config::Entry::Variables,
|
||
|
description: 'Environment variables available for this job.',
|
||
|
inherit: false
|
||
|
|
||
|
helpers(*ALLOWED_KEYS)
|
||
|
attributes(*ALLOWED_KEYS)
|
||
|
|
||
|
def self.matching?(name, config)
|
||
|
!name.to_s.start_with?('.') &&
|
||
|
config.is_a?(Hash) &&
|
||
|
(config.key?(:trigger) || config.key?(:needs))
|
||
|
end
|
||
|
|
||
|
def self.visible?
|
||
|
true
|
||
|
end
|
||
|
|
||
|
def compose!(deps = nil)
|
||
|
super do
|
||
|
has_workflow_rules = deps&.workflow&.has_rules?
|
||
|
|
||
|
# If workflow:rules: or rules: are used
|
||
|
# they are considered not compatible
|
||
|
# with `only/except` defaults
|
||
|
#
|
||
|
# Context: https://gitlab.com/gitlab-org/gitlab/merge_requests/21742
|
||
|
if has_rules? || has_workflow_rules
|
||
|
# Remove only/except defaults
|
||
|
# defaults are not considered as defined
|
||
|
@entries.delete(:only) unless only_defined?
|
||
|
@entries.delete(:except) unless except_defined?
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
def has_rules?
|
||
|
@config&.key?(:rules)
|
||
|
end
|
||
|
|
||
|
def name
|
||
|
@metadata[:name]
|
||
|
end
|
||
|
|
||
|
def value
|
||
|
{ name: name,
|
||
|
trigger: (trigger_value if trigger_defined?),
|
||
|
needs: (needs_value if needs_defined?),
|
||
|
ignore: !!allow_failure,
|
||
|
stage: stage_value,
|
||
|
when: when_value,
|
||
|
extends: extends_value,
|
||
|
variables: (variables_value if variables_defined?),
|
||
|
rules: (rules_value if has_rules?),
|
||
|
only: only_value,
|
||
|
except: except_value,
|
||
|
scheduling_type: needs_defined? && !bridge_needs ? :dag : :stage }.compact
|
||
|
end
|
||
|
|
||
|
def bridge_needs
|
||
|
needs_value[:bridge] if needs_value
|
||
|
end
|
||
|
|
||
|
private
|
||
|
|
||
|
def overwrite_entry(deps, key, current_entry)
|
||
|
deps.default[key] unless current_entry.specified?
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end
|