Commit 2c41fbb1 authored by Grzegorz Bizon's avatar Grzegorz Bizon

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

parent ef26622d
......@@ -6,6 +6,7 @@ module Gitlab
include Enumerable
ExtensionError = Class.new(StandardError)
CircularDependencyError = Class.new(ExtensionError)
def initialize(hash)
@hash = hash
......
......@@ -5,9 +5,9 @@ module Gitlab
class Entry
attr_reader :key
def initialize(key, hash, parent = nil)
def initialize(key, context, parent = nil)
@key = key
@hash = hash
@context = context
@parent = parent
end
......@@ -16,12 +16,12 @@ module Gitlab
end
def value
@value ||= @hash.fetch(@key)
@value ||= @context.fetch(@key)
end
def base
Extendable::Entry
.new(extends, @hash, self)
.new(extends, @context, self)
.extend!
end
......@@ -33,9 +33,17 @@ module Gitlab
value.fetch(:extends).to_sym
end
def path
Array(@parent&.path).compact.push(key)
end
def extend!
if path.count(key) > 1
raise Extendable::Collection::CircularDependencyError
end
if extensible?
@hash[key] = base.deep_merge(value)
@context[key] = base.deep_merge(value)
else
value
end
......
......@@ -117,6 +117,33 @@ describe Gitlab::Ci::Config::Extendable::Collection do
end
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
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