1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
|
# frozen_string_literal: true
module Gitlab
module Ci
class Config
module Entry
##
# This class represents a global entry - root Entry for entire
# GitLab CI Configuration file.
#
class Root < ::Gitlab::Config::Entry::Node
include ::Gitlab::Config::Entry::Configurable
ALLOWED_KEYS = %i[default include before_script image services
after_script variables stages types cache workflow].freeze
validations do
validates :config, allowed_keys: ALLOWED_KEYS
end
# reserved:
# defines whether the node name is reserved
# the reserved name cannot be used a job name
# reserved should not be used as it will make
# breaking change to `.gitlab-ci.yml`
entry :default, Entry::Default,
description: 'Default configuration for all jobs.',
default: {}
entry :include, Entry::Includes,
description: 'List of external YAML files to include.',
reserved: true
entry :before_script, Entry::Commands,
description: 'Script that will be executed before each job.',
reserved: true
entry :image, Entry::Image,
description: 'Docker image that will be used to execute jobs.',
reserved: true
entry :services, Entry::Services,
description: 'Docker images that will be linked to the container.',
reserved: true
entry :after_script, Entry::Commands,
description: 'Script that will be executed after each job.',
reserved: true
entry :variables, Entry::Variables,
description: 'Environment variables that will be used.',
metadata: { use_value_data: true },
reserved: true
entry :stages, Entry::Stages,
description: 'Configuration of stages for this pipeline.',
reserved: true
entry :types, Entry::Stages,
description: 'Deprecated: stages for this pipeline.',
reserved: true,
deprecation: { deprecated: '9.0', warning: '14.8', removed: '15.0' }
entry :cache, Entry::Caches,
description: 'Configure caching between build jobs.',
reserved: true
entry :workflow, Entry::Workflow,
description: 'List of evaluable rules to determine Pipeline status',
default: {}
dynamic_helpers :jobs
delegate :before_script_value,
:image_value,
:services_value,
:after_script_value,
:cache_value, to: :default_entry
attr_reader :jobs_config
class << self
include ::Gitlab::Utils::StrongMemoize
def reserved_nodes_names
strong_memoize(:reserved_nodes_names) do
self.nodes.select do |_, node|
node.reserved?
end.keys
end
end
end
def initialize(config, **metadata)
super do
filter_jobs!
end
end
def compose!(_deps = nil)
super(self) do
compose_deprecated_entries!
compose_jobs!
end
end
private
# rubocop: disable CodeReuse/ActiveRecord
def compose_jobs!
factory = ::Gitlab::Config::Entry::Factory.new(Entry::Jobs)
.value(jobs_config)
.with(key: :jobs, parent: self,
description: 'Jobs definition for this pipeline')
@entries[:jobs] = factory.create!
end
# rubocop: enable CodeReuse/ActiveRecord
def compose_deprecated_entries!
##
# Deprecated `:types` key workaround - if types are defined and
# stages are not defined we use types definition as stages.
# This keyword will be removed in 15.0:
# https://gitlab.com/gitlab-org/gitlab/-/issues/346823
#
if types_defined?
@entries[:stages] = @entries[:types] unless stages_defined?
log_and_warn_deprecated_entry(@entries[:types])
end
@entries.delete(:types)
end
def filter_jobs!
return unless @config.is_a?(Hash)
@jobs_config = @config
.except(*self.class.reserved_nodes_names)
.select do |name, config|
Entry::Jobs.find_type(name, config).present? || ALLOWED_KEYS.exclude?(name)
end
@config = @config.except(*@jobs_config.keys)
end
end
end
end
end
end
|