debian-mirror-gitlab/spec/lib/gitlab/ci/pipeline/seed/build_spec.rb

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

1116 lines
35 KiB
Ruby
Raw Normal View History

2019-09-30 21:07:59 +05:30
# frozen_string_literal: true
2018-05-09 12:01:36 +05:30
require 'spec_helper'
2020-07-28 23:09:34 +05:30
RSpec.describe Gitlab::Ci::Pipeline::Seed::Build do
2021-12-11 22:18:48 +05:30
let_it_be_with_reload(:project) { create(:project, :repository) }
2021-01-03 14:25:43 +05:30
let_it_be(:head_sha) { project.repository.head_commit.id }
2021-06-08 01:23:25 +05:30
2021-01-03 14:25:43 +05:30
let(:pipeline) { build(:ci_empty_pipeline, project: project, sha: head_sha) }
2021-04-29 21:17:54 +05:30
let(:root_variables) { [] }
2022-03-02 08:16:31 +05:30
let(:seed_context) { Gitlab::Ci::Pipeline::Seed::Context.new(pipeline, root_variables: root_variables) }
2022-01-26 12:08:38 +05:30
let(:attributes) { { name: 'rspec', ref: 'master', scheduling_type: :stage, when: 'on_success' } }
2019-10-12 21:52:04 +05:30
let(:previous_stages) { [] }
2021-09-30 23:02:18 +05:30
let(:current_stage) { double(seeds_names: [attributes[:name]]) }
2018-05-09 12:01:36 +05:30
2021-12-11 22:18:48 +05:30
let(:seed_build) { described_class.new(seed_context, attributes, previous_stages + [current_stage]) }
2018-05-09 12:01:36 +05:30
describe '#attributes' do
2019-09-30 21:07:59 +05:30
subject { seed_build.attributes }
it { is_expected.to be_a(Hash) }
it { is_expected.to include(:name, :project, :ref) }
2019-12-04 20:38:33 +05:30
context 'with job:when' do
let(:attributes) { { name: 'rspec', ref: 'master', when: 'on_failure' } }
it { is_expected.to include(when: 'on_failure') }
end
context 'with job:when:delayed' do
let(:attributes) { { name: 'rspec', ref: 'master', when: 'delayed', start_in: '3 hours' } }
it { is_expected.to include(when: 'delayed', start_in: '3 hours') }
end
context 'with job:rules:[when:]' do
context 'is matched' do
let(:attributes) { { name: 'rspec', ref: 'master', rules: [{ if: '$VAR == null', when: 'always' }] } }
it { is_expected.to include(when: 'always') }
end
context 'is not matched' do
let(:attributes) { { name: 'rspec', ref: 'master', rules: [{ if: '$VAR != null', when: 'always' }] } }
it { is_expected.to include(when: 'never') }
end
end
context 'with job:rules:[when:delayed]' do
context 'is matched' do
let(:attributes) { { name: 'rspec', ref: 'master', rules: [{ if: '$VAR == null', when: 'delayed', start_in: '3 hours' }] } }
it { is_expected.to include(when: 'delayed', options: { start_in: '3 hours' }) }
end
context 'is not matched' do
let(:attributes) { { name: 'rspec', ref: 'master', rules: [{ if: '$VAR != null', when: 'delayed', start_in: '3 hours' }] } }
it { is_expected.to include(when: 'never') }
end
end
2022-01-26 12:08:38 +05:30
context 'with job: rules but no explicit when:' do
let(:base_attributes) { { name: 'rspec', ref: 'master' } }
context 'with a manual job' do
context 'with a matched rule' do
let(:attributes) { base_attributes.merge(when: 'manual', rules: [{ if: '$VAR == null' }]) }
it { is_expected.to include(when: 'manual') }
end
2019-12-04 20:38:33 +05:30
2022-01-26 12:08:38 +05:30
context 'is not matched' do
let(:attributes) { base_attributes.merge(when: 'manual', rules: [{ if: '$VAR != null' }]) }
it { is_expected.to include(when: 'never') }
end
2019-12-04 20:38:33 +05:30
end
2022-01-26 12:08:38 +05:30
context 'with an automatic job' do
context 'is matched' do
let(:attributes) { base_attributes.merge(when: 'on_success', rules: [{ if: '$VAR == null' }]) }
2019-12-04 20:38:33 +05:30
2022-01-26 12:08:38 +05:30
it { is_expected.to include(when: 'on_success') }
end
context 'is not matched' do
let(:attributes) { base_attributes.merge(when: 'on_success', rules: [{ if: '$VAR != null' }]) }
it { is_expected.to include(when: 'never') }
end
2019-12-04 20:38:33 +05:30
end
end
2019-12-26 22:10:19 +05:30
2021-02-22 17:27:13 +05:30
context 'with job:rules:[variables:]' do
let(:attributes) do
{ name: 'rspec',
ref: 'master',
2021-04-29 21:17:54 +05:30
job_variables: [{ key: 'VAR1', value: 'var 1', public: true },
{ key: 'VAR2', value: 'var 2', public: true }],
2021-02-22 17:27:13 +05:30
rules: [{ if: '$VAR == null', variables: { VAR1: 'new var 1', VAR3: 'var 3' } }] }
end
it do
is_expected.to include(yaml_variables: [{ key: 'VAR1', value: 'new var 1', public: true },
{ key: 'VAR2', value: 'var 2', public: true },
{ key: 'VAR3', value: 'var 3', public: true }])
end
2021-04-17 20:07:23 +05:30
end
2021-02-22 17:27:13 +05:30
2021-09-30 23:02:18 +05:30
context 'with job:tags' do
let(:attributes) do
{
name: 'rspec',
ref: 'master',
job_variables: [{ key: 'VARIABLE', value: 'value', public: true }],
tag_list: ['static-tag', '$VARIABLE', '$NO_VARIABLE']
}
end
it { is_expected.to include(tag_list: ['static-tag', 'value', '$NO_VARIABLE']) }
it { is_expected.to include(yaml_variables: [{ key: 'VARIABLE', value: 'value', public: true }]) }
end
2021-04-17 20:07:23 +05:30
context 'with cache:key' do
2019-12-26 22:10:19 +05:30
let(:attributes) do
{
name: 'rspec',
ref: 'master',
2021-04-17 20:07:23 +05:30
cache: [{
key: 'a-value'
}]
2019-12-26 22:10:19 +05:30
}
end
2021-04-17 20:07:23 +05:30
it { is_expected.to include(options: { cache: [a_hash_including(key: 'a-value')] }) }
2019-12-26 22:10:19 +05:30
2021-04-17 20:07:23 +05:30
context 'with cache:key:files' do
let(:attributes) do
{
name: 'rspec',
ref: 'master',
cache: [{
key: {
files: ['VERSION']
}
}]
}
end
it 'includes cache options' do
cache_options = {
options: {
cache: [a_hash_including(key: 'f155568ad0933d8358f66b846133614f76dd0ca4')]
2019-12-26 22:10:19 +05:30
}
}
2021-04-17 20:07:23 +05:30
is_expected.to include(cache_options)
end
2019-12-26 22:10:19 +05:30
end
2021-04-17 20:07:23 +05:30
context 'with cache:key:prefix' do
let(:attributes) do
{
name: 'rspec',
ref: 'master',
cache: [{
key: {
prefix: 'something'
}
}]
}
end
it { is_expected.to include(options: { cache: [a_hash_including( key: 'something-default' )] }) }
end
context 'with cache:key:files and prefix' do
let(:attributes) do
{
name: 'rspec',
ref: 'master',
cache: [{
key: {
files: ['VERSION'],
prefix: 'something'
}
}]
}
end
it 'includes cache options' do
cache_options = {
options: {
cache: [a_hash_including(key: 'something-f155568ad0933d8358f66b846133614f76dd0ca4')]
2019-12-26 22:10:19 +05:30
}
}
2021-04-17 20:07:23 +05:30
is_expected.to include(cache_options)
end
2019-12-26 22:10:19 +05:30
end
end
context 'with empty cache' do
let(:attributes) do
{
name: 'rspec',
ref: 'master',
cache: {}
}
end
2021-04-17 20:07:23 +05:30
it { is_expected.to include({}) }
2019-12-26 22:10:19 +05:30
end
2021-02-22 17:27:13 +05:30
context 'with allow_failure' do
let(:options) do
{ allow_failure_criteria: { exit_codes: [42] } }
end
let(:rules) do
[{ if: '$VAR == null', when: 'always' }]
end
let(:attributes) do
{
name: 'rspec',
ref: 'master',
options: options,
rules: rules
}
end
context 'when rules does not override allow_failure' do
it { is_expected.to match a_hash_including(options: options) }
end
context 'when rules set allow_failure to true' do
let(:rules) do
[{ if: '$VAR == null', when: 'always', allow_failure: true }]
end
it { is_expected.to match a_hash_including(options: { allow_failure_criteria: nil }) }
end
context 'when rules set allow_failure to false' do
let(:rules) do
[{ if: '$VAR == null', when: 'always', allow_failure: false }]
end
it { is_expected.to match a_hash_including(options: { allow_failure_criteria: nil }) }
end
end
2021-04-29 21:17:54 +05:30
context 'with workflow:rules:[variables:]' do
let(:attributes) do
{ name: 'rspec',
ref: 'master',
yaml_variables: [{ key: 'VAR2', value: 'var 2', public: true },
{ key: 'VAR3', value: 'var 3', public: true }],
job_variables: [{ key: 'VAR2', value: 'var 2', public: true },
{ key: 'VAR3', value: 'var 3', public: true }],
root_variables_inheritance: root_variables_inheritance }
end
context 'when the pipeline has variables' do
let(:root_variables) do
[{ key: 'VAR1', value: 'var overridden pipeline 1', public: true },
{ key: 'VAR2', value: 'var pipeline 2', public: true },
{ key: 'VAR3', value: 'var pipeline 3', public: true },
{ key: 'VAR4', value: 'new var pipeline 4', public: true }]
end
context 'when root_variables_inheritance is true' do
let(:root_variables_inheritance) { true }
it 'returns calculated yaml variables' do
expect(subject[:yaml_variables]).to match_array(
[{ key: 'VAR1', value: 'var overridden pipeline 1', public: true },
{ key: 'VAR2', value: 'var 2', public: true },
{ key: 'VAR3', value: 'var 3', public: true },
{ key: 'VAR4', value: 'new var pipeline 4', public: true }]
)
end
end
context 'when root_variables_inheritance is false' do
let(:root_variables_inheritance) { false }
it 'returns job variables' do
expect(subject[:yaml_variables]).to match_array(
[{ key: 'VAR2', value: 'var 2', public: true },
{ key: 'VAR3', value: 'var 3', public: true }]
)
end
end
context 'when root_variables_inheritance is an array' do
let(:root_variables_inheritance) { %w(VAR1 VAR2 VAR3) }
it 'returns calculated yaml variables' do
expect(subject[:yaml_variables]).to match_array(
[{ key: 'VAR1', value: 'var overridden pipeline 1', public: true },
{ key: 'VAR2', value: 'var 2', public: true },
{ key: 'VAR3', value: 'var 3', public: true }]
)
end
end
end
context 'when the pipeline has not a variable' do
let(:root_variables_inheritance) { true }
it 'returns seed yaml variables' do
expect(subject[:yaml_variables]).to match_array(
[{ key: 'VAR2', value: 'var 2', public: true },
{ key: 'VAR3', value: 'var 3', public: true }])
end
end
end
context 'when the job rule depends on variables' do
let(:attributes) do
{ name: 'rspec',
ref: 'master',
yaml_variables: [{ key: 'VAR1', value: 'var 1', public: true }],
job_variables: [{ key: 'VAR1', value: 'var 1', public: true }],
root_variables_inheritance: root_variables_inheritance,
rules: rules }
end
let(:root_variables_inheritance) { true }
context 'when the rules use job variables' do
let(:rules) do
[{ if: '$VAR1 == "var 1"', variables: { VAR1: 'overridden var 1', VAR2: 'new var 2' } }]
end
it 'recalculates the variables' do
expect(subject[:yaml_variables]).to contain_exactly({ key: 'VAR1', value: 'overridden var 1', public: true },
{ key: 'VAR2', value: 'new var 2', public: true })
end
end
context 'when the rules use root variables' do
let(:root_variables) do
[{ key: 'VAR2', value: 'var pipeline 2', public: true }]
end
let(:rules) do
[{ if: '$VAR2 == "var pipeline 2"', variables: { VAR1: 'overridden var 1', VAR2: 'overridden var 2' } }]
end
it 'recalculates the variables' do
expect(subject[:yaml_variables]).to contain_exactly({ key: 'VAR1', value: 'overridden var 1', public: true },
{ key: 'VAR2', value: 'overridden var 2', public: true })
end
context 'when the root_variables_inheritance is false' do
let(:root_variables_inheritance) { false }
it 'does not recalculate the variables' do
expect(subject[:yaml_variables]).to contain_exactly({ key: 'VAR1', value: 'var 1', public: true })
end
end
end
end
2018-05-09 12:01:36 +05:30
end
2019-03-02 22:35:43 +05:30
describe '#bridge?' do
2019-09-30 21:07:59 +05:30
subject { seed_build.bridge? }
2019-10-12 21:52:04 +05:30
context 'when job is a downstream bridge' do
2019-03-02 22:35:43 +05:30
let(:attributes) do
{ name: 'rspec', ref: 'master', options: { trigger: 'my/project' } }
end
2019-09-30 21:07:59 +05:30
it { is_expected.to be_truthy }
2019-10-12 21:52:04 +05:30
context 'when trigger definition is empty' do
let(:attributes) do
{ name: 'rspec', ref: 'master', options: { trigger: '' } }
end
it { is_expected.to be_falsey }
end
2019-03-02 22:35:43 +05:30
end
2019-10-12 21:52:04 +05:30
context 'when job is an upstream bridge' do
2019-03-02 22:35:43 +05:30
let(:attributes) do
2019-10-12 21:52:04 +05:30
{ name: 'rspec', ref: 'master', options: { bridge_needs: { pipeline: 'my/project' } } }
2019-03-02 22:35:43 +05:30
end
2019-10-12 21:52:04 +05:30
it { is_expected.to be_truthy }
context 'when upstream definition is empty' do
let(:attributes) do
{ name: 'rspec', ref: 'master', options: { bridge_needs: { pipeline: '' } } }
end
it { is_expected.to be_falsey }
end
2019-03-02 22:35:43 +05:30
end
context 'when job is not a bridge' do
2019-09-30 21:07:59 +05:30
it { is_expected.to be_falsey }
2019-03-02 22:35:43 +05:30
end
end
2018-05-09 12:01:36 +05:30
describe '#to_resource' do
2019-09-30 21:07:59 +05:30
subject { seed_build.to_resource }
2018-05-09 12:01:36 +05:30
it 'memoizes a resource object' do
2019-09-30 21:07:59 +05:30
expect(subject.object_id).to eq seed_build.to_resource.object_id
2018-05-09 12:01:36 +05:30
end
it 'can not be persisted without explicit assignment' do
pipeline.save!
2019-09-30 21:07:59 +05:30
expect(subject).not_to be_persisted
2018-05-09 12:01:36 +05:30
end
end
2019-09-30 21:07:59 +05:30
describe 'applying job inclusion policies' do
subject { seed_build }
2018-05-09 12:01:36 +05:30
context 'when no branch policy is specified' do
2019-09-30 21:07:59 +05:30
let(:attributes) do
{ name: 'rspec' }
end
2018-05-09 12:01:36 +05:30
it { is_expected.to be_included }
end
context 'when branch policy does not match' do
context 'when using only' do
2019-09-30 21:07:59 +05:30
let(:attributes) do
{ name: 'rspec', only: { refs: ['deploy'] } }
end
2018-05-09 12:01:36 +05:30
it { is_expected.not_to be_included }
end
context 'when using except' do
2019-09-30 21:07:59 +05:30
let(:attributes) do
{ name: 'rspec', except: { refs: ['deploy'] } }
end
2018-05-09 12:01:36 +05:30
it { is_expected.to be_included }
end
2019-09-30 21:07:59 +05:30
context 'with both only and except policies' do
let(:attributes) do
{
name: 'rspec',
only: { refs: %w[deploy] },
except: { refs: %w[deploy] }
}
end
it { is_expected.not_to be_included }
end
2018-05-09 12:01:36 +05:30
end
context 'when branch regexp policy does not match' do
context 'when using only' do
2019-09-30 21:07:59 +05:30
let(:attributes) do
{ name: 'rspec', only: { refs: %w[/^deploy$/] } }
end
2018-05-09 12:01:36 +05:30
it { is_expected.not_to be_included }
end
context 'when using except' do
2019-09-30 21:07:59 +05:30
let(:attributes) do
{ name: 'rspec', except: { refs: %w[/^deploy$/] } }
end
2018-05-09 12:01:36 +05:30
it { is_expected.to be_included }
end
2019-09-30 21:07:59 +05:30
context 'with both only and except policies' do
let(:attributes) do
{
name: 'rspec',
only: { refs: %w[/^deploy$/] },
except: { refs: %w[/^deploy$/] }
}
end
it { is_expected.not_to be_included }
end
2018-05-09 12:01:36 +05:30
end
context 'when branch policy matches' do
context 'when using only' do
2019-09-30 21:07:59 +05:30
let(:attributes) do
{ name: 'rspec', only: { refs: %w[deploy master] } }
end
2018-05-09 12:01:36 +05:30
it { is_expected.to be_included }
end
context 'when using except' do
2019-09-30 21:07:59 +05:30
let(:attributes) do
{ name: 'rspec', except: { refs: %w[deploy master] } }
end
it { is_expected.not_to be_included }
end
context 'when using both only and except policies' do
let(:attributes) do
{
name: 'rspec',
only: { refs: %w[deploy master] },
except: { refs: %w[deploy master] }
}
end
2018-05-09 12:01:36 +05:30
it { is_expected.not_to be_included }
end
end
context 'when keyword policy matches' do
context 'when using only' do
2019-09-30 21:07:59 +05:30
let(:attributes) do
{ name: 'rspec', only: { refs: %w[branches] } }
end
2018-05-09 12:01:36 +05:30
it { is_expected.to be_included }
end
context 'when using except' do
2019-09-30 21:07:59 +05:30
let(:attributes) do
{ name: 'rspec', except: { refs: %w[branches] } }
end
it { is_expected.not_to be_included }
end
context 'when using both only and except policies' do
let(:attributes) do
{
name: 'rspec',
only: { refs: %w[branches] },
except: { refs: %w[branches] }
}
end
2018-05-09 12:01:36 +05:30
it { is_expected.not_to be_included }
end
end
context 'when keyword policy does not match' do
context 'when using only' do
2019-09-30 21:07:59 +05:30
let(:attributes) do
{ name: 'rspec', only: { refs: %w[tags] } }
end
2018-05-09 12:01:36 +05:30
it { is_expected.not_to be_included }
end
context 'when using except' do
2019-09-30 21:07:59 +05:30
let(:attributes) do
{ name: 'rspec', except: { refs: %w[tags] } }
end
2018-05-09 12:01:36 +05:30
it { is_expected.to be_included }
end
2019-09-30 21:07:59 +05:30
context 'when using both only and except policies' do
let(:attributes) do
{
name: 'rspec',
only: { refs: %w[tags] },
except: { refs: %w[tags] }
}
end
it { is_expected.not_to be_included }
end
2018-05-09 12:01:36 +05:30
end
2019-09-30 21:07:59 +05:30
context 'with source-keyword policy' do
using RSpec::Parameterized
2018-05-09 12:01:36 +05:30
2019-09-30 21:07:59 +05:30
let(:pipeline) do
2021-01-03 14:25:43 +05:30
build(:ci_empty_pipeline, ref: 'deploy', tag: false, source: source, project: project)
2019-09-30 21:07:59 +05:30
end
2018-05-09 12:01:36 +05:30
2019-09-30 21:07:59 +05:30
context 'matches' do
where(:keyword, :source) do
[
%w[pushes push],
%w[web web],
%w[triggers trigger],
%w[schedules schedule],
%w[api api],
%w[external external]
]
end
with_them do
context 'using an only policy' do
let(:attributes) do
{ name: 'rspec', only: { refs: [keyword] } }
end
2018-05-09 12:01:36 +05:30
it { is_expected.to be_included }
end
2019-09-30 21:07:59 +05:30
context 'using an except policy' do
let(:attributes) do
{ name: 'rspec', except: { refs: [keyword] } }
2018-05-09 12:01:36 +05:30
end
2019-09-30 21:07:59 +05:30
it { is_expected.not_to be_included }
end
context 'using both only and except policies' do
let(:attributes) do
{
name: 'rspec',
only: { refs: [keyword] },
except: { refs: [keyword] }
}
end
2018-05-09 12:01:36 +05:30
it { is_expected.not_to be_included }
end
end
end
2019-09-30 21:07:59 +05:30
context 'non-matches' do
where(:keyword, :source) do
%w[web trigger schedule api external].map { |source| ['pushes', source] } +
%w[push trigger schedule api external].map { |source| ['web', source] } +
%w[push web schedule api external].map { |source| ['triggers', source] } +
%w[push web trigger api external].map { |source| ['schedules', source] } +
%w[push web trigger schedule external].map { |source| ['api', source] } +
%w[push web trigger schedule api].map { |source| ['external', source] }
end
2018-05-09 12:01:36 +05:30
2019-09-30 21:07:59 +05:30
with_them do
context 'using an only policy' do
let(:attributes) do
{ name: 'rspec', only: { refs: [keyword] } }
2018-05-09 12:01:36 +05:30
end
it { is_expected.not_to be_included }
end
2019-09-30 21:07:59 +05:30
context 'using an except policy' do
let(:attributes) do
{ name: 'rspec', except: { refs: [keyword] } }
2018-05-09 12:01:36 +05:30
end
it { is_expected.to be_included }
end
2019-09-30 21:07:59 +05:30
context 'using both only and except policies' do
let(:attributes) do
{
name: 'rspec',
only: { refs: [keyword] },
except: { refs: [keyword] }
}
end
it { is_expected.not_to be_included }
end
2018-05-09 12:01:36 +05:30
end
end
end
context 'when repository path matches' do
context 'when using only' do
let(:attributes) do
{ name: 'rspec', only: { refs: ["branches@#{pipeline.project_full_path}"] } }
end
it { is_expected.to be_included }
end
context 'when using except' do
let(:attributes) do
{ name: 'rspec', except: { refs: ["branches@#{pipeline.project_full_path}"] } }
end
it { is_expected.not_to be_included }
end
2019-09-30 21:07:59 +05:30
context 'when using both only and except policies' do
let(:attributes) do
{
name: 'rspec',
only: { refs: ["branches@#{pipeline.project_full_path}"] },
except: { refs: ["branches@#{pipeline.project_full_path}"] }
}
end
it { is_expected.not_to be_included }
end
2019-12-04 20:38:33 +05:30
context 'when using both only and except policies' do
let(:attributes) do
{
name: 'rspec',
only: {
refs: ["branches@#{pipeline.project_full_path}"]
},
except: {
refs: ["branches@#{pipeline.project_full_path}"]
}
}
end
it { is_expected.not_to be_included }
end
2018-05-09 12:01:36 +05:30
end
2019-12-04 20:38:33 +05:30
context 'when repository path does not match' do
2018-05-09 12:01:36 +05:30
context 'when using only' do
let(:attributes) do
2019-09-30 21:07:59 +05:30
{ name: 'rspec', only: { refs: %w[branches@fork] } }
2018-05-09 12:01:36 +05:30
end
it { is_expected.not_to be_included }
end
context 'when using except' do
let(:attributes) do
2019-09-30 21:07:59 +05:30
{ name: 'rspec', except: { refs: %w[branches@fork] } }
2018-05-09 12:01:36 +05:30
end
it { is_expected.to be_included }
end
2019-09-30 21:07:59 +05:30
context 'when using both only and except policies' do
let(:attributes) do
{
name: 'rspec',
only: { refs: %w[branches@fork] },
except: { refs: %w[branches@fork] }
}
end
it { is_expected.not_to be_included }
end
2018-05-09 12:01:36 +05:30
end
2019-12-04 20:38:33 +05:30
context 'using rules:' do
using RSpec::Parameterized
2022-01-26 12:08:38 +05:30
let(:attributes) { { name: 'rspec', rules: rule_set, when: 'on_success' } }
2019-12-04 20:38:33 +05:30
context 'with a matching if: rule' do
context 'with an explicit `when: never`' do
where(:rule_set) do
[
[[{ if: '$VARIABLE == null', when: 'never' }]],
[[{ if: '$VARIABLE == null', when: 'never' }, { if: '$VARIABLE == null', when: 'always' }]],
[[{ if: '$VARIABLE != "the wrong value"', when: 'never' }, { if: '$VARIABLE == null', when: 'always' }]]
]
end
with_them do
it { is_expected.not_to be_included }
it 'correctly populates when:' do
expect(seed_build.attributes).to include(when: 'never')
end
end
end
context 'with an explicit `when: always`' do
where(:rule_set) do
[
[[{ if: '$VARIABLE == null', when: 'always' }]],
[[{ if: '$VARIABLE == null', when: 'always' }, { if: '$VARIABLE == null', when: 'never' }]],
[[{ if: '$VARIABLE != "the wrong value"', when: 'always' }, { if: '$VARIABLE == null', when: 'never' }]]
]
end
with_them do
it { is_expected.to be_included }
it 'correctly populates when:' do
expect(seed_build.attributes).to include(when: 'always')
end
end
end
context 'with an explicit `when: on_failure`' do
where(:rule_set) do
[
[[{ if: '$CI_JOB_NAME == "rspec" && $VAR == null', when: 'on_failure' }]],
[[{ if: '$VARIABLE != null', when: 'delayed', start_in: '1 day' }, { if: '$CI_JOB_NAME == "rspec"', when: 'on_failure' }]],
[[{ if: '$VARIABLE == "the wrong value"', when: 'delayed', start_in: '1 day' }, { if: '$CI_BUILD_NAME == "rspec"', when: 'on_failure' }]]
]
end
with_them do
it { is_expected.to be_included }
it 'correctly populates when:' do
expect(seed_build.attributes).to include(when: 'on_failure')
end
end
end
context 'with an explicit `when: delayed`' do
where(:rule_set) do
[
[[{ if: '$VARIABLE == null', when: 'delayed', start_in: '1 day' }]],
[[{ if: '$VARIABLE == null', when: 'delayed', start_in: '1 day' }, { if: '$VARIABLE == null', when: 'never' }]],
[[{ if: '$VARIABLE != "the wrong value"', when: 'delayed', start_in: '1 day' }, { if: '$VARIABLE == null', when: 'never' }]]
]
end
with_them do
it { is_expected.to be_included }
it 'correctly populates when:' do
expect(seed_build.attributes).to include(when: 'delayed', options: { start_in: '1 day' })
end
end
end
context 'without an explicit when: value' do
where(:rule_set) do
[
[[{ if: '$VARIABLE == null' }]],
[[{ if: '$VARIABLE == null' }, { if: '$VARIABLE == null' }]],
[[{ if: '$VARIABLE != "the wrong value"' }, { if: '$VARIABLE == null' }]]
]
end
with_them do
it { is_expected.to be_included }
it 'correctly populates when:' do
expect(seed_build.attributes).to include(when: 'on_success')
end
end
end
end
context 'with a matching changes: rule' do
let(:pipeline) do
2021-01-03 14:25:43 +05:30
build(:ci_pipeline, project: project).tap do |pipeline|
2019-12-04 20:38:33 +05:30
stub_pipeline_modified_paths(pipeline, %w[app/models/ci/pipeline.rb spec/models/ci/pipeline_spec.rb .gitlab-ci.yml])
end
end
context 'with an explicit `when: never`' do
where(:rule_set) do
[
[[{ changes: %w[*/**/*.rb], when: 'never' }, { changes: %w[*/**/*.rb], when: 'always' }]],
[[{ changes: %w[app/models/ci/pipeline.rb], when: 'never' }, { changes: %w[app/models/ci/pipeline.rb], when: 'always' }]],
[[{ changes: %w[spec/**/*.rb], when: 'never' }, { changes: %w[spec/**/*.rb], when: 'always' }]],
[[{ changes: %w[*.yml], when: 'never' }, { changes: %w[*.yml], when: 'always' }]],
[[{ changes: %w[.*.yml], when: 'never' }, { changes: %w[.*.yml], when: 'always' }]],
[[{ changes: %w[**/*], when: 'never' }, { changes: %w[**/*], when: 'always' }]],
[[{ changes: %w[*/**/*.rb *.yml], when: 'never' }, { changes: %w[*/**/*.rb *.yml], when: 'always' }]],
[[{ changes: %w[.*.yml **/*], when: 'never' }, { changes: %w[.*.yml **/*], when: 'always' }]]
]
end
with_them do
it { is_expected.not_to be_included }
it 'correctly populates when:' do
expect(seed_build.attributes).to include(when: 'never')
end
end
end
context 'with an explicit `when: always`' do
where(:rule_set) do
[
[[{ changes: %w[*/**/*.rb], when: 'always' }, { changes: %w[*/**/*.rb], when: 'never' }]],
[[{ changes: %w[app/models/ci/pipeline.rb], when: 'always' }, { changes: %w[app/models/ci/pipeline.rb], when: 'never' }]],
[[{ changes: %w[spec/**/*.rb], when: 'always' }, { changes: %w[spec/**/*.rb], when: 'never' }]],
[[{ changes: %w[*.yml], when: 'always' }, { changes: %w[*.yml], when: 'never' }]],
[[{ changes: %w[.*.yml], when: 'always' }, { changes: %w[.*.yml], when: 'never' }]],
[[{ changes: %w[**/*], when: 'always' }, { changes: %w[**/*], when: 'never' }]],
[[{ changes: %w[*/**/*.rb *.yml], when: 'always' }, { changes: %w[*/**/*.rb *.yml], when: 'never' }]],
[[{ changes: %w[.*.yml **/*], when: 'always' }, { changes: %w[.*.yml **/*], when: 'never' }]]
]
end
with_them do
it { is_expected.to be_included }
it 'correctly populates when:' do
expect(seed_build.attributes).to include(when: 'always')
end
end
end
context 'without an explicit when: value' do
where(:rule_set) do
[
[[{ changes: %w[*/**/*.rb] }]],
[[{ changes: %w[app/models/ci/pipeline.rb] }]],
[[{ changes: %w[spec/**/*.rb] }]],
[[{ changes: %w[*.yml] }]],
[[{ changes: %w[.*.yml] }]],
[[{ changes: %w[**/*] }]],
[[{ changes: %w[*/**/*.rb *.yml] }]],
[[{ changes: %w[.*.yml **/*] }]]
]
end
with_them do
it { is_expected.to be_included }
it 'correctly populates when:' do
expect(seed_build.attributes).to include(when: 'on_success')
end
end
end
end
context 'with no matching rule' do
where(:rule_set) do
[
[[{ if: '$VARIABLE != null', when: 'never' }]],
[[{ if: '$VARIABLE != null', when: 'never' }, { if: '$VARIABLE != null', when: 'always' }]],
[[{ if: '$VARIABLE == "the wrong value"', when: 'never' }, { if: '$VARIABLE != null', when: 'always' }]],
[[{ if: '$VARIABLE != null', when: 'always' }]],
[[{ if: '$VARIABLE != null', when: 'always' }, { if: '$VARIABLE != null', when: 'never' }]],
[[{ if: '$VARIABLE == "the wrong value"', when: 'always' }, { if: '$VARIABLE != null', when: 'never' }]],
[[{ if: '$VARIABLE != null' }]],
[[{ if: '$VARIABLE != null' }, { if: '$VARIABLE != null' }]],
[[{ if: '$VARIABLE == "the wrong value"' }, { if: '$VARIABLE != null' }]]
]
end
with_them do
it { is_expected.not_to be_included }
it 'correctly populates when:' do
expect(seed_build.attributes).to include(when: 'never')
end
end
end
context 'with no rules' do
let(:rule_set) { [] }
it { is_expected.not_to be_included }
it 'correctly populates when:' do
expect(seed_build.attributes).to include(when: 'never')
end
end
end
2018-05-09 12:01:36 +05:30
end
2019-10-12 21:52:04 +05:30
describe 'applying needs: dependency' do
subject { seed_build }
let(:needs_count) { 1 }
let(:needs_attributes) do
Array.new(needs_count, name: 'build')
end
let(:attributes) do
{
name: 'rspec',
needs_attributes: needs_attributes
}
end
context 'when build job is not present in prior stages' do
it "is included" do
is_expected.to be_included
end
it "returns an error" do
expect(subject.errors).to contain_exactly(
2021-09-30 23:02:18 +05:30
"'rspec' job needs 'build' job, but 'build' is not in any previous stage")
2019-10-12 21:52:04 +05:30
end
2021-04-17 20:07:23 +05:30
context 'when the needed job is optional' do
let(:needs_attributes) { [{ name: 'build', optional: true }] }
it "does not return an error" do
expect(subject.errors).to be_empty
end
end
2019-10-12 21:52:04 +05:30
end
context 'when build job is part of prior stages' do
let(:stage_attributes) do
{
name: 'build',
index: 0,
builds: [{ name: 'build' }]
}
end
let(:stage_seed) do
2021-04-29 21:17:54 +05:30
Gitlab::Ci::Pipeline::Seed::Stage.new(seed_context, stage_attributes, [])
2019-10-12 21:52:04 +05:30
end
let(:previous_stages) { [stage_seed] }
it "is included" do
is_expected.to be_included
end
it "does not have errors" do
expect(subject.errors).to be_empty
end
end
2021-09-30 23:02:18 +05:30
context 'when build job is part of the same stage' do
let(:current_stage) { double(seeds_names: [attributes[:name], 'build']) }
it 'is included' do
is_expected.to be_included
end
it 'does not have errors' do
expect(subject.errors).to be_empty
end
end
2020-10-24 23:57:45 +05:30
context 'when using 101 needs' do
let(:needs_count) { 101 }
2019-10-12 21:52:04 +05:30
2020-11-24 15:15:51 +05:30
it "returns an error" do
expect(subject.errors).to contain_exactly(
"rspec: one job can only need 50 others, but you have listed 101. See needs keyword documentation for more details")
end
context 'when ci_needs_size_limit is set to 100' do
2020-10-24 23:57:45 +05:30
before do
2020-11-24 15:15:51 +05:30
project.actual_limits.update!(ci_needs_size_limit: 100)
2020-10-24 23:57:45 +05:30
end
2019-10-12 21:52:04 +05:30
2020-10-24 23:57:45 +05:30
it "returns an error" do
expect(subject.errors).to contain_exactly(
2020-11-24 15:15:51 +05:30
"rspec: one job can only need 100 others, but you have listed 101. See needs keyword documentation for more details")
2020-10-24 23:57:45 +05:30
end
2019-10-12 21:52:04 +05:30
end
2020-11-24 15:15:51 +05:30
context 'when ci_needs_size_limit is set to 0' do
2020-10-24 23:57:45 +05:30
before do
2020-11-24 15:15:51 +05:30
project.actual_limits.update!(ci_needs_size_limit: 0)
2020-10-24 23:57:45 +05:30
end
2019-10-12 21:52:04 +05:30
2020-10-24 23:57:45 +05:30
it "returns an error" do
expect(subject.errors).to contain_exactly(
2020-11-24 15:15:51 +05:30
"rspec: one job can only need 0 others, but you have listed 101. See needs keyword documentation for more details")
2020-10-24 23:57:45 +05:30
end
2019-10-12 21:52:04 +05:30
end
end
end
2021-04-17 20:07:23 +05:30
describe 'applying pipeline variables' do
subject { seed_build }
let(:pipeline_variables) { [] }
let(:pipeline) do
build(:ci_empty_pipeline, project: project, sha: head_sha, variables: pipeline_variables)
end
context 'containing variable references' do
let(:pipeline_variables) do
[
build(:ci_pipeline_variable, key: 'A', value: '$B'),
build(:ci_pipeline_variable, key: 'B', value: '$C')
]
end
2021-12-11 22:18:48 +05:30
it "does not have errors" do
expect(subject.errors).to be_empty
2021-04-17 20:07:23 +05:30
end
end
context 'containing cyclic reference' do
let(:pipeline_variables) do
[
build(:ci_pipeline_variable, key: 'A', value: '$B'),
build(:ci_pipeline_variable, key: 'B', value: '$C'),
build(:ci_pipeline_variable, key: 'C', value: '$A')
]
end
2021-12-11 22:18:48 +05:30
it "returns an error" do
expect(subject.errors).to contain_exactly(
'rspec: circular variable reference detected: ["A", "B", "C"]')
2021-04-17 20:07:23 +05:30
end
2021-12-11 22:18:48 +05:30
context 'with job:rules:[if:]' do
let(:attributes) { { name: 'rspec', ref: 'master', rules: [{ if: '$C != null', when: 'always' }] } }
2021-04-17 20:07:23 +05:30
2021-12-11 22:18:48 +05:30
it "included? does not raise" do
expect { subject.included? }.not_to raise_error
2021-04-17 20:07:23 +05:30
end
2021-12-11 22:18:48 +05:30
it "included? returns true" do
expect(subject.included?).to eq(true)
2021-04-17 20:07:23 +05:30
end
end
end
end
2018-05-09 12:01:36 +05:30
end