Commit 05f6c3af authored by Alex Kalderimis's avatar Alex Kalderimis

Merge branch 'mc/feature/flatten-ci-config-rules' into 'master'

Flatten CI config rules

See merge request gitlab-org/gitlab!67922
parents 9240c2c2 0b8c81b8
...@@ -31,7 +31,7 @@ module Gitlab ...@@ -31,7 +31,7 @@ module Gitlab
with_options allow_nil: true do with_options allow_nil: true do
validates :extends, array_of_strings_or_string: true validates :extends, array_of_strings_or_string: true
validates :rules, array_of_hashes: true validates :rules, nested_array_of_hashes: true
validates :resource_group, type: String validates :resource_group, type: String
end end
end end
......
...@@ -13,7 +13,7 @@ module Gitlab ...@@ -13,7 +13,7 @@ module Gitlab
end end
def value def value
@config [@config].flatten
end end
def composable_class def composable_class
......
...@@ -78,10 +78,26 @@ module Gitlab ...@@ -78,10 +78,26 @@ module Gitlab
include LegacyValidationHelpers include LegacyValidationHelpers
def validate_each(record, attribute, value) def validate_each(record, attribute, value)
unless value.is_a?(Array) && value.map { |hsh| hsh.is_a?(Hash) }.all? unless validate_array_of_hashes(value)
record.errors.add(attribute, 'should be an array of hashes') record.errors.add(attribute, 'should be an array of hashes')
end end
end end
private
def validate_array_of_hashes(value)
value.is_a?(Array) && value.all? { |obj| obj.is_a?(Hash) }
end
end
class NestedArrayOfHashesValidator < ArrayOfHashesValidator
include NestedArrayHelpers
def validate_each(record, attribute, value)
unless validate_nested_array(value, 1, &method(:validate_array_of_hashes))
record.errors.add(attribute, 'should be an array containing hashes and arrays of hashes')
end
end
end end
class ArrayOrStringValidator < ActiveModel::EachValidator class ArrayOrStringValidator < ActiveModel::EachValidator
......
...@@ -17,6 +17,10 @@ RSpec.describe Gitlab::Ci::Config::Entry::Rules do ...@@ -17,6 +17,10 @@ RSpec.describe Gitlab::Ci::Config::Entry::Rules do
describe '.new' do describe '.new' do
subject { entry } subject { entry }
before do
subject.compose!
end
context 'with a list of rule rule' do context 'with a list of rule rule' do
let(:config) do let(:config) do
[{ if: '$THIS == "that"', when: 'never' }] [{ if: '$THIS == "that"', when: 'never' }]
...@@ -24,14 +28,6 @@ RSpec.describe Gitlab::Ci::Config::Entry::Rules do ...@@ -24,14 +28,6 @@ RSpec.describe Gitlab::Ci::Config::Entry::Rules do
it { is_expected.to be_a(described_class) } it { is_expected.to be_a(described_class) }
it { is_expected.to be_valid } it { is_expected.to be_valid }
context 'when composed' do
before do
subject.compose!
end
it { is_expected.to be_valid }
end
end end
context 'with a list of two rules' do context 'with a list of two rules' do
...@@ -42,21 +38,34 @@ RSpec.describe Gitlab::Ci::Config::Entry::Rules do ...@@ -42,21 +38,34 @@ RSpec.describe Gitlab::Ci::Config::Entry::Rules do
] ]
end end
it { is_expected.to be_a(described_class) }
it { is_expected.to be_valid } it { is_expected.to be_valid }
end
context 'when composed' do context 'with a single rule object' do
before do let(:config) do
subject.compose! { if: '$SKIP', when: 'never' }
end end
it { is_expected.to be_valid } it { is_expected.not_to be_valid }
end
context 'with nested rules' do
let(:config) do
[
{ if: '$THIS == "that"', when: 'always' },
[{ if: '$SKIP', when: 'never' }]
]
end end
it { is_expected.to be_valid }
end end
context 'with a single rule object' do context 'with rules nested more than one level' do
let(:config) do let(:config) do
{ if: '$SKIP', when: 'never' } [
{ if: '$THIS == "that"', when: 'always' },
[{ if: '$SKIP', when: 'never' }, [{ if: '$THIS == "other"', when: 'aways' }]]
]
end end
it { is_expected.not_to be_valid } it { is_expected.not_to be_valid }
...@@ -90,7 +99,36 @@ RSpec.describe Gitlab::Ci::Config::Entry::Rules do ...@@ -90,7 +99,36 @@ RSpec.describe Gitlab::Ci::Config::Entry::Rules do
{ if: '$SKIP', when: 'never' } { if: '$SKIP', when: 'never' }
end end
it { is_expected.to eq(config) } it { is_expected.to eq([config]) }
end
context 'with nested rules' do
let(:first_rule) { { if: '$THIS == "that"', when: 'always' } }
let(:second_rule) { { if: '$SKIP', when: 'never' } }
let(:config) do
[
first_rule,
[second_rule]
]
end
it { is_expected.to contain_exactly(first_rule, second_rule) }
end
context 'with rules nested more than one level' do
let(:first_rule) { { if: '$THIS == "that"', when: 'always' } }
let(:second_rule) { { if: '$SKIP', when: 'never' } }
let(:third_rule) { { if: '$THIS == "other"', when: 'aways' } }
let(:config) do
[
first_rule,
[second_rule, [third_rule]]
]
end
it { is_expected.to contain_exactly(first_rule, second_rule, third_rule) }
end end
end end
......
...@@ -2781,7 +2781,7 @@ module Gitlab ...@@ -2781,7 +2781,7 @@ module Gitlab
expect(subject.valid?).to eq(false) expect(subject.valid?).to eq(false)
expect(subject.errors).to contain_exactly( expect(subject.errors).to contain_exactly(
'jobs:rspec config contains unknown keys: bad_tags', 'jobs:rspec config contains unknown keys: bad_tags',
'jobs:rspec rules should be an array of hashes') 'jobs:rspec rules should be an array containing hashes and arrays of hashes')
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