summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGrzegorz Bizon <grzesiek.bizon@gmail.com>2018-08-16 15:30:06 +0200
committerGrzegorz Bizon <grzesiek.bizon@gmail.com>2018-09-04 14:17:01 +0200
commit2c41fbb14821c8028e389c270d2f39380e5fbe04 (patch)
treedd7c4069b7cb05247bb605589388bc2a0320d305
parentef26622d62fe37371adf0d66c81f8428ad4bb1b6 (diff)
downloadgitlab-ce-2c41fbb14821c8028e389c270d2f39380e5fbe04.tar.gz
Detect circular dependenies in CI/CD `extends:` entry
-rw-r--r--lib/gitlab/ci/config/extendable/collection.rb1
-rw-r--r--lib/gitlab/ci/config/extendable/entry.rb18
-rw-r--r--spec/lib/gitlab/ci/config/extendable/collection_spec.rb29
3 files changed, 42 insertions, 6 deletions
diff --git a/lib/gitlab/ci/config/extendable/collection.rb b/lib/gitlab/ci/config/extendable/collection.rb
index 3a71e06e3e2..e59884439a2 100644
--- a/lib/gitlab/ci/config/extendable/collection.rb
+++ b/lib/gitlab/ci/config/extendable/collection.rb
@@ -6,6 +6,7 @@ module Gitlab
include Enumerable
ExtensionError = Class.new(StandardError)
+ CircularDependencyError = Class.new(ExtensionError)
def initialize(hash)
@hash = hash
diff --git a/lib/gitlab/ci/config/extendable/entry.rb b/lib/gitlab/ci/config/extendable/entry.rb
index 5844cb098b9..96b0bd1a2ce 100644
--- a/lib/gitlab/ci/config/extendable/entry.rb
+++ b/lib/gitlab/ci/config/extendable/entry.rb
@@ -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
diff --git a/spec/lib/gitlab/ci/config/extendable/collection_spec.rb b/spec/lib/gitlab/ci/config/extendable/collection_spec.rb
index 453c7357561..e3be0704f1a 100644
--- a/spec/lib/gitlab/ci/config/extendable/collection_spec.rb
+++ b/spec/lib/gitlab/ci/config/extendable/collection_spec.rb
@@ -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