Commit ee9fd5c2 authored by Grzegorz Bizon's avatar Grzegorz Bizon

Improve extendable CI/CD config hash collection

parent 2f05e34b
...@@ -6,26 +6,23 @@ module Gitlab ...@@ -6,26 +6,23 @@ module Gitlab
include Enumerable include Enumerable
ExtensionError = Class.new(StandardError) ExtensionError = Class.new(StandardError)
InvalidExtensionError = Class.new(ExtensionError)
CircularDependencyError = Class.new(ExtensionError) CircularDependencyError = Class.new(ExtensionError)
def initialize(hash) def initialize(hash)
@hash = hash @hash = hash.dup
each { |entry| entry.extend! if entry.extensible? }
end end
def each def each
@hash.each_pair do |key, value| @hash.each_key do |key|
next unless value.key?(:extends)
yield Extendable::Entry.new(key, @hash) yield Extendable::Entry.new(key, @hash)
end end
end end
def extend! def to_hash
each do |entry| @hash.to_h
raise ExtensionError unless entry.valid?
entry.extend!
end
end end
end end
end end
......
...@@ -19,9 +19,9 @@ module Gitlab ...@@ -19,9 +19,9 @@ module Gitlab
@value ||= @context.fetch(@key) @value ||= @context.fetch(@key)
end end
def base def base_hash
Extendable::Entry Extendable::Entry
.new(extends, @context, self) .new(extends_key, @context, self)
.extend! .extend!
end end
...@@ -29,8 +29,8 @@ module Gitlab ...@@ -29,8 +29,8 @@ module Gitlab
value.key?(:extends) value.key?(:extends)
end end
def extends def extends_key
value.fetch(:extends).to_sym value.fetch(:extends).to_s.to_sym
end end
def path def path
...@@ -38,16 +38,30 @@ module Gitlab ...@@ -38,16 +38,30 @@ module Gitlab
end end
def extend! def extend!
if path.count(key) > 1 if circular_dependency?
raise Extendable::Collection::CircularDependencyError raise Extendable::Collection::CircularDependencyError
end end
if invalid_extends_key?
raise Extendable::Collection::InvalidExtensionError
end
if extensible? if extensible?
@context[key] = base.deep_merge(value) @context[key] = base_hash.deep_merge(value)
else else
value value
end end
end end
private
def circular_dependency?
path.count(key) > 1
end
def invalid_extends_key?
!@context.key?(key)
end
end end
end end
end end
......
...@@ -13,23 +13,13 @@ describe Gitlab::Ci::Config::Extendable::Collection do ...@@ -13,23 +13,13 @@ describe Gitlab::Ci::Config::Extendable::Collection do
{ something: { script: 'ls' }, test: test } { something: { script: 'ls' }, test: test }
end end
it 'yields the test hash' do it 'yields control' do
expect { |b| subject.each(&b) }.to yield_control
end
end
context 'when not extending using a hash' do
let(:hash) do
{ something: { extends: [1], script: 'ls' } }
end
it 'yields invalid extends as well' do
expect { |b| subject.each(&b) }.to yield_control expect { |b| subject.each(&b) }.to yield_control
end end
end end
end end
describe '#extend!' do describe '#to_hash' do
context 'when a hash has a single simple extension' do context 'when a hash has a single simple extension' do
let(:hash) do let(:hash) do
{ {
...@@ -47,7 +37,7 @@ describe Gitlab::Ci::Config::Extendable::Collection do ...@@ -47,7 +37,7 @@ describe Gitlab::Ci::Config::Extendable::Collection do
end end
it 'extends a hash with a deep reverse merge' do it 'extends a hash with a deep reverse merge' do
expect(subject.extend!).to eq( expect(subject.to_hash).to eq(
something: { something: {
script: 'deploy', script: 'deploy',
only: { variables: %w[$SOMETHING] } only: { variables: %w[$SOMETHING] }
...@@ -88,7 +78,7 @@ describe Gitlab::Ci::Config::Extendable::Collection do ...@@ -88,7 +78,7 @@ describe Gitlab::Ci::Config::Extendable::Collection do
end end
it 'extends a hash with a deep reverse merge' do it 'extends a hash with a deep reverse merge' do
expect(subject.extend!).to eq( expect(subject.to_hash).to eq(
'.first': { '.first': {
script: 'run', script: 'run',
only: { kubernetes: 'active' } only: { kubernetes: 'active' }
...@@ -139,8 +129,8 @@ describe Gitlab::Ci::Config::Extendable::Collection do ...@@ -139,8 +129,8 @@ describe Gitlab::Ci::Config::Extendable::Collection do
} }
end end
it 'raises an error' do it 'raises an error about circular dependency' do
expect { subject.extend! } expect { subject.to_hash }
.to raise_error(described_class::CircularDependencyError) .to raise_error(described_class::CircularDependencyError)
end end
end end
...@@ -156,12 +146,21 @@ describe Gitlab::Ci::Config::Extendable::Collection do ...@@ -156,12 +146,21 @@ describe Gitlab::Ci::Config::Extendable::Collection do
} }
end end
it 'raises an error' do it 'raises an error about circular dependency' do
expect { subject.extend! } expect { subject.to_hash }
.to raise_error(described_class::CircularDependencyError) .to raise_error(described_class::CircularDependencyError)
end end
end end
pending 'when invalid `extends` is specified' context 'when invalid extends value is specified' do
let(:hash) do
{ something: { extends: 1, script: 'ls' } }
end
it 'raises an error about invalid extension' do
expect { subject.to_hash }
.to raise_error(described_class::InvalidExtensionError)
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