Commit 121b4fc1 authored by Grzegorz Bizon's avatar Grzegorz Bizon

Detect circular dependenies in CI/CD `extends:` entry

parent 06c8c490
...@@ -6,6 +6,7 @@ module Gitlab ...@@ -6,6 +6,7 @@ module Gitlab
include Enumerable include Enumerable
ExtensionError = Class.new(StandardError) ExtensionError = Class.new(StandardError)
CircularDependencyError = Class.new(ExtensionError)
def initialize(hash) def initialize(hash)
@hash = hash @hash = hash
......
...@@ -5,9 +5,9 @@ module Gitlab ...@@ -5,9 +5,9 @@ module Gitlab
class Entry class Entry
attr_reader :key attr_reader :key
def initialize(key, hash, parent = nil) def initialize(key, context, parent = nil)
@key = key @key = key
@hash = hash @context = context
@parent = parent @parent = parent
end end
...@@ -16,12 +16,12 @@ module Gitlab ...@@ -16,12 +16,12 @@ module Gitlab
end end
def value def value
@value ||= @hash.fetch(@key) @value ||= @context.fetch(@key)
end end
def base def base
Extendable::Entry Extendable::Entry
.new(extends, @hash, self) .new(extends, @context, self)
.extend! .extend!
end end
...@@ -33,9 +33,17 @@ module Gitlab ...@@ -33,9 +33,17 @@ module Gitlab
value.fetch(:extends).to_sym value.fetch(:extends).to_sym
end end
def path
Array(@parent&.path).compact.push(key)
end
def extend! def extend!
if path.count(key) > 1
raise Extendable::Collection::CircularDependencyError
end
if extensible? if extensible?
@hash[key] = base.deep_merge(value) @context[key] = base.deep_merge(value)
else else
value value
end end
......
...@@ -117,6 +117,33 @@ describe Gitlab::Ci::Config::Extendable::Collection do ...@@ -117,6 +117,33 @@ describe Gitlab::Ci::Config::Extendable::Collection do
end end
pending 'when invalid `extends` is specified' pending 'when invalid `extends` is specified'
pending 'when circular dependecy has been detected' context 'when circular dependecy has been detected' do
let(:hash) do
{
test: {
extends: 'something',
script: 'ls',
only: { refs: %w[master] }
},
something: {
extends: '.first',
script: 'deploy',
only: { variables: %w[$SOMETHING] }
},
'.first': {
extends: 'something',
script: 'run',
only: { kubernetes: 'active' }
}
}
end
it 'raises an error' do
expect { subject.extend! }
.to raise_error(described_class::CircularDependencyError)
end
end
end end
end end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment