diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2021-03-16 18:18:33 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2021-03-16 18:18:33 +0000 |
commit | f64a639bcfa1fc2bc89ca7db268f594306edfd7c (patch) | |
tree | a2c3c2ebcc3b45e596949db485d6ed18ffaacfa1 /spec/models/ci/pipeline_spec.rb | |
parent | bfbc3e0d6583ea1a91f627528bedc3d65ba4b10f (diff) | |
download | gitlab-ce-f64a639bcfa1fc2bc89ca7db268f594306edfd7c.tar.gz |
Add latest changes from gitlab-org/gitlab@13-10-stable-eev13.10.0-rc40
Diffstat (limited to 'spec/models/ci/pipeline_spec.rb')
-rw-r--r-- | spec/models/ci/pipeline_spec.rb | 728 |
1 files changed, 386 insertions, 342 deletions
diff --git a/spec/models/ci/pipeline_spec.rb b/spec/models/ci/pipeline_spec.rb index 94943fb3644..d57a39d133f 100644 --- a/spec/models/ci/pipeline_spec.rb +++ b/spec/models/ci/pipeline_spec.rb @@ -8,12 +8,8 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do include Ci::SourcePipelineHelpers let_it_be(:user) { create(:user) } - let_it_be(:namespace) { create_default(:namespace) } - let_it_be(:project) { create_default(:project, :repository) } - - let(:pipeline) do - create(:ci_empty_pipeline, status: :created, project: project) - end + let_it_be(:namespace) { create_default(:namespace).freeze } + let_it_be(:project) { create_default(:project, :repository).freeze } it_behaves_like 'having unique enum values' @@ -53,6 +49,8 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do end describe 'associations' do + let_it_be(:pipeline) { create(:ci_empty_pipeline, :created) } + it 'has a bidirectional relationship with projects' do expect(described_class.reflect_on_association(:project).has_inverse?).to eq(:all_pipelines) expect(Project.reflect_on_association(:all_pipelines).has_inverse?).to eq(:project) @@ -82,6 +80,8 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do end describe '#set_status' do + let(:pipeline) { build(:ci_empty_pipeline, :created) } + where(:from_status, :to_status) do from_status_names = described_class.state_machines[:status].states.map(&:name) to_status_names = from_status_names - [:created] # we never want to transition into created @@ -105,6 +105,8 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do end describe '.processables' do + let_it_be(:pipeline) { create(:ci_empty_pipeline, :created) } + before do create(:ci_build, name: 'build', pipeline: pipeline) create(:ci_bridge, name: 'bridge', pipeline: pipeline) @@ -142,7 +144,8 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do subject { described_class.for_sha(sha) } let(:sha) { 'abc' } - let!(:pipeline) { create(:ci_pipeline, sha: 'abc') } + + let_it_be(:pipeline) { create(:ci_pipeline, sha: 'abc') } it 'returns the pipeline' do is_expected.to contain_exactly(pipeline) @@ -170,7 +173,8 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do subject { described_class.for_source_sha(source_sha) } let(:source_sha) { 'abc' } - let!(:pipeline) { create(:ci_pipeline, source_sha: 'abc') } + + let_it_be(:pipeline) { create(:ci_pipeline, source_sha: 'abc') } it 'returns the pipeline' do is_expected.to contain_exactly(pipeline) @@ -228,7 +232,8 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do subject { described_class.for_branch(branch) } let(:branch) { 'master' } - let!(:pipeline) { create(:ci_pipeline, ref: 'master') } + + let_it_be(:pipeline) { create(:ci_pipeline, ref: 'master') } it 'returns the pipeline' do is_expected.to contain_exactly(pipeline) @@ -247,13 +252,16 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do describe '.ci_sources' do subject { described_class.ci_sources } - let!(:push_pipeline) { create(:ci_pipeline, source: :push) } - let!(:web_pipeline) { create(:ci_pipeline, source: :web) } - let!(:api_pipeline) { create(:ci_pipeline, source: :api) } - let!(:webide_pipeline) { create(:ci_pipeline, source: :webide) } - let!(:child_pipeline) { create(:ci_pipeline, source: :parent_pipeline) } + let(:push_pipeline) { build(:ci_pipeline, source: :push) } + let(:web_pipeline) { build(:ci_pipeline, source: :web) } + let(:api_pipeline) { build(:ci_pipeline, source: :api) } + let(:webide_pipeline) { build(:ci_pipeline, source: :webide) } + let(:child_pipeline) { build(:ci_pipeline, source: :parent_pipeline) } + let(:pipelines) { [push_pipeline, web_pipeline, api_pipeline, webide_pipeline, child_pipeline] } it 'contains pipelines having CI only sources' do + pipelines.map(&:save!) + expect(subject).to contain_exactly(push_pipeline, web_pipeline, api_pipeline) end @@ -365,8 +373,8 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do end end - describe '#merge_request_pipeline?' do - subject { pipeline.merge_request_pipeline? } + describe '#merged_result_pipeline?' do + subject { pipeline.merged_result_pipeline? } let!(:pipeline) do create(:ci_pipeline, source: :merge_request_event, merge_request: merge_request, target_sha: target_sha) @@ -387,6 +395,8 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do describe '#merge_request_ref?' do subject { pipeline.merge_request_ref? } + let(:pipeline) { build(:ci_empty_pipeline, :created) } + it 'calls MergeRequest#merge_request_ref?' do expect(MergeRequest).to receive(:merge_request_ref?).with(pipeline.ref) @@ -606,7 +616,7 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do describe '#source' do context 'when creating new pipeline' do let(:pipeline) do - build(:ci_empty_pipeline, status: :created, project: project, source: nil) + build(:ci_empty_pipeline, :created, project: project, source: nil) end it "prevents from creating an object" do @@ -615,17 +625,21 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do end context 'when updating existing pipeline' do + let(:pipeline) { create(:ci_empty_pipeline, :created) } + before do pipeline.update_attribute(:source, nil) end - it "object is valid" do + it 'object is valid' do expect(pipeline).to be_valid end end end describe '#block' do + let(:pipeline) { create(:ci_empty_pipeline, :created) } + it 'changes pipeline status to manual' do expect(pipeline.block).to be true expect(pipeline.reload).to be_manual @@ -636,7 +650,7 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do describe '#delay' do subject { pipeline.delay } - let(:pipeline) { build(:ci_pipeline, status: :created) } + let(:pipeline) { build(:ci_pipeline, :created) } it 'changes pipeline status to schedule' do subject @@ -646,6 +660,8 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do end describe '#valid_commit_sha' do + let(:pipeline) { build_stubbed(:ci_empty_pipeline, :created, project: project) } + context 'commit.sha can not start with 00000000' do before do pipeline.sha = '0' * 40 @@ -659,6 +675,8 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do describe '#short_sha' do subject { pipeline.short_sha } + let(:pipeline) { build_stubbed(:ci_empty_pipeline, :created) } + it 'has 8 items' do expect(subject.size).to eq(8) end @@ -668,49 +686,58 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do describe '#retried' do subject { pipeline.retried } + let(:pipeline) { create(:ci_empty_pipeline, :created, project: project) } + let!(:build1) { create(:ci_build, pipeline: pipeline, name: 'deploy', retried: true) } + before do - @build1 = create(:ci_build, pipeline: pipeline, name: 'deploy', retried: true) - @build2 = create(:ci_build, pipeline: pipeline, name: 'deploy') + create(:ci_build, pipeline: pipeline, name: 'deploy') end it 'returns old builds' do - is_expected.to contain_exactly(@build1) + is_expected.to contain_exactly(build1) end end describe '#coverage' do - let(:project) { create(:project, build_coverage_regex: "/.*/") } - let(:pipeline) { create(:ci_empty_pipeline, project: project) } + let_it_be_with_reload(:pipeline) { create(:ci_empty_pipeline) } - it "calculates average when there are two builds with coverage" do - create(:ci_build, name: "rspec", coverage: 30, pipeline: pipeline) - create(:ci_build, name: "rubocop", coverage: 40, pipeline: pipeline) - expect(pipeline.coverage).to eq("35.00") - end + context 'with multiple pipelines' do + before_all do + create(:ci_build, name: "rspec", coverage: 30, pipeline: pipeline) + create(:ci_build, name: "rubocop", coverage: 40, pipeline: pipeline) + end - it "calculates average when there are two builds with coverage and one with nil" do - create(:ci_build, name: "rspec", coverage: 30, pipeline: pipeline) - create(:ci_build, name: "rubocop", coverage: 40, pipeline: pipeline) - create(:ci_build, pipeline: pipeline) - expect(pipeline.coverage).to eq("35.00") - end + it "calculates average when there are two builds with coverage" do + expect(pipeline.coverage).to eq("35.00") + end + + it "calculates average when there are two builds with coverage and one with nil" do + create(:ci_build, pipeline: pipeline) + + expect(pipeline.coverage).to eq("35.00") + end - it "calculates average when there are two builds with coverage and one is retried" do - create(:ci_build, name: "rspec", coverage: 30, pipeline: pipeline) - create(:ci_build, name: "rubocop", coverage: 30, pipeline: pipeline, retried: true) - create(:ci_build, name: "rubocop", coverage: 40, pipeline: pipeline) - expect(pipeline.coverage).to eq("35.00") + it "calculates average when there are two builds with coverage and one is retried" do + create(:ci_build, name: "rubocop", coverage: 30, pipeline: pipeline, retried: true) + + expect(pipeline.coverage).to eq("35.00") + end end - it "calculates average when there is one build without coverage" do - FactoryBot.create(:ci_build, pipeline: pipeline) - expect(pipeline.coverage).to be_nil + context 'when there is one build without coverage' do + it "calculates average to nil" do + create(:ci_build, pipeline: pipeline) + + expect(pipeline.coverage).to be_nil + end end end describe '#retryable?' do subject { pipeline.retryable? } + let_it_be(:pipeline) { create(:ci_empty_pipeline, :created, project: project) } + context 'no failed builds' do before do create_build('rspec', 'success') @@ -772,13 +799,15 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do describe '#predefined_variables' do subject { pipeline.predefined_variables } + let(:pipeline) { build(:ci_empty_pipeline, :created) } + it 'includes all predefined variables in a valid order' do keys = subject.map { |variable| variable[:key] } expect(keys).to eq %w[ CI_PIPELINE_IID CI_PIPELINE_SOURCE - CI_CONFIG_PATH + CI_PIPELINE_CREATED_AT CI_COMMIT_SHA CI_COMMIT_SHORT_SHA CI_COMMIT_BEFORE_SHA @@ -798,21 +827,18 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do end context 'when merge request is present' do + let_it_be(:assignees) { create_list(:user, 2) } + let_it_be(:milestone) { create(:milestone, project: project) } + let_it_be(:labels) { create_list(:label, 2) } let(:merge_request) do - create(:merge_request, + create(:merge_request, :simple, source_project: project, - source_branch: 'feature', target_project: project, - target_branch: 'master', assignees: assignees, milestone: milestone, labels: labels) end - let(:assignees) { create_list(:user, 2) } - let(:milestone) { create(:milestone, project: project) } - let(:labels) { create_list(:label, 2) } - context 'when pipeline for merge request is created' do let(:pipeline) do create(:ci_pipeline, :detached_merge_request_pipeline, @@ -998,9 +1024,7 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do end describe '#protected_ref?' do - before do - pipeline.project = create(:project, :repository) - end + let(:pipeline) { build(:ci_empty_pipeline, :created) } it 'delegates method to project' do expect(pipeline).not_to be_protected_ref @@ -1008,11 +1032,8 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do end describe '#legacy_trigger' do - let(:trigger_request) { create(:ci_trigger_request) } - - before do - pipeline.trigger_requests << trigger_request - end + let(:trigger_request) { build(:ci_trigger_request) } + let(:pipeline) { build(:ci_empty_pipeline, :created, trigger_requests: [trigger_request]) } it 'returns first trigger request' do expect(pipeline.legacy_trigger).to eq trigger_request @@ -1022,6 +1043,8 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do describe '#auto_canceled?' do subject { pipeline.auto_canceled? } + let(:pipeline) { build(:ci_empty_pipeline, :created) } + context 'when it is canceled' do before do pipeline.cancel @@ -1029,7 +1052,7 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do context 'when there is auto_canceled_by' do before do - pipeline.update!(auto_canceled_by: create(:ci_empty_pipeline)) + pipeline.auto_canceled_by = create(:ci_empty_pipeline) end it 'is auto canceled' do @@ -1057,6 +1080,8 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do end describe 'pipeline stages' do + let(:pipeline) { build(:ci_empty_pipeline, :created) } + describe 'legacy stages' do before do create(:commit_status, pipeline: pipeline, @@ -1107,22 +1132,28 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do end context 'when commit status is retried' do - before do + let!(:old_commit_status) do create(:commit_status, pipeline: pipeline, - stage: 'build', - name: 'mac', - stage_idx: 0, - status: 'success') - - Ci::ProcessPipelineService - .new(pipeline) - .execute + stage: 'build', + name: 'mac', + stage_idx: 0, + status: 'success') end - it 'ignores the previous state' do - expect(statuses).to eq([%w(build success), - %w(test success), - %w(deploy running)]) + context 'when FF ci_remove_update_retried_from_process_pipeline is disabled' do + before do + stub_feature_flags(ci_remove_update_retried_from_process_pipeline: false) + + Ci::ProcessPipelineService + .new(pipeline) + .execute + end + + it 'ignores the previous state' do + expect(statuses).to eq([%w(build success), + %w(test success), + %w(deploy running)]) + end end end end @@ -1162,6 +1193,8 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do describe '#legacy_stage' do subject { pipeline.legacy_stage('test') } + let(:pipeline) { build(:ci_empty_pipeline, :created) } + context 'with status in stage' do before do create(:commit_status, pipeline: pipeline, stage: 'test') @@ -1184,6 +1217,8 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do end describe '#stages' do + let(:pipeline) { build(:ci_empty_pipeline, :created) } + before do create(:ci_stage_entity, project: project, pipeline: pipeline, @@ -1238,6 +1273,7 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do end describe 'state machine' do + let_it_be_with_reload(:pipeline) { create(:ci_empty_pipeline, :created) } let(:current) { Time.current.change(usec: 0) } let(:build) { create_build('build1', queued_at: 0) } let(:build_b) { create_build('build2', queued_at: 0) } @@ -1401,28 +1437,10 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do end describe 'pipeline caching' do - context 'if pipeline is cacheable' do - before do - pipeline.source = 'push' - end - - it 'performs ExpirePipelinesCacheWorker' do - expect(ExpirePipelineCacheWorker).to receive(:perform_async).with(pipeline.id) + it 'performs ExpirePipelinesCacheWorker' do + expect(ExpirePipelineCacheWorker).to receive(:perform_async).with(pipeline.id) - pipeline.cancel - end - end - - context 'if pipeline is not cacheable' do - before do - pipeline.source = 'webide' - end - - it 'deos not perform ExpirePipelinesCacheWorker' do - expect(ExpirePipelineCacheWorker).not_to receive(:perform_async) - - pipeline.cancel - end + pipeline.cancel end end @@ -1441,24 +1459,25 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do end describe 'auto merge' do - let(:merge_request) { create(:merge_request, :merge_when_pipeline_succeeds) } - - let(:pipeline) do - create(:ci_pipeline, :running, project: merge_request.source_project, - ref: merge_request.source_branch, - sha: merge_request.diff_head_sha) - end + context 'when auto merge is enabled' do + let_it_be_with_reload(:merge_request) { create(:merge_request, :merge_when_pipeline_succeeds) } + let_it_be_with_reload(:pipeline) do + create(:ci_pipeline, :running, project: merge_request.source_project, + ref: merge_request.source_branch, + sha: merge_request.diff_head_sha) + end - before do - merge_request.update_head_pipeline - end + before_all do + merge_request.update_head_pipeline + end - %w[succeed! drop! cancel! skip!].each do |action| - context "when the pipeline recieved #{action} event" do - it 'performs AutoMergeProcessWorker' do - expect(AutoMergeProcessWorker).to receive(:perform_async).with(merge_request.id) + %w[succeed! drop! cancel! skip!].each do |action| + context "when the pipeline recieved #{action} event" do + it 'performs AutoMergeProcessWorker' do + expect(AutoMergeProcessWorker).to receive(:perform_async).with(merge_request.id) - pipeline.public_send(action) + pipeline.public_send(action) + end end end end @@ -1610,15 +1629,15 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do context 'multi-project pipelines' do let!(:downstream_project) { create(:project, :repository) } - let!(:upstream_pipeline) { create(:ci_pipeline, project: project) } + let!(:upstream_pipeline) { create(:ci_pipeline) } let!(:downstream_pipeline) { create(:ci_pipeline, :with_job, project: downstream_project) } it_behaves_like 'upstream downstream pipeline' end context 'parent-child pipelines' do - let!(:upstream_pipeline) { create(:ci_pipeline, project: project) } - let!(:downstream_pipeline) { create(:ci_pipeline, :with_job, project: project) } + let!(:upstream_pipeline) { create(:ci_pipeline) } + let!(:downstream_pipeline) { create(:ci_pipeline, :with_job) } it_behaves_like 'upstream downstream pipeline' end @@ -1637,6 +1656,8 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do describe '#branch?' do subject { pipeline.branch? } + let(:pipeline) { build(:ci_empty_pipeline, :created) } + context 'when ref is not a tag' do before do pipeline.tag = false @@ -1647,16 +1668,12 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do end context 'when pipeline is merge request' do - let(:pipeline) do - create(:ci_pipeline, merge_request: merge_request) - end + let(:pipeline) { build(:ci_pipeline, merge_request: merge_request) } let(:merge_request) do - create(:merge_request, + create(:merge_request, :simple, source_project: project, - source_branch: 'feature', - target_project: project, - target_branch: 'master') + target_project: project) end it 'returns false' do @@ -1720,6 +1737,8 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do context 'when repository exists' do using RSpec::Parameterized::TableSyntax + let_it_be(:pipeline, refind: true) { create(:ci_empty_pipeline) } + where(:tag, :ref, :result) do false | 'master' | true false | 'non-existent-branch' | false @@ -1728,8 +1747,8 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do end with_them do - let(:pipeline) do - create(:ci_empty_pipeline, project: project, tag: tag, ref: ref) + before do + pipeline.update!(tag: tag, ref: ref) end it "correctly detects ref" do @@ -1739,10 +1758,7 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do end context 'when repository does not exist' do - let(:project) { create(:project) } - let(:pipeline) do - create(:ci_empty_pipeline, project: project, ref: 'master') - end + let(:pipeline) { build(:ci_empty_pipeline, ref: 'master', project: build(:project)) } it 'always returns false' do expect(pipeline.ref_exists?).to eq false @@ -1753,7 +1769,6 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do context 'with non-empty project' do let(:pipeline) do create(:ci_pipeline, - project: project, ref: project.default_branch, sha: project.commit.sha) end @@ -1761,14 +1776,12 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do describe '#lazy_ref_commit' do let(:another) do create(:ci_pipeline, - project: project, ref: 'feature', sha: project.commit('feature').sha) end let(:unicode) do create(:ci_pipeline, - project: project, ref: 'ü/unicode/multi-byte') end @@ -1827,6 +1840,8 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do describe '#manual_actions' do subject { pipeline.manual_actions } + let(:pipeline) { create(:ci_empty_pipeline, :created) } + it 'when none defined' do is_expected.to be_empty end @@ -1853,9 +1868,11 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do end describe '#branch_updated?' do + let(:pipeline) { create(:ci_empty_pipeline, :created) } + context 'when pipeline has before SHA' do before do - pipeline.update_column(:before_sha, 'a1b2c3d4') + pipeline.update!(before_sha: 'a1b2c3d4') end it 'runs on a branch update push' do @@ -1866,7 +1883,7 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do context 'when pipeline does not have before SHA' do before do - pipeline.update_column(:before_sha, Gitlab::Git::BLANK_SHA) + pipeline.update!(before_sha: Gitlab::Git::BLANK_SHA) end it 'does not run on a branch updating push' do @@ -1876,6 +1893,8 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do end describe '#modified_paths' do + let(:pipeline) { create(:ci_empty_pipeline, :created) } + context 'when old and new revisions are set' do before do pipeline.update!(before_sha: '1234abcd', sha: '2345bcde') @@ -1892,7 +1911,7 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do context 'when either old or new revision is missing' do before do - pipeline.update_column(:before_sha, Gitlab::Git::BLANK_SHA) + pipeline.update!(before_sha: Gitlab::Git::BLANK_SHA) end it 'returns nil' do @@ -1906,11 +1925,9 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do end let(:merge_request) do - create(:merge_request, + create(:merge_request, :simple, source_project: project, - source_branch: 'feature', - target_project: project, - target_branch: 'master') + target_project: project) end it 'returns merge request modified paths' do @@ -1944,6 +1961,8 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do end describe '#has_kubernetes_active?' do + let(:pipeline) { create(:ci_empty_pipeline, :created, project: project) } + context 'when kubernetes is active' do context 'when user configured kubernetes from CI/CD > Clusters' do let!(:cluster) { create(:cluster, :project, :provided_by_gcp) } @@ -1965,6 +1984,8 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do describe '#has_warnings?' do subject { pipeline.has_warnings? } + let_it_be(:pipeline) { create(:ci_empty_pipeline, :created) } + context 'build which is allowed to fail fails' do before do create :ci_build, :success, pipeline: pipeline, name: 'rspec' @@ -2021,6 +2042,8 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do end describe '#number_of_warnings' do + let_it_be(:pipeline) { create(:ci_empty_pipeline, :created) } + it 'returns the number of warnings' do create(:ci_build, :allowed_to_fail, :failed, pipeline: pipeline, name: 'rubocop') create(:ci_bridge, :allowed_to_fail, :failed, pipeline: pipeline, name: 'rubocop') @@ -2029,7 +2052,7 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do end it 'supports eager loading of the number of warnings' do - pipeline2 = create(:ci_empty_pipeline, status: :created, project: project) + pipeline2 = create(:ci_empty_pipeline, :created) create(:ci_build, :allowed_to_fail, :failed, pipeline: pipeline, name: 'rubocop') create(:ci_build, :allowed_to_fail, :failed, pipeline: pipeline2, name: 'rubocop') @@ -2053,6 +2076,8 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do subject { pipeline.needs_processing? } + let_it_be(:pipeline) { create(:ci_empty_pipeline, :created) } + where(:processed, :result) do nil | true false | true @@ -2072,122 +2097,107 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do end end - shared_context 'with some outdated pipelines' do - before do - create_pipeline(:canceled, 'ref', 'A', project) - create_pipeline(:success, 'ref', 'A', project) - create_pipeline(:failed, 'ref', 'B', project) - create_pipeline(:skipped, 'feature', 'C', project) + context 'with outdated pipelines' do + before_all do + create_pipeline(:canceled, 'ref', 'A') + create_pipeline(:success, 'ref', 'A') + create_pipeline(:failed, 'ref', 'B') + create_pipeline(:skipped, 'feature', 'C') end - def create_pipeline(status, ref, sha, project) + def create_pipeline(status, ref, sha) create( :ci_empty_pipeline, status: status, ref: ref, - sha: sha, - project: project + sha: sha ) end - end - describe '.newest_first' do - include_context 'with some outdated pipelines' - - it 'returns the pipelines from new to old' do - expect(described_class.newest_first.pluck(:status)) - .to eq(%w[skipped failed success canceled]) - end + describe '.newest_first' do + it 'returns the pipelines from new to old' do + expect(described_class.newest_first.pluck(:status)) + .to eq(%w[skipped failed success canceled]) + end - it 'searches limited backlog' do - expect(described_class.newest_first(limit: 1).pluck(:status)) - .to eq(%w[skipped]) + it 'searches limited backlog' do + expect(described_class.newest_first(limit: 1).pluck(:status)) + .to eq(%w[skipped]) + end end - end - describe '.latest_status' do - include_context 'with some outdated pipelines' - - context 'when no ref is specified' do - it 'returns the status of the latest pipeline' do - expect(described_class.latest_status).to eq('skipped') + describe '.latest_status' do + context 'when no ref is specified' do + it 'returns the status of the latest pipeline' do + expect(described_class.latest_status).to eq('skipped') + end end - end - context 'when ref is specified' do - it 'returns the status of the latest pipeline for the given ref' do - expect(described_class.latest_status('ref')).to eq('failed') + context 'when ref is specified' do + it 'returns the status of the latest pipeline for the given ref' do + expect(described_class.latest_status('ref')).to eq('failed') + end end end - end - describe '.latest_successful_for_ref' do - include_context 'with some outdated pipelines' - - let!(:latest_successful_pipeline) do - create_pipeline(:success, 'ref', 'D', project) - end + describe '.latest_successful_for_ref' do + let!(:latest_successful_pipeline) do + create_pipeline(:success, 'ref', 'D') + end - it 'returns the latest successful pipeline' do - expect(described_class.latest_successful_for_ref('ref')) - .to eq(latest_successful_pipeline) + it 'returns the latest successful pipeline' do + expect(described_class.latest_successful_for_ref('ref')) + .to eq(latest_successful_pipeline) + end end - end - describe '.latest_running_for_ref' do - include_context 'with some outdated pipelines' - - let!(:latest_running_pipeline) do - create_pipeline(:running, 'ref', 'D', project) - end + describe '.latest_running_for_ref' do + let!(:latest_running_pipeline) do + create_pipeline(:running, 'ref', 'D') + end - it 'returns the latest running pipeline' do - expect(described_class.latest_running_for_ref('ref')) - .to eq(latest_running_pipeline) + it 'returns the latest running pipeline' do + expect(described_class.latest_running_for_ref('ref')) + .to eq(latest_running_pipeline) + end end - end - - describe '.latest_failed_for_ref' do - include_context 'with some outdated pipelines' - let!(:latest_failed_pipeline) do - create_pipeline(:failed, 'ref', 'D', project) - end + describe '.latest_failed_for_ref' do + let!(:latest_failed_pipeline) do + create_pipeline(:failed, 'ref', 'D') + end - it 'returns the latest failed pipeline' do - expect(described_class.latest_failed_for_ref('ref')) - .to eq(latest_failed_pipeline) + it 'returns the latest failed pipeline' do + expect(described_class.latest_failed_for_ref('ref')) + .to eq(latest_failed_pipeline) + end end - end - - describe '.latest_successful_for_sha' do - include_context 'with some outdated pipelines' - let!(:latest_successful_pipeline) do - create_pipeline(:success, 'ref', 'awesomesha', project) - end + describe '.latest_successful_for_sha' do + let!(:latest_successful_pipeline) do + create_pipeline(:success, 'ref', 'awesomesha') + end - it 'returns the latest successful pipeline' do - expect(described_class.latest_successful_for_sha('awesomesha')) - .to eq(latest_successful_pipeline) + it 'returns the latest successful pipeline' do + expect(described_class.latest_successful_for_sha('awesomesha')) + .to eq(latest_successful_pipeline) + end end - end - - describe '.latest_successful_for_refs' do - include_context 'with some outdated pipelines' - let!(:latest_successful_pipeline1) do - create_pipeline(:success, 'ref1', 'D', project) - end + describe '.latest_successful_for_refs' do + let!(:latest_successful_pipeline1) do + create_pipeline(:success, 'ref1', 'D') + end - let!(:latest_successful_pipeline2) do - create_pipeline(:success, 'ref2', 'D', project) - end + let!(:latest_successful_pipeline2) do + create_pipeline(:success, 'ref2', 'D') + end - it 'returns the latest successful pipeline for both refs' do - refs = %w(ref1 ref2 ref3) + it 'returns the latest successful pipeline for both refs' do + refs = %w(ref1 ref2 ref3) - expect(described_class.latest_successful_for_refs(refs)).to eq({ 'ref1' => latest_successful_pipeline1, 'ref2' => latest_successful_pipeline2 }) + expect(described_class.latest_successful_for_refs(refs)).to eq({ 'ref1' => latest_successful_pipeline1, 'ref2' => latest_successful_pipeline2 }) + end end end @@ -2197,8 +2207,7 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do :ci_empty_pipeline, status: 'success', ref: 'master', - sha: '123', - project: project + sha: '123' ) end @@ -2207,8 +2216,7 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do :ci_empty_pipeline, status: 'success', ref: 'develop', - sha: '123', - project: project + sha: '123' ) end @@ -2217,8 +2225,7 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do :ci_empty_pipeline, status: 'success', ref: 'test', - sha: '456', - project: project + sha: '456' ) end @@ -2315,12 +2322,11 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do end describe '#status', :sidekiq_inline do - let(:build) do - create(:ci_build, :created, pipeline: pipeline, name: 'test') - end - subject { pipeline.reload.status } + let_it_be(:pipeline) { create(:ci_empty_pipeline, :created) } + let(:build) { create(:ci_build, :created, pipeline: pipeline, name: 'test') } + context 'on waiting for resource' do before do allow(build).to receive(:with_resource_group?) { true } @@ -2412,8 +2418,10 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do describe '#detailed_status' do subject { pipeline.detailed_status(user) } + let_it_be(:pipeline) { create(:ci_empty_pipeline, :created) } + context 'when pipeline is created' do - let(:pipeline) { create(:ci_pipeline, status: :created) } + let(:pipeline) { create(:ci_pipeline, :created) } it 'returns detailed status for created pipeline' do expect(subject.text).to eq s_('CiStatusText|created') @@ -2490,6 +2498,8 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do end describe '#cancelable?' do + let_it_be(:pipeline) { create(:ci_empty_pipeline, :created) } + %i[created running pending].each do |status0| context "when there is a build #{status0}" do before do @@ -2581,7 +2591,9 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do end describe '#cancel_running' do - let(:latest_status) { pipeline.statuses.pluck(:status) } + subject(:latest_status) { pipeline.statuses.pluck(:status) } + + let_it_be(:pipeline) { create(:ci_empty_pipeline, :created) } context 'when there is a running external job and a regular job' do before do @@ -2624,7 +2636,9 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do end describe '#retry_failed' do - let(:latest_status) { pipeline.latest_statuses.pluck(:status) } + subject(:latest_status) { pipeline.latest_statuses.pluck(:status) } + + let_it_be(:pipeline) { create(:ci_empty_pipeline, :created) } before do stub_not_protect_default_branch @@ -2673,11 +2687,12 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do end describe '#execute_hooks' do + let_it_be(:pipeline) { create(:ci_empty_pipeline, :created) } let!(:build_a) { create_build('a', 0) } let!(:build_b) { create_build('b', 0) } let!(:hook) do - create(:project_hook, project: project, pipeline_events: enabled) + create(:project_hook, pipeline_events: enabled) end before do @@ -2703,7 +2718,7 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do end it 'builds hook data once' do - create(:pipelines_email_service, project: project) + create(:pipelines_email_service) expect(Gitlab::DataBuilder::Pipeline).to receive(:build).once.and_call_original @@ -2789,7 +2804,7 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do end describe "#merge_requests_as_head_pipeline" do - let(:pipeline) { create(:ci_empty_pipeline, status: 'created', project: project, ref: 'master', sha: 'a288a022a53a5a944fae87bcec6efc87b7061808') } + let_it_be_with_reload(:pipeline) { create(:ci_empty_pipeline, status: 'created', ref: 'master', sha: 'a288a022a53a5a944fae87bcec6efc87b7061808') } it "returns merge requests whose `diff_head_sha` matches the pipeline's SHA" do allow_next_instance_of(MergeRequest) do |instance| @@ -2801,7 +2816,7 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do end it "doesn't return merge requests whose source branch doesn't match the pipeline's ref" do - create(:merge_request, source_project: project, source_branch: 'feature', target_branch: 'master') + create(:merge_request, :simple, source_project: project) expect(pipeline.merge_requests_as_head_pipeline).to be_empty end @@ -2817,7 +2832,8 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do end describe '#all_merge_requests' do - let(:project) { create(:project) } + let_it_be_with_reload(:project) { create(:project) } + let_it_be(:pipeline) { create(:ci_empty_pipeline, :created, project: project) } shared_examples 'a method that returns all merge requests for a given pipeline' do let(:pipeline) { create(:ci_empty_pipeline, status: 'created', project: pipeline_project, ref: 'master') } @@ -2911,10 +2927,9 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do end describe '#related_merge_requests' do - let(:project) { create(:project, :repository) } let(:merge_request) { create(:merge_request, source_project: project, source_branch: 'feature', target_branch: 'master') } let(:other_merge_request) { create(:merge_request, source_project: project, source_branch: 'feature', target_branch: 'stable') } - let(:branch_pipeline) { create(:ci_pipeline, project: project, ref: 'feature') } + let(:branch_pipeline) { create(:ci_pipeline, ref: 'feature') } let(:merge_pipeline) { create(:ci_pipeline, :detached_merge_request_pipeline, merge_request: merge_request) } context 'for a branch pipeline' do @@ -2951,9 +2966,7 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do end describe '#open_merge_requests_refs' do - let(:project) { create(:project) } - let(:user) { create(:user) } - let!(:pipeline) { create(:ci_pipeline, user: user, project: project, ref: 'feature') } + let!(:pipeline) { create(:ci_pipeline, user: user, ref: 'feature') } let!(:merge_request) { create(:merge_request, source_project: project, source_branch: 'feature', target_branch: 'master') } subject { pipeline.open_merge_requests_refs } @@ -3000,6 +3013,8 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do describe '#same_family_pipeline_ids' do subject { pipeline.same_family_pipeline_ids.map(&:id) } + let_it_be(:pipeline) { create(:ci_empty_pipeline, :created) } + context 'when pipeline is not child nor parent' do it 'returns just the pipeline id' do expect(subject).to contain_exactly(pipeline.id) @@ -3007,7 +3022,7 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do end context 'when pipeline is child' do - let(:parent) { create(:ci_pipeline, project: project) } + let(:parent) { create(:ci_pipeline) } let!(:pipeline) { create(:ci_pipeline, child_of: parent) } let!(:sibling) { create(:ci_pipeline, child_of: parent) } @@ -3025,7 +3040,7 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do end context 'when pipeline is a child of a child pipeline' do - let(:ancestor) { create(:ci_pipeline, project: project) } + let(:ancestor) { create(:ci_pipeline) } let!(:parent) { create(:ci_pipeline, child_of: ancestor) } let!(:pipeline) { create(:ci_pipeline, child_of: parent) } let!(:cousin_parent) { create(:ci_pipeline, child_of: ancestor) } @@ -3050,10 +3065,10 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do describe '#root_ancestor' do subject { pipeline.root_ancestor } - let_it_be(:pipeline) { create(:ci_pipeline, project: project) } + let_it_be(:pipeline) { create(:ci_pipeline) } context 'when pipeline is child of child pipeline' do - let!(:root_ancestor) { create(:ci_pipeline, project: project) } + let!(:root_ancestor) { create(:ci_pipeline) } let!(:parent_pipeline) { create(:ci_pipeline, child_of: root_ancestor) } let!(:pipeline) { create(:ci_pipeline, child_of: parent_pipeline) } @@ -3088,6 +3103,8 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do end describe '#stuck?' do + let(:pipeline) { create(:ci_empty_pipeline, :created) } + before do create(:ci_build, :pending, pipeline: pipeline) end @@ -3132,6 +3149,8 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do end describe '#has_yaml_errors?' do + let(:pipeline) { build_stubbed(:ci_pipeline) } + context 'when yaml_errors is set' do before do pipeline.yaml_errors = 'File not found' @@ -3201,7 +3220,7 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do context 'when pipeline is not the latest' do before do - create(:ci_pipeline, :success, project: project, ci_ref: pipeline.ci_ref) + create(:ci_pipeline, :success, ci_ref: pipeline.ci_ref) end it 'does not pass ref_status' do @@ -3302,7 +3321,7 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do describe '#builds_in_self_and_descendants' do subject(:builds) { pipeline.builds_in_self_and_descendants } - let(:pipeline) { create(:ci_pipeline, project: project) } + let(:pipeline) { create(:ci_pipeline) } let!(:build) { create(:ci_build, pipeline: pipeline) } context 'when pipeline is standalone' do @@ -3333,6 +3352,7 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do end describe '#build_with_artifacts_in_self_and_descendants' do + let_it_be(:pipeline) { create(:ci_pipeline) } let!(:build) { create(:ci_build, name: 'test', pipeline: pipeline) } let(:child_pipeline) { create(:ci_pipeline, child_of: pipeline) } let!(:child_build) { create(:ci_build, :artifacts, name: 'test', pipeline: child_pipeline) } @@ -3351,6 +3371,7 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do end describe '#find_job_with_archive_artifacts' do + let(:pipeline) { create(:ci_pipeline) } let!(:old_job) { create(:ci_build, name: 'rspec', retried: true, pipeline: pipeline) } let!(:job_without_artifacts) { create(:ci_build, name: 'rspec', pipeline: pipeline) } let!(:expected_job) { create(:ci_build, :artifacts, name: 'rspec', pipeline: pipeline ) } @@ -3364,6 +3385,7 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do end describe '#latest_builds_with_artifacts' do + let(:pipeline) { create(:ci_pipeline) } let!(:fresh_build) { create(:ci_build, :success, :artifacts, pipeline: pipeline) } let!(:stale_build) { create(:ci_build, :success, :expired, :artifacts, pipeline: pipeline) } @@ -3390,7 +3412,7 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do describe '#batch_lookup_report_artifact_for_file_type' do context 'with code quality report artifact' do - let(:pipeline) { create(:ci_pipeline, :with_codequality_reports, project: project) } + let(:pipeline) { create(:ci_pipeline, :with_codequality_reports) } it "returns the code quality artifact" do expect(pipeline.batch_lookup_report_artifact_for_file_type(:codequality)).to eq(pipeline.job_artifacts.sample) @@ -3399,24 +3421,26 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do end describe '#latest_report_builds' do + let_it_be(:pipeline) { create(:ci_pipeline, project: project) } + it 'returns build with test artifacts' do - test_build = create(:ci_build, :test_reports, pipeline: pipeline, project: project) - coverage_build = create(:ci_build, :coverage_reports, pipeline: pipeline, project: project) + test_build = create(:ci_build, :test_reports, pipeline: pipeline) + coverage_build = create(:ci_build, :coverage_reports, pipeline: pipeline) create(:ci_build, :artifacts, pipeline: pipeline, project: project) expect(pipeline.latest_report_builds).to contain_exactly(test_build, coverage_build) end it 'filters builds by scope' do - test_build = create(:ci_build, :test_reports, pipeline: pipeline, project: project) - create(:ci_build, :coverage_reports, pipeline: pipeline, project: project) + test_build = create(:ci_build, :test_reports, pipeline: pipeline) + create(:ci_build, :coverage_reports, pipeline: pipeline) expect(pipeline.latest_report_builds(Ci::JobArtifact.test_reports)).to contain_exactly(test_build) end it 'only returns not retried builds' do - test_build = create(:ci_build, :test_reports, pipeline: pipeline, project: project) - create(:ci_build, :test_reports, :retried, pipeline: pipeline, project: project) + test_build = create(:ci_build, :test_reports, pipeline: pipeline) + create(:ci_build, :test_reports, :retried, pipeline: pipeline) expect(pipeline.latest_report_builds).to contain_exactly(test_build) end @@ -3427,17 +3451,17 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do context 'when pipeline has builds with test reports' do before do - create(:ci_build, :test_reports, pipeline: pipeline, project: project) + create(:ci_build, :test_reports, pipeline: pipeline) end context 'when pipeline status is running' do - let(:pipeline) { create(:ci_pipeline, :running, project: project) } + let(:pipeline) { create(:ci_pipeline, :running) } it { is_expected.to be_falsey } end context 'when pipeline status is success' do - let(:pipeline) { create(:ci_pipeline, :success, project: project) } + let(:pipeline) { create(:ci_pipeline, :success) } it { is_expected.to be_truthy } end @@ -3445,20 +3469,20 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do context 'when pipeline does not have builds with test reports' do before do - create(:ci_build, :artifacts, pipeline: pipeline, project: project) + create(:ci_build, :artifacts, pipeline: pipeline) end - let(:pipeline) { create(:ci_pipeline, :success, project: project) } + let(:pipeline) { create(:ci_pipeline, :success) } it { is_expected.to be_falsey } end context 'when retried build has test reports' do before do - create(:ci_build, :retried, :test_reports, pipeline: pipeline, project: project) + create(:ci_build, :retried, :test_reports, pipeline: pipeline) end - let(:pipeline) { create(:ci_pipeline, :success, project: project) } + let(:pipeline) { create(:ci_pipeline, :success) } it { is_expected.to be_falsey } end @@ -3468,13 +3492,13 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do subject { pipeline.has_coverage_reports? } context 'when pipeline has a code coverage artifact' do - let(:pipeline) { create(:ci_pipeline, :with_coverage_report_artifact, :running, project: project) } + let(:pipeline) { create(:ci_pipeline, :with_coverage_report_artifact, :running) } it { expect(subject).to be_truthy } end context 'when pipeline does not have a code coverage artifact' do - let(:pipeline) { create(:ci_pipeline, :success, project: project) } + let(:pipeline) { create(:ci_pipeline, :success) } it { expect(subject).to be_falsey } end @@ -3485,17 +3509,17 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do context 'when pipeline has builds with coverage reports' do before do - create(:ci_build, :coverage_reports, pipeline: pipeline, project: project) + create(:ci_build, :coverage_reports, pipeline: pipeline) end context 'when pipeline status is running' do - let(:pipeline) { create(:ci_pipeline, :running, project: project) } + let(:pipeline) { create(:ci_pipeline, :running) } it { expect(subject).to be_falsey } end context 'when pipeline status is success' do - let(:pipeline) { create(:ci_pipeline, :success, project: project) } + let(:pipeline) { create(:ci_pipeline, :success) } it { expect(subject).to be_truthy } end @@ -3503,10 +3527,10 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do context 'when pipeline does not have builds with coverage reports' do before do - create(:ci_build, :artifacts, pipeline: pipeline, project: project) + create(:ci_build, :artifacts, pipeline: pipeline) end - let(:pipeline) { create(:ci_pipeline, :success, project: project) } + let(:pipeline) { create(:ci_pipeline, :success) } it { expect(subject).to be_falsey } end @@ -3516,13 +3540,13 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do subject { pipeline.has_codequality_mr_diff_report? } context 'when pipeline has a codequality mr diff report' do - let(:pipeline) { create(:ci_pipeline, :with_codequality_mr_diff_report, :running, project: project) } + let(:pipeline) { create(:ci_pipeline, :with_codequality_mr_diff_report, :running) } it { expect(subject).to be_truthy } end context 'when pipeline does not have a codequality mr diff report' do - let(:pipeline) { create(:ci_pipeline, :success, project: project) } + let(:pipeline) { create(:ci_pipeline, :success) } it { expect(subject).to be_falsey } end @@ -3533,17 +3557,17 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do context 'when pipeline has builds with codequality reports' do before do - create(:ci_build, :codequality_reports, pipeline: pipeline, project: project) + create(:ci_build, :codequality_reports, pipeline: pipeline) end context 'when pipeline status is running' do - let(:pipeline) { create(:ci_pipeline, :running, project: project) } + let(:pipeline) { create(:ci_pipeline, :running) } it { expect(subject).to be_falsey } end context 'when pipeline status is success' do - let(:pipeline) { create(:ci_pipeline, :success, project: project) } + let(:pipeline) { create(:ci_pipeline, :success) } it 'can generate a codequality report' do expect(subject).to be_truthy @@ -3563,10 +3587,10 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do context 'when pipeline does not have builds with codequality reports' do before do - create(:ci_build, :artifacts, pipeline: pipeline, project: project) + create(:ci_build, :artifacts, pipeline: pipeline) end - let(:pipeline) { create(:ci_pipeline, :success, project: project) } + let(:pipeline) { create(:ci_pipeline, :success) } it { expect(subject).to be_falsey } end @@ -3575,12 +3599,12 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do describe '#test_report_summary' do subject { pipeline.test_report_summary } - context 'when pipeline has multiple builds with report results' do - let(:pipeline) { create(:ci_pipeline, :success, project: project) } + let(:pipeline) { create(:ci_pipeline, :success) } + context 'when pipeline has multiple builds with report results' do before do - create(:ci_build, :success, :report_results, name: 'rspec', pipeline: pipeline, project: project) - create(:ci_build, :success, :report_results, name: 'java', pipeline: pipeline, project: project) + create(:ci_build, :success, :report_results, name: 'rspec', pipeline: pipeline) + create(:ci_build, :success, :report_results, name: 'java', pipeline: pipeline) end it 'returns test report summary with collected data' do @@ -3598,13 +3622,15 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do describe '#test_reports' do subject { pipeline.test_reports } + let_it_be(:pipeline) { create(:ci_pipeline) } + context 'when pipeline has multiple builds with test reports' do - let!(:build_rspec) { create(:ci_build, :success, name: 'rspec', pipeline: pipeline, project: project) } - let!(:build_java) { create(:ci_build, :success, name: 'java', pipeline: pipeline, project: project) } + let!(:build_rspec) { create(:ci_build, :success, name: 'rspec', pipeline: pipeline) } + let!(:build_java) { create(:ci_build, :success, name: 'java', pipeline: pipeline) } before do - create(:ci_job_artifact, :junit, job: build_rspec, project: project) - create(:ci_job_artifact, :junit_with_ant, job: build_java, project: project) + create(:ci_job_artifact, :junit, job: build_rspec) + create(:ci_job_artifact, :junit_with_ant, job: build_java) end it 'returns test reports with collected data' do @@ -3614,8 +3640,8 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do end context 'when builds are retried' do - let!(:build_rspec) { create(:ci_build, :retried, :success, name: 'rspec', pipeline: pipeline, project: project) } - let!(:build_java) { create(:ci_build, :retried, :success, name: 'java', pipeline: pipeline, project: project) } + let!(:build_rspec) { create(:ci_build, :retried, :success, name: 'rspec', pipeline: pipeline) } + let!(:build_java) { create(:ci_build, :retried, :success, name: 'java', pipeline: pipeline) } it 'does not take retried builds into account' do expect(subject.total_count).to be(0) @@ -3635,13 +3661,15 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do describe '#accessibility_reports' do subject { pipeline.accessibility_reports } + let_it_be(:pipeline) { create(:ci_pipeline) } + context 'when pipeline has multiple builds with accessibility reports' do - let(:build_rspec) { create(:ci_build, :success, name: 'rspec', pipeline: pipeline, project: project) } - let(:build_golang) { create(:ci_build, :success, name: 'golang', pipeline: pipeline, project: project) } + let(:build_rspec) { create(:ci_build, :success, name: 'rspec', pipeline: pipeline) } + let(:build_golang) { create(:ci_build, :success, name: 'golang', pipeline: pipeline) } before do - create(:ci_job_artifact, :accessibility, job: build_rspec, project: project) - create(:ci_job_artifact, :accessibility_without_errors, job: build_golang, project: project) + create(:ci_job_artifact, :accessibility, job: build_rspec) + create(:ci_job_artifact, :accessibility_without_errors, job: build_golang) end it 'returns accessibility report with collected data' do @@ -3652,8 +3680,8 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do end context 'when builds are retried' do - let(:build_rspec) { create(:ci_build, :retried, :success, name: 'rspec', pipeline: pipeline, project: project) } - let(:build_golang) { create(:ci_build, :retried, :success, name: 'golang', pipeline: pipeline, project: project) } + let(:build_rspec) { create(:ci_build, :retried, :success, name: 'rspec', pipeline: pipeline) } + let(:build_golang) { create(:ci_build, :retried, :success, name: 'golang', pipeline: pipeline) } it 'returns empty urls for accessibility reports' do expect(subject.urls).to be_empty @@ -3671,13 +3699,15 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do describe '#coverage_reports' do subject { pipeline.coverage_reports } + let_it_be(:pipeline) { create(:ci_pipeline) } + context 'when pipeline has multiple builds with coverage reports' do - let!(:build_rspec) { create(:ci_build, :success, name: 'rspec', pipeline: pipeline, project: project) } - let!(:build_golang) { create(:ci_build, :success, name: 'golang', pipeline: pipeline, project: project) } + let!(:build_rspec) { create(:ci_build, :success, name: 'rspec', pipeline: pipeline) } + let!(:build_golang) { create(:ci_build, :success, name: 'golang', pipeline: pipeline) } before do - create(:ci_job_artifact, :cobertura, job: build_rspec, project: project) - create(:ci_job_artifact, :coverage_gocov_xml, job: build_golang, project: project) + create(:ci_job_artifact, :cobertura, job: build_rspec) + create(:ci_job_artifact, :coverage_gocov_xml, job: build_golang) end it 'returns coverage reports with collected data' do @@ -3689,8 +3719,8 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do end it 'does not execute N+1 queries' do - single_build_pipeline = create(:ci_empty_pipeline, status: :created, project: project) - single_rspec = create(:ci_build, :success, name: 'rspec', pipeline: single_build_pipeline, project: project) + single_build_pipeline = create(:ci_empty_pipeline, :created) + single_rspec = create(:ci_build, :success, name: 'rspec', pipeline: single_build_pipeline) create(:ci_job_artifact, :cobertura, job: single_rspec, project: project) control = ActiveRecord::QueryRecorder.new { single_build_pipeline.coverage_reports } @@ -3699,8 +3729,8 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do end context 'when builds are retried' do - let!(:build_rspec) { create(:ci_build, :retried, :success, name: 'rspec', pipeline: pipeline, project: project) } - let!(:build_golang) { create(:ci_build, :retried, :success, name: 'golang', pipeline: pipeline, project: project) } + let!(:build_rspec) { create(:ci_build, :retried, :success, name: 'rspec', pipeline: pipeline) } + let!(:build_golang) { create(:ci_build, :retried, :success, name: 'golang', pipeline: pipeline) } it 'does not take retried builds into account' do expect(subject.files).to eql({}) @@ -3718,13 +3748,15 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do describe '#codequality_reports' do subject(:codequality_reports) { pipeline.codequality_reports } + let_it_be(:pipeline) { create(:ci_pipeline) } + context 'when pipeline has multiple builds with codequality reports' do - let(:build_rspec) { create(:ci_build, :success, name: 'rspec', pipeline: pipeline, project: project) } - let(:build_golang) { create(:ci_build, :success, name: 'golang', pipeline: pipeline, project: project) } + let(:build_rspec) { create(:ci_build, :success, name: 'rspec', pipeline: pipeline) } + let(:build_golang) { create(:ci_build, :success, name: 'golang', pipeline: pipeline) } before do - create(:ci_job_artifact, :codequality, job: build_rspec, project: project) - create(:ci_job_artifact, :codequality_without_errors, job: build_golang, project: project) + create(:ci_job_artifact, :codequality, job: build_rspec) + create(:ci_job_artifact, :codequality_without_errors, job: build_golang) end it 'returns codequality report with collected data' do @@ -3732,8 +3764,8 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do end context 'when builds are retried' do - let(:build_rspec) { create(:ci_build, :retried, :success, name: 'rspec', pipeline: pipeline, project: project) } - let(:build_golang) { create(:ci_build, :retried, :success, name: 'golang', pipeline: pipeline, project: project) } + let(:build_rspec) { create(:ci_build, :retried, :success, name: 'rspec', pipeline: pipeline) } + let(:build_golang) { create(:ci_build, :retried, :success, name: 'golang', pipeline: pipeline) } it 'returns a codequality reports without degradations' do expect(codequality_reports.degradations).to be_empty @@ -3749,6 +3781,7 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do end describe '#total_size' do + let(:pipeline) { create(:ci_pipeline) } let!(:build_job1) { create(:ci_build, pipeline: pipeline, stage_idx: 0) } let!(:build_job2) { create(:ci_build, pipeline: pipeline, stage_idx: 0) } let!(:test_job_failed_and_retried) { create(:ci_build, :failed, :retried, pipeline: pipeline, stage_idx: 1) } @@ -3785,17 +3818,11 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do end describe '#default_branch?' do - let(:default_branch) { 'master'} - subject { pipeline.default_branch? } - before do - allow(project).to receive(:default_branch).and_return(default_branch) - end - context 'when pipeline ref is the default branch of the project' do let(:pipeline) do - build(:ci_empty_pipeline, status: :created, project: project, ref: default_branch) + build(:ci_empty_pipeline, :created, project: project, ref: project.default_branch) end it "returns true" do @@ -3805,7 +3832,7 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do context 'when pipeline ref is not the default branch of the project' do let(:pipeline) do - build(:ci_empty_pipeline, status: :created, project: project, ref: 'another_branch') + build(:ci_empty_pipeline, :created, project: project, ref: 'another_branch') end it "returns false" do @@ -3815,7 +3842,7 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do end describe '#find_stage_by_name' do - let(:pipeline) { create(:ci_pipeline) } + let_it_be(:pipeline) { create(:ci_pipeline) } let(:stage_name) { 'test' } let(:stage) do @@ -3895,10 +3922,10 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do end describe '#parent_pipeline' do - let_it_be(:project) { create(:project) } + let_it_be_with_reload(:pipeline) { create(:ci_pipeline) } context 'when pipeline is triggered by a pipeline from the same project' do - let_it_be(:upstream_pipeline) { create(:ci_pipeline, project: project) } + let_it_be(:upstream_pipeline) { create(:ci_pipeline) } let_it_be(:pipeline) { create(:ci_pipeline, child_of: upstream_pipeline) } it 'returns the parent pipeline' do @@ -3911,7 +3938,7 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do end context 'when pipeline is triggered by a pipeline from another project' do - let(:pipeline) { create(:ci_pipeline, project: project) } + let(:pipeline) { create(:ci_pipeline) } let!(:upstream_pipeline) { create(:ci_pipeline, project: create(:project), upstream_of: pipeline) } it 'returns nil' do @@ -3938,7 +3965,7 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do describe '#child_pipelines' do let_it_be(:project) { create(:project) } - let(:pipeline) { create(:ci_pipeline, project: project) } + let_it_be_with_reload(:pipeline) { create(:ci_pipeline, project: project) } context 'when pipeline triggered other pipelines on same project' do let(:downstream_pipeline) { create(:ci_pipeline, project: pipeline.project) } @@ -3992,6 +4019,8 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do end describe 'upstream status interactions' do + let_it_be_with_reload(:pipeline) { create(:ci_pipeline, :created) } + context 'when a pipeline has an upstream status' do context 'when an upstream status is a bridge' do let(:bridge) { create(:ci_bridge, status: :pending) } @@ -4050,6 +4079,8 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do describe '#source_ref_path' do subject { pipeline.source_ref_path } + let(:pipeline) { create(:ci_pipeline, :created) } + context 'when pipeline is for a branch' do it { is_expected.to eq(Gitlab::Git::BRANCH_REF_PREFIX + pipeline.source_ref.to_s) } end @@ -4062,13 +4093,15 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do end context 'when pipeline is for a tag' do - let(:pipeline) { create(:ci_pipeline, project: project, tag: true) } + let(:pipeline) { create(:ci_pipeline, tag: true) } it { is_expected.to eq(Gitlab::Git::TAG_REF_PREFIX + pipeline.source_ref.to_s) } end end - describe "#builds_with_coverage" do + describe '#builds_with_coverage' do + let_it_be(:pipeline) { create(:ci_pipeline, :created) } + it 'returns builds with coverage only' do rspec = create(:ci_build, name: 'rspec', coverage: 97.1, pipeline: pipeline) jest = create(:ci_build, name: 'jest', coverage: 94.1, pipeline: pipeline) @@ -4092,10 +4125,11 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do end describe '#base_and_ancestors' do - let(:same_project) { false } - subject { pipeline.base_and_ancestors(same_project: same_project) } + let_it_be(:pipeline) { create(:ci_pipeline, :created) } + let(:same_project) { false } + context 'when pipeline is not child nor parent' do it 'returns just the pipeline itself' do expect(subject).to contain_exactly(pipeline) @@ -4103,8 +4137,8 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do end context 'when pipeline is child' do - let(:parent) { create(:ci_pipeline, project: pipeline.project) } - let(:sibling) { create(:ci_pipeline, project: pipeline.project) } + let(:parent) { create(:ci_pipeline) } + let(:sibling) { create(:ci_pipeline) } before do create_source_pipeline(parent, pipeline) @@ -4117,7 +4151,7 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do end context 'when pipeline is parent' do - let(:child) { create(:ci_pipeline, project: pipeline.project) } + let(:child) { create(:ci_pipeline) } before do create_source_pipeline(pipeline, child) @@ -4129,8 +4163,9 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do end context 'when pipeline is a child of a child pipeline' do - let(:ancestor) { create(:ci_pipeline, project: pipeline.project) } - let(:parent) { create(:ci_pipeline, project: pipeline.project) } + let_it_be(:pipeline) { create(:ci_pipeline, :created) } + let(:ancestor) { create(:ci_pipeline) } + let(:parent) { create(:ci_pipeline) } before do create_source_pipeline(ancestor, parent) @@ -4143,6 +4178,7 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do end context 'when pipeline is a triggered pipeline' do + let_it_be(:pipeline) { create(:ci_pipeline, :created) } let(:upstream) { create(:ci_pipeline, project: create(:project)) } before do @@ -4166,8 +4202,10 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do end describe 'reset_ancestor_bridges!' do + let_it_be(:pipeline) { create(:ci_pipeline, :created) } + context 'when the pipeline is a child pipeline and the bridge is depended' do - let!(:parent_pipeline) { create(:ci_pipeline, project: project) } + let!(:parent_pipeline) { create(:ci_pipeline) } let!(:bridge) { create_bridge(parent_pipeline, pipeline, true) } it 'marks source bridge as pending' do @@ -4191,7 +4229,7 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do end context 'when the pipeline is a child pipeline and the bridge is not depended' do - let!(:parent_pipeline) { create(:ci_pipeline, project: project) } + let!(:parent_pipeline) { create(:ci_pipeline) } let!(:bridge) { create_bridge(parent_pipeline, pipeline, false) } it 'does not touch source bridge' do @@ -4227,6 +4265,8 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do end describe 'test failure history processing' do + let(:pipeline) { build(:ci_pipeline, :created) } + it 'performs the service asynchronously when the pipeline is completed' do service = double @@ -4238,21 +4278,23 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do end describe '#latest_test_report_builds' do + let_it_be(:pipeline) { create(:ci_pipeline, :created) } + it 'returns pipeline builds with test report artifacts' do - test_build = create(:ci_build, :test_reports, pipeline: pipeline, project: project) + test_build = create(:ci_build, :test_reports, pipeline: pipeline) create(:ci_build, :artifacts, pipeline: pipeline, project: project) expect(pipeline.latest_test_report_builds).to contain_exactly(test_build) end it 'preloads project on each build to avoid N+1 queries' do - create(:ci_build, :test_reports, pipeline: pipeline, project: project) + create(:ci_build, :test_reports, pipeline: pipeline) control_count = ActiveRecord::QueryRecorder.new do pipeline.latest_test_report_builds.map(&:project).map(&:full_path) end - multi_build_pipeline = create(:ci_empty_pipeline, status: :created, project: project) + multi_build_pipeline = create(:ci_empty_pipeline, :created) create(:ci_build, :test_reports, pipeline: multi_build_pipeline, project: project) create(:ci_build, :test_reports, pipeline: multi_build_pipeline, project: project) @@ -4262,30 +4304,32 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do end describe '#builds_with_failed_tests' do + let_it_be(:pipeline) { create(:ci_pipeline, :created) } + it 'returns pipeline builds with test report artifacts' do - failed_build = create(:ci_build, :failed, :test_reports, pipeline: pipeline, project: project) - create(:ci_build, :success, :test_reports, pipeline: pipeline, project: project) + failed_build = create(:ci_build, :failed, :test_reports, pipeline: pipeline) + create(:ci_build, :success, :test_reports, pipeline: pipeline) expect(pipeline.builds_with_failed_tests).to contain_exactly(failed_build) end it 'supports limiting the number of builds to fetch' do - create(:ci_build, :failed, :test_reports, pipeline: pipeline, project: project) - create(:ci_build, :failed, :test_reports, pipeline: pipeline, project: project) + create(:ci_build, :failed, :test_reports, pipeline: pipeline) + create(:ci_build, :failed, :test_reports, pipeline: pipeline) expect(pipeline.builds_with_failed_tests(limit: 1).count).to eq(1) end it 'preloads project on each build to avoid N+1 queries' do - create(:ci_build, :failed, :test_reports, pipeline: pipeline, project: project) + create(:ci_build, :failed, :test_reports, pipeline: pipeline) control_count = ActiveRecord::QueryRecorder.new do pipeline.builds_with_failed_tests.map(&:project).map(&:full_path) end - multi_build_pipeline = create(:ci_empty_pipeline, status: :created, project: project) - create(:ci_build, :failed, :test_reports, pipeline: multi_build_pipeline, project: project) - create(:ci_build, :failed, :test_reports, pipeline: multi_build_pipeline, project: project) + multi_build_pipeline = create(:ci_empty_pipeline, :created) + create(:ci_build, :failed, :test_reports, pipeline: multi_build_pipeline) + create(:ci_build, :failed, :test_reports, pipeline: multi_build_pipeline) expect { multi_build_pipeline.builds_with_failed_tests.map(&:project).map(&:full_path) } .not_to exceed_query_limit(control_count) |