summaryrefslogtreecommitdiff
path: root/spec/services/ci/create_pipeline_service_spec.rb
diff options
context:
space:
mode:
Diffstat (limited to 'spec/services/ci/create_pipeline_service_spec.rb')
-rw-r--r--spec/services/ci/create_pipeline_service_spec.rb815
1 files changed, 2 insertions, 813 deletions
diff --git a/spec/services/ci/create_pipeline_service_spec.rb b/spec/services/ci/create_pipeline_service_spec.rb
index 9cef7f7dadb..a9442b0dc68 100644
--- a/spec/services/ci/create_pipeline_service_spec.rb
+++ b/spec/services/ci/create_pipeline_service_spec.rb
@@ -18,6 +18,7 @@ RSpec.describe Ci::CreatePipelineService do
# rubocop:disable Metrics/ParameterLists
def execute_service(
source: :push,
+ before: '00000000',
after: project.commit.id,
ref: ref_name,
trigger_request: nil,
@@ -29,7 +30,7 @@ RSpec.describe Ci::CreatePipelineService do
target_sha: nil,
save_on_errors: true)
params = { ref: ref,
- before: '00000000',
+ before: before,
after: after,
variables_attributes: variables_attributes,
push_options: push_options,
@@ -1865,818 +1866,6 @@ RSpec.describe Ci::CreatePipelineService do
end
end
end
-
- context 'when rules are used' do
- let(:ref_name) { 'refs/heads/master' }
- let(:response) { execute_service }
- let(:pipeline) { response.payload }
- let(:build_names) { pipeline.builds.pluck(:name) }
- let(:regular_job) { find_job('regular-job') }
- let(:rules_job) { find_job('rules-job') }
- let(:delayed_job) { find_job('delayed-job') }
-
- context 'with when:manual' do
- let(:config) do
- <<-EOY
- job-with-rules:
- script: 'echo hey'
- rules:
- - if: $CI_COMMIT_REF_NAME =~ /master/
-
- job-when-with-rules:
- script: 'echo hey'
- when: manual
- rules:
- - if: $CI_COMMIT_REF_NAME =~ /master/
-
- job-when-with-rules-when:
- script: 'echo hey'
- when: manual
- rules:
- - if: $CI_COMMIT_REF_NAME =~ /master/
- when: on_success
-
- job-with-rules-when:
- script: 'echo hey'
- rules:
- - if: $CI_COMMIT_REF_NAME =~ /master/
- when: manual
-
- job-without-rules:
- script: 'echo this is a job with NO rules'
- EOY
- end
-
- let(:job_with_rules) { find_job('job-with-rules') }
- let(:job_when_with_rules) { find_job('job-when-with-rules') }
- let(:job_when_with_rules_when) { find_job('job-when-with-rules-when') }
- let(:job_with_rules_when) { find_job('job-with-rules-when') }
- let(:job_without_rules) { find_job('job-without-rules') }
-
- context 'when matching the rules' do
- let(:ref_name) { 'refs/heads/master' }
-
- it 'adds the job-with-rules with a when:manual' do
- expect(job_with_rules).to be_persisted
- expect(job_when_with_rules).to be_persisted
- expect(job_when_with_rules_when).to be_persisted
- expect(job_with_rules_when).to be_persisted
- expect(job_without_rules).to be_persisted
-
- expect(job_with_rules.when).to eq('on_success')
- expect(job_when_with_rules.when).to eq('manual')
- expect(job_when_with_rules_when.when).to eq('on_success')
- expect(job_with_rules_when.when).to eq('manual')
- expect(job_without_rules.when).to eq('on_success')
- end
- end
-
- context 'when there is no match to the rule' do
- let(:ref_name) { 'refs/heads/wip' }
-
- it 'does not add job_with_rules' do
- expect(job_with_rules).to be_nil
- expect(job_when_with_rules).to be_nil
- expect(job_when_with_rules_when).to be_nil
- expect(job_with_rules_when).to be_nil
- expect(job_without_rules).to be_persisted
- end
- end
- end
-
- shared_examples 'rules jobs are excluded' do
- it 'only persists the job without rules' do
- expect(pipeline).to be_persisted
- expect(regular_job).to be_persisted
- expect(rules_job).to be_nil
- expect(delayed_job).to be_nil
- end
- end
-
- def find_job(name)
- pipeline.builds.find_by(name: name)
- end
-
- before do
- stub_ci_pipeline_yaml_file(config)
- allow_any_instance_of(Ci::BuildScheduleWorker).to receive(:perform).and_return(true)
- end
-
- context 'with simple if: clauses' do
- let(:config) do
- <<-EOY
- regular-job:
- script: 'echo Hello, World!'
-
- master-job:
- script: "echo hello world, $CI_COMMIT_REF_NAME"
- rules:
- - if: $CI_COMMIT_REF_NAME == "nonexistant-branch"
- when: never
- - if: $CI_COMMIT_REF_NAME =~ /master/
- when: manual
-
- negligible-job:
- script: "exit 1"
- rules:
- - if: $CI_COMMIT_REF_NAME =~ /master/
- allow_failure: true
-
- delayed-job:
- script: "echo See you later, World!"
- rules:
- - if: $CI_COMMIT_REF_NAME =~ /master/
- when: delayed
- start_in: 1 hour
-
- never-job:
- script: "echo Goodbye, World!"
- rules:
- - if: $CI_COMMIT_REF_NAME
- when: never
- EOY
- end
-
- context 'with matches' do
- it 'creates a pipeline with the vanilla and manual jobs' do
- expect(pipeline).to be_persisted
- expect(build_names).to contain_exactly(
- 'regular-job', 'delayed-job', 'master-job', 'negligible-job'
- )
- end
-
- it 'assigns job:when values to the builds' do
- expect(find_job('regular-job').when).to eq('on_success')
- expect(find_job('master-job').when).to eq('manual')
- expect(find_job('negligible-job').when).to eq('on_success')
- expect(find_job('delayed-job').when).to eq('delayed')
- end
-
- it 'assigns job:allow_failure values to the builds' do
- expect(find_job('regular-job').allow_failure).to eq(false)
- expect(find_job('master-job').allow_failure).to eq(false)
- expect(find_job('negligible-job').allow_failure).to eq(true)
- expect(find_job('delayed-job').allow_failure).to eq(false)
- end
-
- it 'assigns start_in for delayed jobs' do
- expect(delayed_job.options[:start_in]).to eq('1 hour')
- end
- end
-
- context 'with no matches' do
- let(:ref_name) { 'refs/heads/feature' }
-
- it_behaves_like 'rules jobs are excluded'
- end
- end
-
- context 'with complex if: clauses' do
- let(:config) do
- <<-EOY
- regular-job:
- script: 'echo Hello, World!'
- rules:
- - if: $VAR == 'present' && $OTHER || $CI_COMMIT_REF_NAME
- when: manual
- allow_failure: true
- EOY
- end
-
- it 'matches the first rule' do
- expect(pipeline).to be_persisted
- expect(build_names).to contain_exactly('regular-job')
- expect(regular_job.when).to eq('manual')
- expect(regular_job.allow_failure).to eq(true)
- end
- end
-
- context 'with changes:' do
- let(:config) do
- <<-EOY
- regular-job:
- script: 'echo Hello, World!'
-
- rules-job:
- script: "echo hello world, $CI_COMMIT_REF_NAME"
- rules:
- - changes:
- - README.md
- when: manual
- - changes:
- - app.rb
- when: on_success
-
- delayed-job:
- script: "echo See you later, World!"
- rules:
- - changes:
- - README.md
- when: delayed
- start_in: 4 hours
-
- negligible-job:
- script: "can be failed sometimes"
- rules:
- - changes:
- - README.md
- allow_failure: true
-
- README:
- script: "I use variables for changes!"
- rules:
- - changes:
- - $CI_JOB_NAME*
-
- changes-paths:
- script: "I am using a new syntax!"
- rules:
- - changes:
- paths: [README.md]
- EOY
- end
-
- context 'and matches' do
- before do
- allow_any_instance_of(Ci::Pipeline)
- .to receive(:modified_paths).and_return(%w[README.md])
- end
-
- it 'creates five jobs' do
- expect(pipeline).to be_persisted
- expect(build_names).to contain_exactly(
- 'regular-job', 'rules-job', 'delayed-job', 'negligible-job', 'README', 'changes-paths'
- )
- end
-
- it 'sets when: for all jobs' do
- expect(regular_job.when).to eq('on_success')
- expect(rules_job.when).to eq('manual')
- expect(delayed_job.when).to eq('delayed')
- expect(delayed_job.options[:start_in]).to eq('4 hours')
- end
-
- it 'sets allow_failure: for negligible job' do
- expect(find_job('negligible-job').allow_failure).to eq(true)
- end
- end
-
- context 'and matches the second rule' do
- before do
- allow_any_instance_of(Ci::Pipeline)
- .to receive(:modified_paths).and_return(%w[app.rb])
- end
-
- it 'includes both jobs' do
- expect(pipeline).to be_persisted
- expect(build_names).to contain_exactly('regular-job', 'rules-job')
- end
-
- it 'sets when: for the created rules job based on the second clause' do
- expect(regular_job.when).to eq('on_success')
- expect(rules_job.when).to eq('on_success')
- end
- end
-
- context 'and does not match' do
- before do
- allow_any_instance_of(Ci::Pipeline)
- .to receive(:modified_paths).and_return(%w[useless_script.rb])
- end
-
- it_behaves_like 'rules jobs are excluded'
-
- it 'sets when: for the created job' do
- expect(regular_job.when).to eq('on_success')
- end
- end
- end
-
- context 'with mixed if: and changes: rules' do
- let(:config) do
- <<-EOY
- regular-job:
- script: 'echo Hello, World!'
-
- rules-job:
- script: "echo hello world, $CI_COMMIT_REF_NAME"
- allow_failure: true
- rules:
- - changes:
- - README.md
- when: manual
- - if: $CI_COMMIT_REF_NAME == "master"
- when: on_success
- allow_failure: false
-
- delayed-job:
- script: "echo See you later, World!"
- rules:
- - changes:
- - README.md
- when: delayed
- start_in: 4 hours
- allow_failure: true
- - if: $CI_COMMIT_REF_NAME == "master"
- when: delayed
- start_in: 1 hour
- EOY
- end
-
- context 'and changes: matches before if' do
- before do
- allow_any_instance_of(Ci::Pipeline)
- .to receive(:modified_paths).and_return(%w[README.md])
- end
-
- it 'creates two jobs' do
- expect(pipeline).to be_persisted
- expect(build_names)
- .to contain_exactly('regular-job', 'rules-job', 'delayed-job')
- end
-
- it 'sets when: for all jobs' do
- expect(regular_job.when).to eq('on_success')
- expect(rules_job.when).to eq('manual')
- expect(delayed_job.when).to eq('delayed')
- expect(delayed_job.options[:start_in]).to eq('4 hours')
- end
-
- it 'sets allow_failure: for all jobs' do
- expect(regular_job.allow_failure).to eq(false)
- expect(rules_job.allow_failure).to eq(true)
- expect(delayed_job.allow_failure).to eq(true)
- end
- end
-
- context 'and if: matches after changes' do
- it 'includes both jobs' do
- expect(pipeline).to be_persisted
- expect(build_names).to contain_exactly('regular-job', 'rules-job', 'delayed-job')
- end
-
- it 'sets when: for the created rules job based on the second clause' do
- expect(regular_job.when).to eq('on_success')
- expect(rules_job.when).to eq('on_success')
- expect(delayed_job.when).to eq('delayed')
- expect(delayed_job.options[:start_in]).to eq('1 hour')
- end
- end
-
- context 'and does not match' do
- let(:ref_name) { 'refs/heads/wip' }
-
- it_behaves_like 'rules jobs are excluded'
-
- it 'sets when: for the created job' do
- expect(regular_job.when).to eq('on_success')
- end
- end
- end
-
- context 'with mixed if: and changes: clauses' do
- let(:config) do
- <<-EOY
- regular-job:
- script: 'echo Hello, World!'
-
- rules-job:
- script: "echo hello world, $CI_COMMIT_REF_NAME"
- rules:
- - if: $CI_COMMIT_REF_NAME =~ /master/
- changes: [README.md]
- when: on_success
- allow_failure: true
- - if: $CI_COMMIT_REF_NAME =~ /master/
- changes: [app.rb]
- when: manual
- EOY
- end
-
- context 'with if matches and changes matches' do
- before do
- allow_any_instance_of(Ci::Pipeline)
- .to receive(:modified_paths).and_return(%w[app.rb])
- end
-
- it 'persists all jobs' do
- expect(pipeline).to be_persisted
- expect(regular_job).to be_persisted
- expect(rules_job).to be_persisted
- expect(rules_job.when).to eq('manual')
- expect(rules_job.allow_failure).to eq(false)
- end
- end
-
- context 'with if matches and no change matches' do
- it_behaves_like 'rules jobs are excluded'
- end
-
- context 'with change matches and no if matches' do
- let(:ref_name) { 'refs/heads/feature' }
-
- before do
- allow_any_instance_of(Ci::Pipeline)
- .to receive(:modified_paths).and_return(%w[README.md])
- end
-
- it_behaves_like 'rules jobs are excluded'
- end
-
- context 'and no matches' do
- let(:ref_name) { 'refs/heads/feature' }
-
- it_behaves_like 'rules jobs are excluded'
- end
- end
-
- context 'with complex if: allow_failure usages' do
- let(:config) do
- <<-EOY
- job-1:
- script: "exit 1"
- allow_failure: true
- rules:
- - if: $CI_COMMIT_REF_NAME =~ /master/
- allow_failure: false
-
- job-2:
- script: "exit 1"
- allow_failure: true
- rules:
- - if: $CI_COMMIT_REF_NAME =~ /nonexistant-branch/
- allow_failure: false
-
- job-3:
- script: "exit 1"
- rules:
- - if: $CI_COMMIT_REF_NAME =~ /nonexistant-branch/
- allow_failure: true
-
- job-4:
- script: "exit 1"
- rules:
- - if: $CI_COMMIT_REF_NAME =~ /master/
- allow_failure: false
-
- job-5:
- script: "exit 1"
- allow_failure: false
- rules:
- - if: $CI_COMMIT_REF_NAME =~ /master/
- allow_failure: true
-
- job-6:
- script: "exit 1"
- rules:
- - if: $CI_COMMIT_REF_NAME =~ /nonexistant-branch/
- allow_failure: false
- - allow_failure: true
- EOY
- end
-
- it 'creates a pipeline' do
- expect(pipeline).to be_persisted
- expect(build_names).to contain_exactly('job-1', 'job-4', 'job-5', 'job-6')
- end
-
- it 'assigns job:allow_failure values to the builds' do
- expect(find_job('job-1').allow_failure).to eq(false)
- expect(find_job('job-4').allow_failure).to eq(false)
- expect(find_job('job-5').allow_failure).to eq(true)
- expect(find_job('job-6').allow_failure).to eq(true)
- end
- end
-
- context 'with complex if: allow_failure & when usages' do
- let(:config) do
- <<-EOY
- job-1:
- script: "exit 1"
- rules:
- - if: $CI_COMMIT_REF_NAME =~ /master/
- when: manual
-
- job-2:
- script: "exit 1"
- rules:
- - if: $CI_COMMIT_REF_NAME =~ /master/
- when: manual
- allow_failure: true
-
- job-3:
- script: "exit 1"
- allow_failure: true
- rules:
- - if: $CI_COMMIT_REF_NAME =~ /master/
- when: manual
-
- job-4:
- script: "exit 1"
- allow_failure: true
- rules:
- - if: $CI_COMMIT_REF_NAME =~ /master/
- when: manual
- allow_failure: false
-
- job-5:
- script: "exit 1"
- rules:
- - if: $CI_COMMIT_REF_NAME =~ /nonexistant-branch/
- when: manual
- allow_failure: false
- - when: always
- allow_failure: true
-
- job-6:
- script: "exit 1"
- allow_failure: false
- rules:
- - if: $CI_COMMIT_REF_NAME =~ /master/
- when: manual
-
- job-7:
- script: "exit 1"
- allow_failure: false
- rules:
- - if: $CI_COMMIT_REF_NAME =~ /nonexistant-branch/
- when: manual
- - when: :on_failure
- allow_failure: true
- EOY
- end
-
- it 'creates a pipeline' do
- expect(pipeline).to be_persisted
- expect(build_names).to contain_exactly(
- 'job-1', 'job-2', 'job-3', 'job-4', 'job-5', 'job-6', 'job-7'
- )
- end
-
- it 'assigns job:allow_failure values to the builds' do
- expect(find_job('job-1').allow_failure).to eq(false)
- expect(find_job('job-2').allow_failure).to eq(true)
- expect(find_job('job-3').allow_failure).to eq(true)
- expect(find_job('job-4').allow_failure).to eq(false)
- expect(find_job('job-5').allow_failure).to eq(true)
- expect(find_job('job-6').allow_failure).to eq(false)
- expect(find_job('job-7').allow_failure).to eq(true)
- end
-
- it 'assigns job:when values to the builds' do
- expect(find_job('job-1').when).to eq('manual')
- expect(find_job('job-2').when).to eq('manual')
- expect(find_job('job-3').when).to eq('manual')
- expect(find_job('job-4').when).to eq('manual')
- expect(find_job('job-5').when).to eq('always')
- expect(find_job('job-6').when).to eq('manual')
- expect(find_job('job-7').when).to eq('on_failure')
- end
- end
-
- context 'with deploy freeze period `if:` clause' do
- # '0 23 * * 5' == "At 23:00 on Friday."", '0 7 * * 1' == "At 07:00 on Monday.""
- let!(:freeze_period) { create(:ci_freeze_period, project: project, freeze_start: '0 23 * * 5', freeze_end: '0 7 * * 1') }
-
- context 'with 2 jobs' do
- let(:config) do
- <<-EOY
- stages:
- - test
- - deploy
-
- test-job:
- script:
- - echo 'running TEST stage'
-
- deploy-job:
- stage: deploy
- script:
- - echo 'running DEPLOY stage'
- rules:
- - if: $CI_DEPLOY_FREEZE == null
- EOY
- end
-
- context 'when outside freeze period' do
- it 'creates two jobs' do
- Timecop.freeze(2020, 4, 10, 22, 59) do
- expect(pipeline).to be_persisted
- expect(build_names).to contain_exactly('test-job', 'deploy-job')
- end
- end
- end
-
- context 'when inside freeze period' do
- it 'creates one job' do
- Timecop.freeze(2020, 4, 10, 23, 1) do
- expect(pipeline).to be_persisted
- expect(build_names).to contain_exactly('test-job')
- end
- end
- end
- end
-
- context 'with 1 job' do
- let(:config) do
- <<-EOY
- stages:
- - deploy
-
- deploy-job:
- stage: deploy
- script:
- - echo 'running DEPLOY stage'
- rules:
- - if: $CI_DEPLOY_FREEZE == null
- EOY
- end
-
- context 'when outside freeze period' do
- it 'creates two jobs' do
- Timecop.freeze(2020, 4, 10, 22, 59) do
- expect(pipeline).to be_persisted
- expect(build_names).to contain_exactly('deploy-job')
- end
- end
- end
-
- context 'when inside freeze period' do
- it 'does not create the pipeline', :aggregate_failures do
- Timecop.freeze(2020, 4, 10, 23, 1) do
- expect(response).to be_error
- expect(pipeline).not_to be_persisted
- end
- end
- end
- end
- end
-
- context 'with workflow rules with persisted variables' do
- let(:config) do
- <<-EOY
- workflow:
- rules:
- - if: $CI_COMMIT_REF_NAME == "master"
-
- regular-job:
- script: 'echo Hello, World!'
- EOY
- end
-
- context 'with matches' do
- it 'creates a pipeline' do
- expect(pipeline).to be_persisted
- expect(build_names).to contain_exactly('regular-job')
- end
- end
-
- context 'with no matches' do
- let(:ref_name) { 'refs/heads/feature' }
-
- it 'does not create a pipeline', :aggregate_failures do
- expect(response).to be_error
- expect(pipeline).not_to be_persisted
- end
- end
- end
-
- context 'with workflow rules with pipeline variables' do
- let(:pipeline) do
- execute_service(variables_attributes: variables_attributes).payload
- end
-
- let(:config) do
- <<-EOY
- workflow:
- rules:
- - if: $SOME_VARIABLE
-
- regular-job:
- script: 'echo Hello, World!'
- EOY
- end
-
- context 'with matches' do
- let(:variables_attributes) do
- [{ key: 'SOME_VARIABLE', secret_value: 'SOME_VAR' }]
- end
-
- it 'creates a pipeline' do
- expect(pipeline).to be_persisted
- expect(build_names).to contain_exactly('regular-job')
- end
- end
-
- context 'with no matches' do
- let(:variables_attributes) { {} }
-
- it 'does not create a pipeline', :aggregate_failures do
- expect(response).to be_error
- expect(pipeline).not_to be_persisted
- end
- end
- end
-
- context 'with workflow rules with trigger variables' do
- let(:pipeline) do
- execute_service do |pipeline|
- pipeline.variables.build(variables)
- end.payload
- end
-
- let(:config) do
- <<-EOY
- workflow:
- rules:
- - if: $SOME_VARIABLE
-
- regular-job:
- script: 'echo Hello, World!'
- EOY
- end
-
- context 'with matches' do
- let(:variables) do
- [{ key: 'SOME_VARIABLE', secret_value: 'SOME_VAR' }]
- end
-
- it 'creates a pipeline' do
- expect(pipeline).to be_persisted
- expect(build_names).to contain_exactly('regular-job')
- end
-
- context 'when a job requires the same variable' do
- let(:config) do
- <<-EOY
- workflow:
- rules:
- - if: $SOME_VARIABLE
-
- build:
- stage: build
- script: 'echo build'
- rules:
- - if: $SOME_VARIABLE
-
- test1:
- stage: test
- script: 'echo test1'
- needs: [build]
-
- test2:
- stage: test
- script: 'echo test2'
- EOY
- end
-
- it 'creates a pipeline' do
- expect(pipeline).to be_persisted
- expect(build_names).to contain_exactly('build', 'test1', 'test2')
- end
- end
- end
-
- context 'with no matches' do
- let(:variables) { {} }
-
- it 'does not create a pipeline', :aggregate_failures do
- expect(response).to be_error
- expect(pipeline).not_to be_persisted
- end
-
- context 'when a job requires the same variable' do
- let(:config) do
- <<-EOY
- workflow:
- rules:
- - if: $SOME_VARIABLE
-
- build:
- stage: build
- script: 'echo build'
- rules:
- - if: $SOME_VARIABLE
-
- test1:
- stage: test
- script: 'echo test1'
- needs: [build]
-
- test2:
- stage: test
- script: 'echo test2'
- EOY
- end
-
- it 'does not create a pipeline', :aggregate_failures do
- expect(response).to be_error
- expect(pipeline).not_to be_persisted
- end
- end
- end
- end
- end
end
describe '#execute!' do