diff options
Diffstat (limited to 'spec/models/ci')
-rw-r--r-- | spec/models/ci/bridge_spec.rb | 2 | ||||
-rw-r--r-- | spec/models/ci/build_spec.rb | 108 | ||||
-rw-r--r-- | spec/models/ci/job_artifact_spec.rb | 21 | ||||
-rw-r--r-- | spec/models/ci/processable_spec.rb | 78 | ||||
-rw-r--r-- | spec/models/ci/runner_spec.rb | 30 |
5 files changed, 177 insertions, 62 deletions
diff --git a/spec/models/ci/bridge_spec.rb b/spec/models/ci/bridge_spec.rb index 31e13122b95..34f89d9cdae 100644 --- a/spec/models/ci/bridge_spec.rb +++ b/spec/models/ci/bridge_spec.rb @@ -17,8 +17,6 @@ describe Ci::Bridge do { trigger: { project: 'my/project', branch: 'master' } } end - it { is_expected.to include_module(Ci::PipelineDelegator) } - it 'has many sourced pipelines' do expect(bridge).to have_many(:sourced_pipelines) end diff --git a/spec/models/ci/build_spec.rb b/spec/models/ci/build_spec.rb index 673b9e5f076..bdaecea2089 100644 --- a/spec/models/ci/build_spec.rb +++ b/spec/models/ci/build_spec.rb @@ -37,8 +37,6 @@ describe Ci::Build do it { is_expected.to delegate_method(:merge_request_ref?).to(:pipeline) } it { is_expected.to delegate_method(:legacy_detached_merge_request_pipeline?).to(:pipeline) } - it { is_expected.to include_module(Ci::PipelineDelegator) } - describe 'associations' do it 'has a bidirectional relationship with projects' do expect(described_class.reflect_on_association(:project).has_inverse?).to eq(:builds) @@ -1818,64 +1816,65 @@ describe Ci::Build do end describe '#merge_request' do - def create_mr(build, pipeline, factory: :merge_request, created_at: Time.now) - create(factory, source_project: pipeline.project, - target_project: pipeline.project, - source_branch: build.ref, - created_at: created_at) - end + subject { pipeline.builds.take.merge_request } - context 'when a MR has a reference to the pipeline' do - before do - @merge_request = create_mr(build, pipeline, factory: :merge_request) + context 'on a branch pipeline' do + let!(:pipeline) { create(:ci_pipeline, :with_job, project: project, ref: 'fix') } - commits = [double(id: pipeline.sha)] - allow(@merge_request).to receive(:commits).and_return(commits) - allow(MergeRequest).to receive_message_chain(:includes, :where, :reorder).and_return([@merge_request]) + context 'with no merge request' do + it { is_expected.to be_nil } end - it 'returns the single associated MR' do - expect(build.merge_request.id).to eq(@merge_request.id) - end - end + context 'with an open merge request from the same ref name' do + let!(:merge_request) { create(:merge_request, source_project: project, source_branch: 'fix') } - context 'when there is not a MR referencing the pipeline' do - it 'returns nil' do - expect(build.merge_request).to be_nil - end - end + # If no diff exists, the pipeline commit was not part of the merge + # request and may have simply incidentally used the same ref name. + context 'without a merge request diff containing the pipeline commit' do + it { is_expected.to be_nil } + end - context 'when more than one MR have a reference to the pipeline' do - before do - @merge_request = create_mr(build, pipeline, factory: :merge_request) - @merge_request.close! - @merge_request2 = create_mr(build, pipeline, factory: :merge_request) + # If the merge request was truly opened from the branch that the + # pipeline ran on, that head sha will be present in a diff. + context 'with a merge request diff containing the pipeline commit' do + let!(:mr_diff) { create(:merge_request_diff, merge_request: merge_request) } + let!(:mr_diff_commit) { create(:merge_request_diff_commit, sha: build.sha, merge_request_diff: mr_diff) } - commits = [double(id: pipeline.sha)] - allow(@merge_request).to receive(:commits).and_return(commits) - allow(@merge_request2).to receive(:commits).and_return(commits) - allow(MergeRequest).to receive_message_chain(:includes, :where, :reorder).and_return([@merge_request, @merge_request2]) + it { is_expected.to eq(merge_request) } + end end - it 'returns the first MR' do - expect(build.merge_request.id).to eq(@merge_request.id) + context 'with multiple open merge requests' do + let!(:merge_request) { create(:merge_request, source_project: project, source_branch: 'fix') } + let!(:mr_diff) { create(:merge_request_diff, merge_request: merge_request) } + let!(:mr_diff_commit) { create(:merge_request_diff_commit, sha: build.sha, merge_request_diff: mr_diff) } + + let!(:new_merge_request) { create(:merge_request, source_project: project, source_branch: 'fix', target_branch: 'staging') } + let!(:new_mr_diff) { create(:merge_request_diff, merge_request: new_merge_request) } + let!(:new_mr_diff_commit) { create(:merge_request_diff_commit, sha: build.sha, merge_request_diff: new_mr_diff) } + + it 'returns the first merge request' do + expect(subject).to eq(merge_request) + end end end - context 'when a Build is created after the MR' do - before do - @merge_request = create_mr(build, pipeline, factory: :merge_request_with_diffs) - pipeline2 = create(:ci_pipeline, project: project) - @build2 = create(:ci_build, pipeline: pipeline2) + context 'on a detached merged request pipeline' do + let(:pipeline) { create(:ci_pipeline, :detached_merge_request_pipeline, :with_job) } - allow(@merge_request).to receive(:commit_shas) - .and_return([pipeline.sha, pipeline2.sha]) - allow(MergeRequest).to receive_message_chain(:includes, :where, :reorder).and_return([@merge_request]) - end + it { is_expected.to eq(pipeline.merge_request) } + end - it 'returns the current MR' do - expect(@build2.merge_request.id).to eq(@merge_request.id) - end + context 'on a legacy detached merged request pipeline' do + let(:pipeline) { create(:ci_pipeline, :legacy_detached_merge_request_pipeline, :with_job) } + + it { is_expected.to eq(pipeline.merge_request) } + end + + context 'on a pipeline for merged results' do + let(:pipeline) { create(:ci_pipeline, :merged_result_pipeline, :with_job) } + + it { is_expected.to eq(pipeline.merge_request) } end end @@ -2281,6 +2280,7 @@ describe Ci::Build do { key: 'CI_REGISTRY_USER', value: 'gitlab-ci-token', public: true, masked: false }, { key: 'CI_REGISTRY_PASSWORD', value: 'my-token', public: false, masked: true }, { key: 'CI_REPOSITORY_URL', value: build.repo_url, public: false, masked: false }, + { key: 'CI_JOB_JWT', value: 'ci.job.jwt', public: false, masked: true }, { key: 'CI_JOB_NAME', value: 'test', public: true, masked: false }, { key: 'CI_JOB_STAGE', value: 'test', public: true, masked: false }, { key: 'CI_NODE_TOTAL', value: '1', public: true, masked: false }, @@ -2333,23 +2333,36 @@ describe Ci::Build do end before do + allow(Gitlab::Ci::Jwt).to receive(:for_build).with(build).and_return('ci.job.jwt') build.set_token('my-token') build.yaml_variables = [] end it { is_expected.to eq(predefined_variables) } + context 'when ci_job_jwt feature flag is disabled' do + before do + stub_feature_flags(ci_job_jwt: false) + end + + it 'CI_JOB_JWT is not included' do + expect(subject.pluck(:key)).not_to include('CI_JOB_JWT') + end + end + describe 'variables ordering' do context 'when variables hierarchy is stubbed' do let(:build_pre_var) { { key: 'build', value: 'value', public: true, masked: false } } let(:project_pre_var) { { key: 'project', value: 'value', public: true, masked: false } } let(:pipeline_pre_var) { { key: 'pipeline', value: 'value', public: true, masked: false } } let(:build_yaml_var) { { key: 'yaml', value: 'value', public: true, masked: false } } + let(:job_jwt_var) { { key: 'CI_JOB_JWT', value: 'ci.job.jwt', public: false, masked: true } } before do allow(build).to receive(:predefined_variables) { [build_pre_var] } allow(build).to receive(:yaml_variables) { [build_yaml_var] } allow(build).to receive(:persisted_variables) { [] } + allow(build).to receive(:job_jwt_variables) { [job_jwt_var] } allow_any_instance_of(Project) .to receive(:predefined_variables) { [project_pre_var] } @@ -2362,7 +2375,8 @@ describe Ci::Build do it 'returns variables in order depending on resource hierarchy' do is_expected.to eq( - [build_pre_var, + [job_jwt_var, + build_pre_var, project_pre_var, pipeline_pre_var, build_yaml_var, diff --git a/spec/models/ci/job_artifact_spec.rb b/spec/models/ci/job_artifact_spec.rb index 80b619ed2b1..6f6ff3704b4 100644 --- a/spec/models/ci/job_artifact_spec.rb +++ b/spec/models/ci/job_artifact_spec.rb @@ -349,13 +349,16 @@ describe Ci::JobArtifact do end describe 'file is being stored' do - context 'when object has nil store' do - it 'is stored locally' do - subject = build(:ci_job_artifact, :archive, file_store: nil) + subject { create(:ci_job_artifact, :archive) } - subject.save + context 'when object has nil store' do + before do + subject.update_column(:file_store, nil) + subject.reload + end - expect(subject.file_store).to be(ObjectStorage::Store::LOCAL) + it 'is stored locally' do + expect(subject.file_store).to be(nil) expect(subject.file).to be_file_storage expect(subject.file.object_store).to eq(ObjectStorage::Store::LOCAL) end @@ -363,10 +366,6 @@ describe Ci::JobArtifact do context 'when existing object has local store' do it 'is stored locally' do - subject = build(:ci_job_artifact, :archive) - - subject.save - expect(subject.file_store).to be(ObjectStorage::Store::LOCAL) expect(subject.file).to be_file_storage expect(subject.file.object_store).to eq(ObjectStorage::Store::LOCAL) @@ -380,10 +379,6 @@ describe Ci::JobArtifact do context 'when file is stored' do it 'is stored remotely' do - subject = build(:ci_job_artifact, :archive) - - subject.save - expect(subject.file_store).to eq(ObjectStorage::Store::REMOTE) expect(subject.file).not_to be_file_storage expect(subject.file.object_store).to eq(ObjectStorage::Store::REMOTE) diff --git a/spec/models/ci/processable_spec.rb b/spec/models/ci/processable_spec.rb index e8ef7b29681..4490371bde5 100644 --- a/spec/models/ci/processable_spec.rb +++ b/spec/models/ci/processable_spec.rb @@ -6,6 +6,18 @@ describe Ci::Processable do let_it_be(:project) { create(:project) } let_it_be(:pipeline) { create(:ci_pipeline, project: project) } + let_it_be(:detached_merge_request_pipeline) do + create(:ci_pipeline, :detached_merge_request_pipeline, :with_job, project: project) + end + + let_it_be(:legacy_detached_merge_request_pipeline) do + create(:ci_pipeline, :legacy_detached_merge_request_pipeline, :with_job, project: project) + end + + let_it_be(:merged_result_pipeline) do + create(:ci_pipeline, :merged_result_pipeline, :with_job, project: project) + end + describe '#aggregated_needs_names' do let(:with_aggregated_needs) { pipeline.processables.select_with_aggregated_needs(project) } @@ -155,4 +167,70 @@ describe Ci::Processable do end end end + + describe '#merge_request?' do + subject { pipeline.processables.first.merge_request? } + + context 'in a detached merge request pipeline' do + let(:pipeline) { detached_merge_request_pipeline } + + it { is_expected.to eq(pipeline.merge_request?) } + end + + context 'in a legacy detached merge_request_pipeline' do + let(:pipeline) { legacy_detached_merge_request_pipeline } + + it { is_expected.to eq(pipeline.merge_request?) } + end + + context 'in a pipeline for merged results' do + let(:pipeline) { merged_result_pipeline } + + it { is_expected.to eq(pipeline.merge_request?) } + end + end + + describe '#merge_request_ref?' do + subject { pipeline.processables.first.merge_request_ref? } + + context 'in a detached merge request pipeline' do + let(:pipeline) { detached_merge_request_pipeline } + + it { is_expected.to eq(pipeline.merge_request_ref?) } + end + + context 'in a legacy detached merge_request_pipeline' do + let(:pipeline) { legacy_detached_merge_request_pipeline } + + it { is_expected.to eq(pipeline.merge_request_ref?) } + end + + context 'in a pipeline for merged results' do + let(:pipeline) { merged_result_pipeline } + + it { is_expected.to eq(pipeline.merge_request_ref?) } + end + end + + describe '#legacy_detached_merge_request_pipeline?' do + subject { pipeline.processables.first.legacy_detached_merge_request_pipeline? } + + context 'in a detached merge request pipeline' do + let(:pipeline) { detached_merge_request_pipeline } + + it { is_expected.to eq(pipeline.legacy_detached_merge_request_pipeline?) } + end + + context 'in a legacy detached merge_request_pipeline' do + let(:pipeline) { legacy_detached_merge_request_pipeline } + + it { is_expected.to eq(pipeline.legacy_detached_merge_request_pipeline?) } + end + + context 'in a pipeline for merged results' do + let(:pipeline) { merged_result_pipeline } + + it { is_expected.to eq(pipeline.legacy_detached_merge_request_pipeline?) } + end + end end diff --git a/spec/models/ci/runner_spec.rb b/spec/models/ci/runner_spec.rb index b8034ba5bf2..2dedff7f15b 100644 --- a/spec/models/ci/runner_spec.rb +++ b/spec/models/ci/runner_spec.rb @@ -78,6 +78,36 @@ describe Ci::Runner do .to raise_error(ActiveRecord::RecordInvalid) end end + + context 'cost factors validations' do + it 'dissalows :private_projects_minutes_cost_factor being nil' do + runner = build(:ci_runner, private_projects_minutes_cost_factor: nil) + + expect(runner).to be_invalid + expect(runner.errors.full_messages).to include('Private projects minutes cost factor needs to be non-negative') + end + + it 'dissalows :public_projects_minutes_cost_factor being nil' do + runner = build(:ci_runner, public_projects_minutes_cost_factor: nil) + + expect(runner).to be_invalid + expect(runner.errors.full_messages).to include('Public projects minutes cost factor needs to be non-negative') + end + + it 'dissalows :private_projects_minutes_cost_factor being negative' do + runner = build(:ci_runner, private_projects_minutes_cost_factor: -1.1) + + expect(runner).to be_invalid + expect(runner.errors.full_messages).to include('Private projects minutes cost factor needs to be non-negative') + end + + it 'dissalows :public_projects_minutes_cost_factor being negative' do + runner = build(:ci_runner, public_projects_minutes_cost_factor: -2.2) + + expect(runner).to be_invalid + expect(runner.errors.full_messages).to include('Public projects minutes cost factor needs to be non-negative') + end + end end describe 'constraints' do |