summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorWolphin <wolphin@wolph.in>2019-06-05 08:25:55 +0000
committerKamil TrzciƄski <ayufan@ayufan.eu>2019-06-05 08:25:55 +0000
commit1f2244f16bc2990000a77911520b0c06095522c2 (patch)
tree1e920c31d012cb4f928397b467739e0499de83ea /lib
parentdf549eb28c83b27500619ccb14c201a4ff87daa3 (diff)
downloadgitlab-ce-1f2244f16bc2990000a77911520b0c06095522c2.tar.gz
Add multiple extends support
Diffstat (limited to 'lib')
-rw-r--r--lib/gitlab/ci/config/entry/job.rb2
-rw-r--r--lib/gitlab/ci/config/extendable/entry.rb59
2 files changed, 43 insertions, 18 deletions
diff --git a/lib/gitlab/ci/config/entry/job.rb b/lib/gitlab/ci/config/entry/job.rb
index 290c9591b98..762532f7007 100644
--- a/lib/gitlab/ci/config/entry/job.rb
+++ b/lib/gitlab/ci/config/entry/job.rb
@@ -34,7 +34,7 @@ module Gitlab
message: 'should be on_success, on_failure, ' \
'always, manual or delayed' }
validates :dependencies, array_of_strings: true
- validates :extends, type: String
+ validates :extends, array_of_strings_or_string: true
end
validates :start_in, duration: { limit: '1 day' }, if: :delayed?
diff --git a/lib/gitlab/ci/config/extendable/entry.rb b/lib/gitlab/ci/config/extendable/entry.rb
index 7793db09d33..0001a259281 100644
--- a/lib/gitlab/ci/config/extendable/entry.rb
+++ b/lib/gitlab/ci/config/extendable/entry.rb
@@ -5,6 +5,8 @@ module Gitlab
class Config
class Extendable
class Entry
+ include Gitlab::Utils::StrongMemoize
+
InvalidExtensionError = Class.new(Extendable::ExtensionError)
CircularDependencyError = Class.new(Extendable::ExtensionError)
NestingTooDeepError = Class.new(Extendable::ExtensionError)
@@ -28,34 +30,46 @@ module Gitlab
end
def value
- @value ||= @context.fetch(@key)
+ strong_memoize(:value) do
+ @context.fetch(@key)
+ end
end
- def base_hash!
- @base ||= Extendable::Entry
- .new(extends_key, @context, self)
- .extend!
+ def base_hashes!
+ strong_memoize(:base_hashes) do
+ extends_keys.map do |key|
+ Extendable::Entry
+ .new(key, @context, self)
+ .extend!
+ end
+ end
end
- def extends_key
- value.fetch(:extends).to_s.to_sym if extensible?
+ def extends_keys
+ strong_memoize(:extends_keys) do
+ next unless extensible?
+
+ Array(value.fetch(:extends)).map(&:to_s).map(&:to_sym)
+ end
end
def ancestors
- @ancestors ||= Array(@parent&.ancestors) + Array(@parent&.key)
+ strong_memoize(:ancestors) do
+ Array(@parent&.ancestors) + Array(@parent&.key)
+ end
end
def extend!
return value unless extensible?
- if unknown_extension?
+ if unknown_extensions.any?
raise Entry::InvalidExtensionError,
- "#{key}: unknown key in `extends`"
+ "#{key}: unknown keys in `extends` (#{show_keys(unknown_extensions)})"
end
- if invalid_base?
+ if invalid_bases.any?
raise Entry::InvalidExtensionError,
- "#{key}: invalid base hash in `extends`"
+ "#{key}: invalid base hashes in `extends` (#{show_keys(invalid_bases)})"
end
if nesting_too_deep?
@@ -68,11 +82,18 @@ module Gitlab
"#{key}: circular dependency detected in `extends`"
end
- @context[key] = base_hash!.deep_merge(value)
+ merged = {}
+ base_hashes!.each { |h| merged.deep_merge!(h) }
+
+ @context[key] = merged.deep_merge!(value)
end
private
+ def show_keys(keys)
+ keys.join(', ')
+ end
+
def nesting_too_deep?
ancestors.count > MAX_NESTING_LEVELS
end
@@ -81,12 +102,16 @@ module Gitlab
ancestors.include?(key)
end
- def unknown_extension?
- !@context.key?(extends_key)
+ def unknown_extensions
+ strong_memoize(:unknown_extensions) do
+ extends_keys.reject { |key| @context.key?(key) }
+ end
end
- def invalid_base?
- !@context[extends_key].is_a?(Hash)
+ def invalid_bases
+ strong_memoize(:invalid_bases) do
+ extends_keys.reject { |key| @context[key].is_a?(Hash) }
+ end
end
end
end