debian-mirror-gitlab/spec/lib/gitlab/ci/config/entry/bridge_spec.rb
2023-01-13 15:02:22 +05:30

417 lines
12 KiB
Ruby

# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Gitlab::Ci::Config::Entry::Bridge do
subject(:entry) { 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] },
job_variables: {},
root_variables_inheritance: true,
scheduling_type: :stage)
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] },
job_variables: {},
root_variables_inheritance: true,
scheduling_type: :stage)
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.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
context 'when bridge config contains exit_codes' do
let(:config) do
{ script: 'rspec', allow_failure: { exit_codes: [42] } }
end
describe '#valid?' do
it { is_expected.not_to be_valid }
end
describe '#errors' do
it 'returns an error message' do
expect(subject.errors)
.to include(/allow failure should be a boolean value/)
end
end
end
context 'when bridge config contains parallel' do
let(:config) { { trigger: 'some/project', parallel: parallel_config } }
context 'when parallel config is a number' do
let(:parallel_config) { 2 }
describe '#valid?' do
it { is_expected.not_to be_valid }
end
describe '#errors' do
it 'returns an error message' do
expect(subject.errors)
.to include(/cannot use "parallel: <number>"/)
end
end
end
context 'when parallel config is a matrix' do
let(:parallel_config) do
{ matrix: [{ PROVIDER: 'aws', STACK: %w[monitoring app1] },
{ PROVIDER: 'gcp', STACK: %w[data] }] }
end
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] },
parallel: { matrix: [{ 'PROVIDER' => ['aws'], 'STACK' => %w(monitoring app1) },
{ 'PROVIDER' => ['gcp'], 'STACK' => %w(data) }] },
job_variables: {},
root_variables_inheritance: true,
scheduling_type: :stage
)
end
end
end
end
context 'when bridge trigger contains forward' do
let(:config) do
{ trigger: { project: 'some/project', forward: { pipeline_variables: true } } }
end
describe '#valid?' do
it { is_expected.to be_valid }
end
describe '#value' do
it 'returns a bridge job configuration hash' do
expect(subject.value).to eq(name: :my_bridge,
trigger: { project: 'some/project',
forward: { pipeline_variables: true } },
ignore: false,
stage: 'test',
only: { refs: %w[branches tags] },
job_variables: {},
root_variables_inheritance: true,
scheduling_type: :stage)
end
end
end
end
describe '#manual_action?' do
context 'when job is a manual action' do
let(:config) { { script: 'deploy', when: 'manual' } }
it { is_expected.to be_manual_action }
end
context 'when job is not a manual action' do
let(:config) { { script: 'deploy' } }
it { is_expected.not_to be_manual_action }
end
end
describe '#ignored?' do
context 'when job is a manual action' do
context 'when it is not specified if job is allowed to fail' do
let(:config) do
{ script: 'deploy', when: 'manual' }
end
it { is_expected.to be_ignored }
end
context 'when job is allowed to fail' do
let(:config) do
{ script: 'deploy', when: 'manual', allow_failure: true }
end
it { is_expected.to be_ignored }
end
context 'when job is not allowed to fail' do
let(:config) do
{ script: 'deploy', when: 'manual', allow_failure: false }
end
it { is_expected.not_to be_ignored }
end
end
context 'when job is not a manual action' do
context 'when it is not specified if job is allowed to fail' do
let(:config) { { script: 'deploy' } }
it { is_expected.not_to be_ignored }
end
context 'when job is allowed to fail' do
let(:config) { { script: 'deploy', allow_failure: true } }
it { is_expected.to be_ignored }
end
context 'when job is not allowed to fail' do
let(:config) { { script: 'deploy', allow_failure: false } }
it { is_expected.not_to be_ignored }
end
end
end
describe '#when' do
context 'when bridge is a manual action' do
let(:config) { { script: 'deploy', when: 'manual' } }
it { expect(entry.when).to eq('manual') }
end
context 'when bridge has no `when` attribute' do
let(:config) { { script: 'deploy' } }
it { expect(entry.when).to be_nil }
end
context 'when the `when` keyword is not a string' do
context 'when it is an array' do
let(:config) { { script: 'exit 0', when: ['always'] } }
it 'returns error' do
expect(entry).not_to be_valid
expect(entry.errors).to include 'bridge when should be a string'
end
end
context 'when it is a boolean' do
let(:config) { { script: 'exit 0', when: true } }
it 'returns error' do
expect(entry).not_to be_valid
expect(entry.errors).to include 'bridge when should be a string'
end
end
end
end
end