diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2019-11-18 18:06:53 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2019-11-18 18:06:53 +0000 |
commit | 143f196f8b3c40ceb7e9335a8dcc712b079519b9 (patch) | |
tree | 909df13e1f99b456287934741ba466b506e01129 /spec/lib/gitlab/ci | |
parent | 575ccb036ea14c6a899482a83bd985ffbc992077 (diff) | |
download | gitlab-ce-143f196f8b3c40ceb7e9335a8dcc712b079519b9.tar.gz |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec/lib/gitlab/ci')
5 files changed, 205 insertions, 199 deletions
diff --git a/spec/lib/gitlab/ci/pipeline/chain/build_spec.rb b/spec/lib/gitlab/ci/pipeline/chain/build_spec.rb index ba4f841cf43..a631cd2777b 100644 --- a/spec/lib/gitlab/ci/pipeline/chain/build_spec.rb +++ b/spec/lib/gitlab/ci/pipeline/chain/build_spec.rb @@ -11,6 +11,7 @@ describe Gitlab::Ci::Pipeline::Chain::Build do [{ key: 'first', secret_value: 'world' }, { key: 'second', secret_value: 'second_world' }] end + let(:command) do Gitlab::Ci::Pipeline::Chain::Command.new( source: :push, @@ -51,12 +52,6 @@ describe Gitlab::Ci::Pipeline::Chain::Build do .to eq variables_attributes.map(&:with_indifferent_access) end - it 'sets a valid config source' do - step.perform! - - expect(pipeline.repository_source?).to be true - end - it 'returns a valid pipeline' do step.perform! diff --git a/spec/lib/gitlab/ci/pipeline/chain/populate_spec.rb b/spec/lib/gitlab/ci/pipeline/chain/populate_spec.rb index 75160a93ba7..52e9432dc92 100644 --- a/spec/lib/gitlab/ci/pipeline/chain/populate_spec.rb +++ b/spec/lib/gitlab/ci/pipeline/chain/populate_spec.rb @@ -18,19 +18,32 @@ describe Gitlab::Ci::Pipeline::Chain::Populate do seeds_block: nil) end + let(:dependencies) do + [ + Gitlab::Ci::Pipeline::Chain::Config::Content.new(pipeline, command), + Gitlab::Ci::Pipeline::Chain::Config::Process.new(pipeline, command), + Gitlab::Ci::Pipeline::Chain::Seed.new(pipeline, command) + ] + end + let(:step) { described_class.new(pipeline, command) } let(:config) do { rspec: { script: 'rspec' } } end + def run_chain + dependencies.map(&:perform!) + step.perform! + end + before do stub_ci_pipeline_yaml_file(YAML.dump(config)) end context 'when pipeline doesn not have seeds block' do before do - step.perform! + run_chain end it 'does not persist the pipeline' do @@ -66,7 +79,7 @@ describe Gitlab::Ci::Pipeline::Chain::Populate do end before do - step.perform! + run_chain end it 'breaks the chain' do @@ -84,16 +97,16 @@ describe Gitlab::Ci::Pipeline::Chain::Populate do end describe 'pipeline protect' do - subject { step.perform! } - context 'when ref is protected' do before do allow(project).to receive(:protected_for?).with('master').and_return(true) allow(project).to receive(:protected_for?).with('refs/heads/master').and_return(true) + + dependencies.map(&:perform!) end it 'does not protect the pipeline' do - subject + run_chain expect(pipeline.protected).to eq(true) end @@ -101,7 +114,7 @@ describe Gitlab::Ci::Pipeline::Chain::Populate do context 'when ref is not protected' do it 'does not protect the pipeline' do - subject + run_chain expect(pipeline.protected).to eq(false) end @@ -114,7 +127,7 @@ describe Gitlab::Ci::Pipeline::Chain::Populate do end before do - step.perform! + run_chain end it 'breaks the chain' do @@ -146,7 +159,7 @@ describe Gitlab::Ci::Pipeline::Chain::Populate do end it 'populates pipeline with resources described in the seeds block' do - step.perform! + run_chain expect(pipeline).not_to be_persisted expect(pipeline.variables).not_to be_empty @@ -156,7 +169,7 @@ describe Gitlab::Ci::Pipeline::Chain::Populate do end it 'has pipeline iid' do - step.perform! + run_chain expect(pipeline.iid).to be > 0 end @@ -168,7 +181,7 @@ describe Gitlab::Ci::Pipeline::Chain::Populate do end it 'wastes pipeline iid' do - expect { step.perform! }.to raise_error(ActiveRecord::RecordNotSaved) + expect { run_chain }.to raise_error(ActiveRecord::RecordNotSaved) last_iid = InternalId.ci_pipelines .where(project_id: project.id) @@ -183,14 +196,14 @@ describe Gitlab::Ci::Pipeline::Chain::Populate do let(:pipeline) { create(:ci_pipeline, project: project) } it 'raises error' do - expect { step.perform! }.to raise_error(described_class::PopulateError) + expect { run_chain }.to raise_error(described_class::PopulateError) end end context 'when variables policy is specified' do shared_examples_for 'a correct pipeline' do it 'populates pipeline according to used policies' do - step.perform! + run_chain expect(pipeline.stages.size).to eq 1 expect(pipeline.stages.first.statuses.size).to eq 1 diff --git a/spec/lib/gitlab/ci/pipeline/chain/remove_unwanted_chat_jobs_spec.rb b/spec/lib/gitlab/ci/pipeline/chain/remove_unwanted_chat_jobs_spec.rb index af0f4d68150..92eadf5548c 100644 --- a/spec/lib/gitlab/ci/pipeline/chain/remove_unwanted_chat_jobs_spec.rb +++ b/spec/lib/gitlab/ci/pipeline/chain/remove_unwanted_chat_jobs_spec.rb @@ -2,36 +2,38 @@ require 'spec_helper' -describe Gitlab::Ci::Pipeline::Chain::RemoveUnwantedChatJobs do - let(:project) { create(:project, :repository) } +describe ::Gitlab::Ci::Pipeline::Chain::RemoveUnwantedChatJobs do + let(:project) { create(:project) } let(:pipeline) do build(:ci_pipeline, project: project) end let(:command) do - double(:command, project: project, chat_data: { command: 'echo' }) - end - - before do - stub_ci_pipeline_yaml_file(YAML.dump(rspec: { script: 'rspec' })) + double(:command, + config_processor: double(:processor, + jobs: { echo: double(:job_echo), rspec: double(:job_rspec) }), + project: project, + chat_data: { command: 'echo' }) end describe '#perform!' do - it 'removes unwanted jobs for chat pipelines' do - allow(pipeline).to receive(:chat?).and_return(true) + subject { described_class.new(pipeline, command).perform! } - pipeline.config_processor.jobs[:echo] = double(:job) + it 'removes unwanted jobs for chat pipelines' do + expect(pipeline).to receive(:chat?).and_return(true) - described_class.new(pipeline, command).perform! + subject - expect(pipeline.config_processor.jobs.keys).to eq([:echo]) + expect(command.config_processor.jobs.keys).to eq([:echo]) end - end - it 'does not remove any jobs for non-chat pipelines' do - described_class.new(pipeline, command).perform! + it 'does not remove any jobs for non chat-pipelines' do + expect(pipeline).to receive(:chat?).and_return(false) + + subject - expect(pipeline.config_processor.jobs.keys).to eq([:rspec]) + expect(command.config_processor.jobs.keys).to eq([:echo, :rspec]) + end end end diff --git a/spec/lib/gitlab/ci/pipeline/chain/seed_spec.rb b/spec/lib/gitlab/ci/pipeline/chain/seed_spec.rb new file mode 100644 index 00000000000..aa54f19b26c --- /dev/null +++ b/spec/lib/gitlab/ci/pipeline/chain/seed_spec.rb @@ -0,0 +1,161 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe Gitlab::Ci::Pipeline::Chain::Seed do + let(:project) { create(:project, :repository) } + let(:user) { create(:user, developer_projects: [project]) } + + let(:command) do + Gitlab::Ci::Pipeline::Chain::Command.new( + project: project, + current_user: user, + origin_ref: 'master', + seeds_block: nil) + end + + def run_chain(pipeline, command) + [ + Gitlab::Ci::Pipeline::Chain::Config::Content.new(pipeline, command), + Gitlab::Ci::Pipeline::Chain::Config::Process.new(pipeline, command) + ].map(&:perform!) + + described_class.new(pipeline, command).perform! + end + + let(:pipeline) { build(:ci_pipeline, project: project) } + + describe '#perform!' do + before do + stub_ci_pipeline_yaml_file(YAML.dump(config)) + run_chain(pipeline, command) + end + + let(:config) do + { rspec: { script: 'rake' } } + end + + it 'allocates next IID' do + expect(pipeline.iid).to be_present + end + + it 'sets the seeds in the command object' do + expect(command.stage_seeds).to all(be_a Gitlab::Ci::Pipeline::Seed::Base) + expect(command.stage_seeds.count).to eq 1 + end + + context 'when no ref policy is specified' do + let(:config) do + { + production: { stage: 'deploy', script: 'cap prod' }, + rspec: { stage: 'test', script: 'rspec' }, + spinach: { stage: 'test', script: 'spinach' } + } + end + + it 'correctly fabricates a stage seeds object' do + seeds = command.stage_seeds + expect(seeds.size).to eq 2 + expect(seeds.first.attributes[:name]).to eq 'test' + expect(seeds.second.attributes[:name]).to eq 'deploy' + expect(seeds.dig(0, 0, :name)).to eq 'rspec' + expect(seeds.dig(0, 1, :name)).to eq 'spinach' + expect(seeds.dig(1, 0, :name)).to eq 'production' + end + end + + context 'when refs policy is specified' do + let(:pipeline) do + build(:ci_pipeline, project: project, ref: 'feature', tag: true) + end + + let(:config) do + { + production: { stage: 'deploy', script: 'cap prod', only: ['master'] }, + spinach: { stage: 'test', script: 'spinach', only: ['tags'] } + } + end + + it 'returns stage seeds only assigned to master' do + seeds = command.stage_seeds + + expect(seeds.size).to eq 1 + expect(seeds.first.attributes[:name]).to eq 'test' + expect(seeds.dig(0, 0, :name)).to eq 'spinach' + end + end + + context 'when source policy is specified' do + let(:pipeline) { create(:ci_pipeline, source: :schedule) } + + let(:config) do + { + production: { stage: 'deploy', script: 'cap prod', only: ['triggers'] }, + spinach: { stage: 'test', script: 'spinach', only: ['schedules'] } + } + end + + it 'returns stage seeds only assigned to schedules' do + seeds = command.stage_seeds + + expect(seeds.size).to eq 1 + expect(seeds.first.attributes[:name]).to eq 'test' + expect(seeds.dig(0, 0, :name)).to eq 'spinach' + end + end + + context 'when kubernetes policy is specified' do + let(:config) do + { + spinach: { stage: 'test', script: 'spinach' }, + production: { + stage: 'deploy', + script: 'cap', + only: { kubernetes: 'active' } + } + } + end + + context 'when kubernetes is active' do + context 'when user configured kubernetes from CI/CD > Clusters' do + let!(:cluster) { create(:cluster, :project, :provided_by_gcp) } + let(:project) { cluster.project } + let(:pipeline) { build(:ci_pipeline, project: project) } + + it 'returns seeds for kubernetes dependent job' do + seeds = command.stage_seeds + + expect(seeds.size).to eq 2 + expect(seeds.dig(0, 0, :name)).to eq 'spinach' + expect(seeds.dig(1, 0, :name)).to eq 'production' + end + end + end + + context 'when kubernetes is not active' do + it 'does not return seeds for kubernetes dependent job' do + seeds = command.stage_seeds + + expect(seeds.size).to eq 1 + expect(seeds.dig(0, 0, :name)).to eq 'spinach' + end + end + end + + context 'when variables policy is specified' do + let(:config) do + { + unit: { script: 'minitest', only: { variables: ['$CI_PIPELINE_SOURCE'] } }, + feature: { script: 'spinach', only: { variables: ['$UNDEFINED'] } } + } + end + + it 'returns stage seeds only when variables expression is truthy' do + seeds = command.stage_seeds + + expect(seeds.size).to eq 1 + expect(seeds.dig(0, 0, :name)).to eq 'unit' + end + end + end +end diff --git a/spec/lib/gitlab/ci/pipeline/chain/validate/config_spec.rb b/spec/lib/gitlab/ci/pipeline/chain/validate/config_spec.rb deleted file mode 100644 index ed3ce6760a3..00000000000 --- a/spec/lib/gitlab/ci/pipeline/chain/validate/config_spec.rb +++ /dev/null @@ -1,165 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -describe Gitlab::Ci::Pipeline::Chain::Validate::Config do - set(:project) { create(:project, :repository) } - set(:user) { create(:user) } - - let(:command) do - Gitlab::Ci::Pipeline::Chain::Command.new( - project: project, - current_user: user, - save_incompleted: true) - end - - let(:pipeline) do - build(:ci_pipeline, project: project) - end - - let!(:step) { described_class.new(pipeline, command) } - - subject { step.perform! } - - context 'when pipeline has no YAML configuration' do - let(:pipeline) do - build_stubbed(:ci_pipeline, project: project) - end - - it 'appends errors about missing configuration' do - subject - - expect(pipeline.errors.to_a) - .to include 'Missing .gitlab-ci.yml file' - end - - it 'breaks the chain' do - subject - - expect(step.break?).to be true - end - end - - context 'when YAML configuration contains errors' do - before do - stub_ci_pipeline_yaml_file('invalid YAML') - subject - end - - it 'appends errors about YAML errors' do - expect(pipeline.errors.to_a) - .to include 'Invalid configuration format' - end - - it 'breaks the chain' do - expect(step.break?).to be true - end - - context 'when saving incomplete pipeline is allowed' do - let(:command) do - double('command', project: project, - current_user: user, - save_incompleted: true) - end - - it 'fails the pipeline' do - subject - - expect(pipeline.reload).to be_failed - end - - it 'sets a config error failure reason' do - subject - - expect(pipeline.reload.config_error?).to eq true - end - end - - context 'when saving incomplete pipeline is not allowed' do - let(:command) do - double('command', project: project, - current_user: user, - save_incompleted: false) - end - - it 'does not drop pipeline' do - subject - - expect(pipeline).not_to be_failed - expect(pipeline).not_to be_persisted - end - end - end - - context 'when pipeline contains configuration validation errors' do - before do - stub_ci_pipeline_yaml_file(YAML.dump({ - rspec: { - before_script: 10, - script: 'ls -al' - } - })) - - subject - end - - it 'appends configuration validation errors to pipeline errors' do - expect(pipeline.errors.to_a) - .to include "jobs:rspec:before_script config should be an array containing strings and arrays of strings" - end - - it 'breaks the chain' do - expect(step.break?).to be true - end - end - - context 'when pipeline is correct and complete' do - before do - stub_ci_pipeline_yaml_file(YAML.dump({ - rspec: { - script: 'rspec' - } - })) - subject - end - - it 'does not invalidate the pipeline' do - expect(pipeline).to be_valid - end - - it 'does not break the chain' do - expect(step.break?).to be false - end - end - - context 'when pipeline source is merge request' do - before do - stub_ci_pipeline_yaml_file(YAML.dump(config)) - subject - end - - let(:pipeline) { build_stubbed(:ci_pipeline, project: project) } - - let(:merge_request_pipeline) do - build(:ci_pipeline, source: :merge_request_event, project: project) - end - - let(:chain) { described_class.new(merge_request_pipeline, command).tap(&:perform!) } - - context "when config contains 'merge_requests' keyword" do - let(:config) { { rspec: { script: 'echo', only: ['merge_requests'] } } } - - it 'does not break the chain' do - expect(chain).not_to be_break - end - end - - context "when config contains 'merge_request' keyword" do - let(:config) { { rspec: { script: 'echo', only: ['merge_request'] } } } - - it 'does not break the chain' do - expect(chain).not_to be_break - end - end - end -end |