diff options
author | Wolphin <wolphin@wolph.in> | 2019-06-05 08:25:55 +0000 |
---|---|---|
committer | Kamil TrzciĆski <ayufan@ayufan.eu> | 2019-06-05 08:25:55 +0000 |
commit | 1f2244f16bc2990000a77911520b0c06095522c2 (patch) | |
tree | 1e920c31d012cb4f928397b467739e0499de83ea /lib | |
parent | df549eb28c83b27500619ccb14c201a4ff87daa3 (diff) | |
download | gitlab-ce-1f2244f16bc2990000a77911520b0c06095522c2.tar.gz |
Add multiple extends support
Diffstat (limited to 'lib')
-rw-r--r-- | lib/gitlab/ci/config/entry/job.rb | 2 | ||||
-rw-r--r-- | lib/gitlab/ci/config/extendable/entry.rb | 59 |
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 |