diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2020-02-11 09:09:46 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2020-02-11 09:09:46 +0300 |
commit | 55733b19c526145cceb120e8bb874d476a84383a (patch) | |
tree | dcde3cfb905516cd1f07ab364a94aff5fddff391 /spec/lib | |
parent | ea99abb145ed193c2ac5d19efbff3b8990a54c9c (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec/lib')
-rw-r--r-- | spec/lib/gitlab/ci/config/entry/bridge_spec.rb | 227 | ||||
-rw-r--r-- | spec/lib/gitlab/ci/config/entry/jobs_spec.rb | 68 | ||||
-rw-r--r-- | spec/lib/gitlab/ci/config/entry/trigger_spec.rb | 164 |
3 files changed, 425 insertions, 34 deletions
diff --git a/spec/lib/gitlab/ci/config/entry/bridge_spec.rb b/spec/lib/gitlab/ci/config/entry/bridge_spec.rb new file mode 100644 index 00000000000..07590556db8 --- /dev/null +++ b/spec/lib/gitlab/ci/config/entry/bridge_spec.rb @@ -0,0 +1,227 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe Gitlab::Ci::Config::Entry::Bridge do + subject { described_class.new(config, name: :my_bridge) } + + it_behaves_like 'with inheritable CI config' do + let(:inheritable_key) { 'default' } + let(:inheritable_class) { Gitlab::Ci::Config::Entry::Default } + + # These are entries defined in Default + # that we know that we don't want to inherit + # as they do not have sense in context of Bridge + let(:ignored_inheritable_columns) do + %i[before_script after_script image services cache interruptible timeout + retry tags artifacts] + end + end + + describe '.matching?' do + subject { described_class.matching?(name, config) } + + context 'when config is not a hash' do + let(:name) { :my_trigger } + let(:config) { 'string' } + + it { is_expected.to be_falsey } + end + + context 'when config is a regular job' do + let(:name) { :my_trigger } + let(:config) do + { script: 'ls -al' } + end + + it { is_expected.to be_falsey } + + context 'with rules' do + let(:config) do + { + script: 'ls -al', + rules: [{ if: '$VAR == "value"', when: 'always' }] + } + end + + it { is_expected.to be_falsey } + end + end + + context 'when config is a bridge job' do + let(:name) { :my_trigger } + let(:config) do + { trigger: 'other-project' } + end + + it { is_expected.to be_truthy } + + context 'with rules' do + let(:config) do + { + trigger: 'other-project', + rules: [{ if: '$VAR == "value"', when: 'always' }] + } + end + + it { is_expected.to be_truthy } + end + end + + context 'when config is a hidden job' do + let(:name) { '.my_trigger' } + let(:config) do + { trigger: 'other-project' } + end + + it { is_expected.to be_falsey } + end + end + + describe '.new' do + before do + subject.compose! + end + + let(:base_config) do + { + trigger: { project: 'some/project', branch: 'feature' }, + extends: '.some-key', + stage: 'deploy', + variables: { VARIABLE: '123' } + } + end + + context 'when trigger config is a non-empty string' do + let(:config) { { trigger: 'some/project' } } + + describe '#valid?' do + it { is_expected.to be_valid } + end + + describe '#value' do + it 'is returns a bridge job configuration' do + expect(subject.value).to eq(name: :my_bridge, + trigger: { project: 'some/project' }, + ignore: false, + stage: 'test', + only: { refs: %w[branches tags] }) + end + end + end + + context 'when bridge trigger is a hash' do + let(:config) do + { trigger: { project: 'some/project', branch: 'feature' } } + end + + describe '#valid?' do + it { is_expected.to be_valid } + end + + describe '#value' do + it 'is returns a bridge job configuration hash' do + expect(subject.value).to eq(name: :my_bridge, + trigger: { project: 'some/project', + branch: 'feature' }, + ignore: false, + stage: 'test', + only: { refs: %w[branches tags] }) + end + end + end + + context 'when bridge configuration contains trigger, when, extends, stage, only, except, and variables' do + let(:config) do + base_config.merge({ + when: 'always', + only: { variables: %w[$SOMEVARIABLE] }, + except: { refs: %w[feature] } + }) + end + + it { is_expected.to be_valid } + end + + context 'when bridge configuration uses rules' do + let(:config) { base_config.merge({ rules: [{ if: '$VAR == null', when: 'never' }] }) } + + it { is_expected.to be_valid } + end + + context 'when bridge configuration uses rules with job:when' do + let(:config) do + base_config.merge({ + when: 'always', + rules: [{ if: '$VAR == null', when: 'never' }] + }) + end + + it { is_expected.not_to be_valid } + end + + context 'when bridge configuration uses rules with only' do + let(:config) do + base_config.merge({ + only: { variables: %w[$SOMEVARIABLE] }, + rules: [{ if: '$VAR == null', when: 'never' }] + }) + end + + it { is_expected.not_to be_valid } + end + + context 'when bridge configuration uses rules with except' do + let(:config) do + base_config.merge({ + except: { refs: %w[feature] }, + rules: [{ if: '$VAR == null', when: 'never' }] + }) + end + + it { is_expected.not_to be_valid } + end + + context 'when bridge has only job needs' do + let(:config) do + { + needs: ['some_job'] + } + end + + describe '#valid?' do + it { is_expected.not_to be_valid } + end + end + + context 'when bridge config contains unknown keys' do + let(:config) { { unknown: 123 } } + + describe '#valid?' do + it { is_expected.not_to be_valid } + end + + describe '#errors' do + it 'is returns an error about unknown config key' do + expect(subject.errors.first) + .to match /config contains unknown keys: unknown/ + end + end + end + + context 'when bridge config contains build-specific attributes' do + let(:config) { { script: 'something' } } + + describe '#valid?' do + it { is_expected.not_to be_valid } + end + + describe '#errors' do + it 'returns an error message' do + expect(subject.errors.first) + .to match /contains unknown keys: script/ + end + end + end + end +end diff --git a/spec/lib/gitlab/ci/config/entry/jobs_spec.rb b/spec/lib/gitlab/ci/config/entry/jobs_spec.rb index 61c8956d41f..05249b7c717 100644 --- a/spec/lib/gitlab/ci/config/entry/jobs_spec.rb +++ b/spec/lib/gitlab/ci/config/entry/jobs_spec.rb @@ -5,27 +5,31 @@ require 'spec_helper' describe Gitlab::Ci::Config::Entry::Jobs do let(:entry) { described_class.new(config) } + let(:config) do + { + '.hidden_job'.to_sym => { script: 'something' }, + '.hidden_bridge'.to_sym => { trigger: 'my/project' }, + regular_job: { script: 'something' }, + my_trigger: { trigger: 'my/project' } + } + end + describe '.all_types' do subject { described_class.all_types } it { is_expected.to include(::Gitlab::Ci::Config::Entry::Hidden) } it { is_expected.to include(::Gitlab::Ci::Config::Entry::Job) } + it { is_expected.to include(::Gitlab::Ci::Config::Entry::Bridge) } end describe '.find_type' do using RSpec::Parameterized::TableSyntax - let(:config) do - { - '.hidden_job'.to_sym => { script: 'something' }, - regular_job: { script: 'something' }, - invalid_job: 'text' - } - end - where(:name, :type) do :'.hidden_job' | ::Gitlab::Ci::Config::Entry::Hidden + :'.hidden_bridge' | ::Gitlab::Ci::Config::Entry::Hidden :regular_job | ::Gitlab::Ci::Config::Entry::Job + :my_trigger | ::Gitlab::Ci::Config::Entry::Bridge :invalid_job | nil end @@ -42,8 +46,6 @@ describe Gitlab::Ci::Config::Entry::Jobs do end context 'when entry config value is correct' do - let(:config) { { rspec: { script: 'rspec' } } } - describe '#valid?' do it 'is valid' do expect(entry).to be_valid @@ -88,43 +90,41 @@ describe Gitlab::Ci::Config::Entry::Jobs do entry.compose! end - let(:config) do - { rspec: { script: 'rspec' }, - spinach: { script: 'spinach' }, - '.hidden'.to_sym => {} } - end - describe '#value' do it 'returns key value' do expect(entry.value).to eq( - rspec: { name: :rspec, - script: %w[rspec], - ignore: false, - stage: 'test', - only: { refs: %w[branches tags] }, - variables: {} }, - spinach: { name: :spinach, - script: %w[spinach], - ignore: false, - stage: 'test', - only: { refs: %w[branches tags] }, - variables: {} }) + my_trigger: { + ignore: false, + name: :my_trigger, + only: { refs: %w[branches tags] }, + stage: 'test', + trigger: { project: 'my/project' } + }, + regular_job: { + ignore: false, + name: :regular_job, + only: { refs: %w[branches tags] }, + script: ['something'], + stage: 'test', + variables: {} + }) end end describe '#descendants' do it 'creates valid descendant nodes' do - expect(entry.descendants.count).to eq 3 - expect(entry.descendants.first(2)) - .to all(be_an_instance_of(Gitlab::Ci::Config::Entry::Job)) - expect(entry.descendants.last) - .to be_an_instance_of(Gitlab::Ci::Config::Entry::Hidden) + expect(entry.descendants.map(&:class)).to eq [ + Gitlab::Ci::Config::Entry::Hidden, + Gitlab::Ci::Config::Entry::Hidden, + Gitlab::Ci::Config::Entry::Job, + Gitlab::Ci::Config::Entry::Bridge + ] end end describe '#value' do it 'returns value of visible jobs only' do - expect(entry.value.keys).to eq [:rspec, :spinach] + expect(entry.value.keys).to eq [:regular_job, :my_trigger] end end end diff --git a/spec/lib/gitlab/ci/config/entry/trigger_spec.rb b/spec/lib/gitlab/ci/config/entry/trigger_spec.rb new file mode 100644 index 00000000000..752c3f59a95 --- /dev/null +++ b/spec/lib/gitlab/ci/config/entry/trigger_spec.rb @@ -0,0 +1,164 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe Gitlab::Ci::Config::Entry::Trigger do + subject { described_class.new(config) } + + context 'when trigger config is a non-empty string' do + let(:config) { 'some/project' } + + describe '#valid?' do + it { is_expected.to be_valid } + end + + describe '#value' do + it 'returns a trigger configuration hash' do + expect(subject.value).to eq(project: 'some/project') + end + end + end + + context 'when trigger config an empty string' do + let(:config) { '' } + + describe '#valid?' do + it { is_expected.not_to be_valid } + end + + describe '#errors' do + it 'returns an error about an empty config' do + expect(subject.errors.first) + .to match /config can't be blank/ + end + end + end + + context 'when trigger is a hash' do + context 'when branch is provided' do + let(:config) { { project: 'some/project', branch: 'feature' } } + + describe '#valid?' do + it { is_expected.to be_valid } + end + + describe '#value' do + it 'returns a trigger configuration hash' do + expect(subject.value) + .to eq(project: 'some/project', branch: 'feature') + end + end + end + + context 'when strategy is provided' do + context 'when strategy is depend' do + let(:config) { { project: 'some/project', strategy: 'depend' } } + + describe '#valid?' do + it { is_expected.to be_valid } + end + + describe '#value' do + it 'returns a trigger configuration hash' do + expect(subject.value) + .to eq(project: 'some/project', strategy: 'depend') + end + end + end + + context 'when strategy is invalid' do + let(:config) { { project: 'some/project', strategy: 'notdepend' } } + + describe '#valid?' do + it { is_expected.not_to be_valid } + end + + describe '#errors' do + it 'returns an error about unknown config key' do + expect(subject.errors.first) + .to match /trigger strategy should be depend/ + end + end + end + end + + describe '#include' do + context 'with simple include' do + let(:config) { { include: 'path/to/config.yml' } } + + it { is_expected.to be_valid } + + it 'returns a trigger configuration hash' do + expect(subject.value).to eq(include: 'path/to/config.yml' ) + end + end + + context 'with project' do + let(:config) { { project: 'some/project', include: 'path/to/config.yml' } } + + it { is_expected.not_to be_valid } + + it 'returns an error' do + expect(subject.errors.first) + .to match /config contains unknown keys: project/ + end + end + + context 'with branch' do + let(:config) { { branch: 'feature', include: 'path/to/config.yml' } } + + it { is_expected.not_to be_valid } + + it 'returns an error' do + expect(subject.errors.first) + .to match /config contains unknown keys: branch/ + end + end + + context 'when feature flag is off' do + before do + stub_feature_flags(ci_parent_child_pipeline: false) + end + + let(:config) { { include: 'path/to/config.yml' } } + + it 'is returns an error if include is used' do + expect(subject.errors.first) + .to match /config must specify project/ + end + end + end + + context 'when config contains unknown keys' do + let(:config) { { project: 'some/project', unknown: 123 } } + + describe '#valid?' do + it { is_expected.not_to be_valid } + end + + describe '#errors' do + it 'returns an error about unknown config key' do + expect(subject.errors.first) + .to match /config contains unknown keys: unknown/ + end + end + end + end + + context 'when trigger configuration is not valid' do + context 'when branch is not provided' do + let(:config) { 123 } + + describe '#valid?' do + it { is_expected.not_to be_valid } + end + + describe '#errors' do + it 'returns an error message' do + expect(subject.errors.first) + .to match /has to be either a string or a hash/ + end + end + end + end +end |