gitlab-ci-yaml_lint 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +12 -0
- data/.rspec +3 -0
- data/.travis.yml +5 -0
- data/Gemfile +8 -0
- data/LICENSE +20 -0
- data/README.md +50 -0
- data/Rakefile +6 -0
- data/bin/gitlab-ci-yaml_lint +13 -0
- data/gitlab-ci-yaml_lint.gemspec +31 -0
- data/gitlab_lib/LICENSE +27 -0
- data/gitlab_lib/gitlab/ci/config.rb +62 -0
- data/gitlab_lib/gitlab/ci/config/entry/artifacts.rb +35 -0
- data/gitlab_lib/gitlab/ci/config/entry/attributable.rb +27 -0
- data/gitlab_lib/gitlab/ci/config/entry/boolean.rb +18 -0
- data/gitlab_lib/gitlab/ci/config/entry/cache.rb +45 -0
- data/gitlab_lib/gitlab/ci/config/entry/commands.rb +33 -0
- data/gitlab_lib/gitlab/ci/config/entry/configurable.rb +77 -0
- data/gitlab_lib/gitlab/ci/config/entry/coverage.rb +22 -0
- data/gitlab_lib/gitlab/ci/config/entry/environment.rb +83 -0
- data/gitlab_lib/gitlab/ci/config/entry/factory.rb +73 -0
- data/gitlab_lib/gitlab/ci/config/entry/global.rb +72 -0
- data/gitlab_lib/gitlab/ci/config/entry/hidden.rb +22 -0
- data/gitlab_lib/gitlab/ci/config/entry/image.rb +47 -0
- data/gitlab_lib/gitlab/ci/config/entry/job.rb +157 -0
- data/gitlab_lib/gitlab/ci/config/entry/jobs.rb +52 -0
- data/gitlab_lib/gitlab/ci/config/entry/key.rb +22 -0
- data/gitlab_lib/gitlab/ci/config/entry/legacy_validation_helpers.rb +61 -0
- data/gitlab_lib/gitlab/ci/config/entry/node.rb +101 -0
- data/gitlab_lib/gitlab/ci/config/entry/paths.rb +18 -0
- data/gitlab_lib/gitlab/ci/config/entry/policy.rb +53 -0
- data/gitlab_lib/gitlab/ci/config/entry/script.rb +18 -0
- data/gitlab_lib/gitlab/ci/config/entry/service.rb +34 -0
- data/gitlab_lib/gitlab/ci/config/entry/services.rb +41 -0
- data/gitlab_lib/gitlab/ci/config/entry/simplifiable.rb +43 -0
- data/gitlab_lib/gitlab/ci/config/entry/stage.rb +22 -0
- data/gitlab_lib/gitlab/ci/config/entry/stages.rb +22 -0
- data/gitlab_lib/gitlab/ci/config/entry/undefined.rb +40 -0
- data/gitlab_lib/gitlab/ci/config/entry/unspecified.rb +19 -0
- data/gitlab_lib/gitlab/ci/config/entry/validatable.rb +38 -0
- data/gitlab_lib/gitlab/ci/config/entry/validator.rb +26 -0
- data/gitlab_lib/gitlab/ci/config/entry/validators.rb +144 -0
- data/gitlab_lib/gitlab/ci/config/entry/variables.rb +26 -0
- data/gitlab_lib/gitlab/ci/config/loader.rb +25 -0
- data/gitlab_lib/gitlab/ci/yaml_processor.rb +189 -0
- data/lib/gitlab/ci/yaml_lint.rb +73 -0
- data/lib/gitlab/ci/yaml_lint/rake/tasks.rb +28 -0
- data/lib/gitlab/ci/yaml_lint/version.rb +7 -0
- metadata +203 -0
@@ -0,0 +1,22 @@
|
|
1
|
+
module Gitlab
|
2
|
+
module Ci
|
3
|
+
class Config
|
4
|
+
module Entry
|
5
|
+
##
|
6
|
+
# Entry that represents a stage for a job.
|
7
|
+
#
|
8
|
+
class Stage < Node
|
9
|
+
include Validatable
|
10
|
+
|
11
|
+
validations do
|
12
|
+
validates :config, type: String
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.default
|
16
|
+
'test'
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Gitlab
|
2
|
+
module Ci
|
3
|
+
class Config
|
4
|
+
module Entry
|
5
|
+
##
|
6
|
+
# Entry that represents a configuration for pipeline stages.
|
7
|
+
#
|
8
|
+
class Stages < Node
|
9
|
+
include Validatable
|
10
|
+
|
11
|
+
validations do
|
12
|
+
validates :config, array_of_strings: true
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.default
|
16
|
+
%w[build test deploy]
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module Gitlab
|
2
|
+
module Ci
|
3
|
+
class Config
|
4
|
+
module Entry
|
5
|
+
##
|
6
|
+
# This class represents an undefined entry.
|
7
|
+
#
|
8
|
+
class Undefined < Node
|
9
|
+
def initialize(*)
|
10
|
+
super(nil)
|
11
|
+
end
|
12
|
+
|
13
|
+
def value
|
14
|
+
nil
|
15
|
+
end
|
16
|
+
|
17
|
+
def valid?
|
18
|
+
true
|
19
|
+
end
|
20
|
+
|
21
|
+
def errors
|
22
|
+
[]
|
23
|
+
end
|
24
|
+
|
25
|
+
def specified?
|
26
|
+
false
|
27
|
+
end
|
28
|
+
|
29
|
+
def relevant?
|
30
|
+
false
|
31
|
+
end
|
32
|
+
|
33
|
+
def inspect
|
34
|
+
"#<#{self.class.name}>"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Gitlab
|
2
|
+
module Ci
|
3
|
+
class Config
|
4
|
+
module Entry
|
5
|
+
##
|
6
|
+
# This class represents an unspecified entry.
|
7
|
+
#
|
8
|
+
# It decorates original entry adding method that indicates it is
|
9
|
+
# unspecified.
|
10
|
+
#
|
11
|
+
class Unspecified < SimpleDelegator
|
12
|
+
def specified?
|
13
|
+
false
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module Gitlab
|
2
|
+
module Ci
|
3
|
+
class Config
|
4
|
+
module Entry
|
5
|
+
module Validatable
|
6
|
+
extend ActiveSupport::Concern
|
7
|
+
|
8
|
+
def self.included(node)
|
9
|
+
node.aspects.append -> do
|
10
|
+
@validator = self.class.validator.new(self)
|
11
|
+
@validator.validate(:new)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def errors
|
16
|
+
@validator.messages + descendants.flat_map(&:errors) # rubocop:disable Gitlab/ModuleWithInstanceVariables
|
17
|
+
end
|
18
|
+
|
19
|
+
class_methods do
|
20
|
+
def validator
|
21
|
+
@validator ||= Class.new(Entry::Validator).tap do |validator|
|
22
|
+
if defined?(@validations)
|
23
|
+
@validations.each { |rules| validator.class_eval(&rules) }
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def validations(&block)
|
31
|
+
(@validations ||= []).append(block)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Gitlab
|
2
|
+
module Ci
|
3
|
+
class Config
|
4
|
+
module Entry
|
5
|
+
class Validator < SimpleDelegator
|
6
|
+
include ActiveModel::Validations
|
7
|
+
include Entry::Validators
|
8
|
+
|
9
|
+
def initialize(entry)
|
10
|
+
super(entry)
|
11
|
+
end
|
12
|
+
|
13
|
+
def messages
|
14
|
+
errors.full_messages.map do |error|
|
15
|
+
"#{location} #{error}".downcase
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.name
|
20
|
+
'Validator'
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,144 @@
|
|
1
|
+
module Gitlab
|
2
|
+
module Ci
|
3
|
+
class Config
|
4
|
+
module Entry
|
5
|
+
module Validators
|
6
|
+
class AllowedKeysValidator < ActiveModel::EachValidator
|
7
|
+
def validate_each(record, attribute, value)
|
8
|
+
unknown_keys = record.config.try(:keys).to_a - options[:in]
|
9
|
+
|
10
|
+
if unknown_keys.any?
|
11
|
+
record.errors.add(:config, 'contains unknown keys: ' +
|
12
|
+
unknown_keys.join(', '))
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
class AllowedValuesValidator < ActiveModel::EachValidator
|
18
|
+
def validate_each(record, attribute, value)
|
19
|
+
unless options[:in].include?(value.to_s)
|
20
|
+
record.errors.add(attribute, "unknown value: #{value}")
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
class ArrayOfStringsValidator < ActiveModel::EachValidator
|
26
|
+
include LegacyValidationHelpers
|
27
|
+
|
28
|
+
def validate_each(record, attribute, value)
|
29
|
+
unless validate_array_of_strings(value)
|
30
|
+
record.errors.add(attribute, 'should be an array of strings')
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
class BooleanValidator < ActiveModel::EachValidator
|
36
|
+
include LegacyValidationHelpers
|
37
|
+
|
38
|
+
def validate_each(record, attribute, value)
|
39
|
+
unless validate_boolean(value)
|
40
|
+
record.errors.add(attribute, 'should be a boolean value')
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
class DurationValidator < ActiveModel::EachValidator
|
46
|
+
include LegacyValidationHelpers
|
47
|
+
|
48
|
+
def validate_each(record, attribute, value)
|
49
|
+
unless validate_duration(value)
|
50
|
+
record.errors.add(attribute, 'should be a duration')
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
class HashOrStringValidator < ActiveModel::EachValidator
|
56
|
+
def validate_each(record, attribute, value)
|
57
|
+
unless value.is_a?(Hash) || value.is_a?(String)
|
58
|
+
record.errors.add(attribute, 'should be a hash or a string')
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
class KeyValidator < ActiveModel::EachValidator
|
64
|
+
include LegacyValidationHelpers
|
65
|
+
|
66
|
+
def validate_each(record, attribute, value)
|
67
|
+
unless validate_string(value)
|
68
|
+
record.errors.add(attribute, 'should be a string or symbol')
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
class RegexpValidator < ActiveModel::EachValidator
|
74
|
+
include LegacyValidationHelpers
|
75
|
+
|
76
|
+
def validate_each(record, attribute, value)
|
77
|
+
unless validate_regexp(value)
|
78
|
+
record.errors.add(attribute, 'must be a regular expression')
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
private
|
83
|
+
|
84
|
+
def look_like_regexp?(value)
|
85
|
+
value.is_a?(String) && value.start_with?('/') &&
|
86
|
+
value.end_with?('/')
|
87
|
+
end
|
88
|
+
|
89
|
+
def validate_regexp(value)
|
90
|
+
look_like_regexp?(value) &&
|
91
|
+
Regexp.new(value.to_s[1...-1]) &&
|
92
|
+
true
|
93
|
+
rescue RegexpError
|
94
|
+
false
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
class ArrayOfStringsOrRegexpsValidator < RegexpValidator
|
99
|
+
def validate_each(record, attribute, value)
|
100
|
+
unless validate_array_of_strings_or_regexps(value)
|
101
|
+
record.errors.add(attribute, 'should be an array of strings or regexps')
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
private
|
106
|
+
|
107
|
+
def validate_array_of_strings_or_regexps(values)
|
108
|
+
values.is_a?(Array) && values.all?(&method(:validate_string_or_regexp))
|
109
|
+
end
|
110
|
+
|
111
|
+
def validate_string_or_regexp(value)
|
112
|
+
return false unless value.is_a?(String)
|
113
|
+
return validate_regexp(value) if look_like_regexp?(value)
|
114
|
+
|
115
|
+
true
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
class TypeValidator < ActiveModel::EachValidator
|
120
|
+
def validate_each(record, attribute, value)
|
121
|
+
type = options[:with]
|
122
|
+
raise unless type.is_a?(Class)
|
123
|
+
|
124
|
+
unless value.is_a?(type)
|
125
|
+
message = options[:message] || "should be a #{type.name}"
|
126
|
+
record.errors.add(attribute, message)
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
class VariablesValidator < ActiveModel::EachValidator
|
132
|
+
include LegacyValidationHelpers
|
133
|
+
|
134
|
+
def validate_each(record, attribute, value)
|
135
|
+
unless validate_variables(value)
|
136
|
+
record.errors.add(attribute, 'should be a hash of key value pairs')
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Gitlab
|
2
|
+
module Ci
|
3
|
+
class Config
|
4
|
+
module Entry
|
5
|
+
##
|
6
|
+
# Entry that represents environment variables.
|
7
|
+
#
|
8
|
+
class Variables < Node
|
9
|
+
include Validatable
|
10
|
+
|
11
|
+
validations do
|
12
|
+
validates :config, variables: true
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.default
|
16
|
+
{}
|
17
|
+
end
|
18
|
+
|
19
|
+
def value
|
20
|
+
Hash[@config.map { |key, value| [key.to_s, value.to_s] }]
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Gitlab
|
2
|
+
module Ci
|
3
|
+
class Config
|
4
|
+
class Loader
|
5
|
+
FormatError = Class.new(StandardError)
|
6
|
+
|
7
|
+
def initialize(config)
|
8
|
+
@config = YAML.safe_load(config, [Symbol], [], true)
|
9
|
+
end
|
10
|
+
|
11
|
+
def valid?
|
12
|
+
@config.is_a?(Hash)
|
13
|
+
end
|
14
|
+
|
15
|
+
def load!
|
16
|
+
unless valid?
|
17
|
+
raise FormatError, 'Invalid configuration format'
|
18
|
+
end
|
19
|
+
|
20
|
+
@config.deep_symbolize_keys
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,189 @@
|
|
1
|
+
module Gitlab
|
2
|
+
module Ci
|
3
|
+
class YamlProcessor
|
4
|
+
ValidationError = Class.new(StandardError)
|
5
|
+
|
6
|
+
include Gitlab::Ci::Config::Entry::LegacyValidationHelpers
|
7
|
+
|
8
|
+
attr_reader :cache, :stages, :jobs
|
9
|
+
|
10
|
+
def initialize(config)
|
11
|
+
@ci_config = Gitlab::Ci::Config.new(config)
|
12
|
+
@config = @ci_config.to_hash
|
13
|
+
|
14
|
+
unless @ci_config.valid?
|
15
|
+
raise ValidationError, @ci_config.errors.first
|
16
|
+
end
|
17
|
+
|
18
|
+
initial_parsing
|
19
|
+
rescue Gitlab::Ci::Config::Loader::FormatError => e
|
20
|
+
raise ValidationError, e.message
|
21
|
+
end
|
22
|
+
|
23
|
+
def builds
|
24
|
+
@jobs.map do |name, _|
|
25
|
+
build_attributes(name)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def build_attributes(name)
|
30
|
+
job = @jobs[name.to_sym] || {}
|
31
|
+
|
32
|
+
{ stage_idx: @stages.index(job[:stage]),
|
33
|
+
stage: job[:stage],
|
34
|
+
commands: job[:commands],
|
35
|
+
tag_list: job[:tags] || [],
|
36
|
+
name: job[:name].to_s,
|
37
|
+
allow_failure: job[:ignore],
|
38
|
+
when: job[:when] || 'on_success',
|
39
|
+
environment: job[:environment_name],
|
40
|
+
coverage_regex: job[:coverage],
|
41
|
+
yaml_variables: yaml_variables(name),
|
42
|
+
options: {
|
43
|
+
image: job[:image],
|
44
|
+
services: job[:services],
|
45
|
+
artifacts: job[:artifacts],
|
46
|
+
cache: job[:cache],
|
47
|
+
dependencies: job[:dependencies],
|
48
|
+
before_script: job[:before_script],
|
49
|
+
script: job[:script],
|
50
|
+
after_script: job[:after_script],
|
51
|
+
environment: job[:environment],
|
52
|
+
retry: job[:retry]
|
53
|
+
}.compact }
|
54
|
+
end
|
55
|
+
|
56
|
+
def pipeline_stage_builds(stage, pipeline)
|
57
|
+
selected_jobs = @jobs.select do |_, job|
|
58
|
+
next unless job[:stage] == stage
|
59
|
+
|
60
|
+
only_specs = Gitlab::Ci::Build::Policy
|
61
|
+
.fabricate(job.fetch(:only, {}))
|
62
|
+
except_specs = Gitlab::Ci::Build::Policy
|
63
|
+
.fabricate(job.fetch(:except, {}))
|
64
|
+
|
65
|
+
only_specs.all? { |spec| spec.satisfied_by?(pipeline) } &&
|
66
|
+
except_specs.none? { |spec| spec.satisfied_by?(pipeline) }
|
67
|
+
end
|
68
|
+
|
69
|
+
selected_jobs.map { |_, job| build_attributes(job[:name]) }
|
70
|
+
end
|
71
|
+
|
72
|
+
def stage_seeds(pipeline)
|
73
|
+
seeds = @stages.uniq.map do |stage|
|
74
|
+
builds = pipeline_stage_builds(stage, pipeline)
|
75
|
+
|
76
|
+
Gitlab::Ci::Stage::Seed.new(pipeline, stage, builds) if builds.any?
|
77
|
+
end
|
78
|
+
|
79
|
+
seeds.compact
|
80
|
+
end
|
81
|
+
|
82
|
+
def self.validation_message(content)
|
83
|
+
return 'Please provide content of .gitlab-ci.yml' if content.blank?
|
84
|
+
|
85
|
+
begin
|
86
|
+
Gitlab::Ci::YamlProcessor.new(content)
|
87
|
+
nil
|
88
|
+
rescue ValidationError, Psych::SyntaxError => e
|
89
|
+
e.message
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
private
|
94
|
+
|
95
|
+
def initial_parsing
|
96
|
+
##
|
97
|
+
# Global config
|
98
|
+
#
|
99
|
+
@before_script = @ci_config.before_script
|
100
|
+
@image = @ci_config.image
|
101
|
+
@after_script = @ci_config.after_script
|
102
|
+
@services = @ci_config.services
|
103
|
+
@variables = @ci_config.variables
|
104
|
+
@stages = @ci_config.stages
|
105
|
+
@cache = @ci_config.cache
|
106
|
+
|
107
|
+
##
|
108
|
+
# Jobs
|
109
|
+
#
|
110
|
+
@jobs = @ci_config.jobs
|
111
|
+
|
112
|
+
@jobs.each do |name, job|
|
113
|
+
# logical validation for job
|
114
|
+
|
115
|
+
validate_job_stage!(name, job)
|
116
|
+
validate_job_dependencies!(name, job)
|
117
|
+
validate_job_environment!(name, job)
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
def yaml_variables(name)
|
122
|
+
variables = (@variables || {})
|
123
|
+
.merge(job_variables(name))
|
124
|
+
|
125
|
+
variables.map do |key, value|
|
126
|
+
{ key: key.to_s, value: value, public: true }
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
def job_variables(name)
|
131
|
+
job = @jobs[name.to_sym]
|
132
|
+
return {} unless job
|
133
|
+
|
134
|
+
job[:variables] || {}
|
135
|
+
end
|
136
|
+
|
137
|
+
def validate_job_stage!(name, job)
|
138
|
+
return unless job[:stage]
|
139
|
+
|
140
|
+
unless job[:stage].is_a?(String) && job[:stage].in?(@stages)
|
141
|
+
raise ValidationError, "#{name} job: stage parameter should be #{@stages.join(", ")}"
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
def validate_job_dependencies!(name, job)
|
146
|
+
return unless job[:dependencies]
|
147
|
+
|
148
|
+
stage_index = @stages.index(job[:stage])
|
149
|
+
|
150
|
+
job[:dependencies].each do |dependency|
|
151
|
+
raise ValidationError, "#{name} job: undefined dependency: #{dependency}" unless @jobs[dependency.to_sym]
|
152
|
+
|
153
|
+
unless @stages.index(@jobs[dependency.to_sym][:stage]) < stage_index
|
154
|
+
raise ValidationError, "#{name} job: dependency #{dependency} is not defined in prior stages"
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
def validate_job_environment!(name, job)
|
160
|
+
return unless job[:environment]
|
161
|
+
return unless job[:environment].is_a?(Hash)
|
162
|
+
|
163
|
+
environment = job[:environment]
|
164
|
+
validate_on_stop_job!(name, environment, environment[:on_stop])
|
165
|
+
end
|
166
|
+
|
167
|
+
def validate_on_stop_job!(name, environment, on_stop)
|
168
|
+
return unless on_stop
|
169
|
+
|
170
|
+
on_stop_job = @jobs[on_stop.to_sym]
|
171
|
+
unless on_stop_job
|
172
|
+
raise ValidationError, "#{name} job: on_stop job #{on_stop} is not defined"
|
173
|
+
end
|
174
|
+
|
175
|
+
unless on_stop_job[:environment]
|
176
|
+
raise ValidationError, "#{name} job: on_stop job #{on_stop} does not have environment defined"
|
177
|
+
end
|
178
|
+
|
179
|
+
unless on_stop_job[:environment][:name] == environment[:name]
|
180
|
+
raise ValidationError, "#{name} job: on_stop job #{on_stop} have different environment name"
|
181
|
+
end
|
182
|
+
|
183
|
+
unless on_stop_job[:environment][:action] == 'stop'
|
184
|
+
raise ValidationError, "#{name} job: on_stop job #{on_stop} needs to have action stop defined"
|
185
|
+
end
|
186
|
+
end
|
187
|
+
end
|
188
|
+
end
|
189
|
+
end
|