diff options
Diffstat (limited to 'spec/models/ci/pipeline_spec.rb')
-rw-r--r-- | spec/models/ci/pipeline_spec.rb | 656 |
1 files changed, 359 insertions, 297 deletions
diff --git a/spec/models/ci/pipeline_spec.rb b/spec/models/ci/pipeline_spec.rb index 7dc84577f40..bc9bd8edc6e 100644 --- a/spec/models/ci/pipeline_spec.rb +++ b/spec/models/ci/pipeline_spec.rb @@ -11,10 +11,6 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do let_it_be(:namespace) { create_default(:namespace).freeze } let_it_be(:project) { create_default(:project, :repository).freeze } - let(:pipeline) do - create(:ci_empty_pipeline, status: :created, project: project) - end - it_behaves_like 'having unique enum values' it { is_expected.to belong_to(:project) } @@ -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 @@ -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) @@ -624,7 +634,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 @@ -633,17 +643,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 @@ -654,7 +668,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 @@ -664,6 +678,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 @@ -677,6 +693,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 @@ -686,49 +704,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 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 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: "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') @@ -790,6 +817,8 @@ 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] } @@ -816,21 +845,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, @@ -1016,9 +1042,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 @@ -1026,11 +1050,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 @@ -1040,6 +1061,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 @@ -1047,7 +1070,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 @@ -1075,6 +1098,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, @@ -1180,6 +1205,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') @@ -1202,6 +1229,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, @@ -1256,6 +1285,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) } @@ -1459,24 +1489,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 @@ -1628,15 +1659,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 @@ -1655,6 +1686,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 @@ -1665,16 +1698,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 @@ -1738,6 +1767,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 @@ -1746,8 +1777,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 @@ -1757,10 +1788,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 @@ -1771,7 +1799,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 @@ -1779,14 +1806,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 @@ -1845,6 +1870,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 @@ -1871,9 +1898,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 @@ -1884,7 +1913,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 @@ -1894,6 +1923,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') @@ -1910,7 +1941,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 @@ -1924,11 +1955,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 @@ -1962,6 +1991,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) } @@ -1983,6 +2014,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' @@ -2039,6 +2072,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') @@ -2047,7 +2082,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') @@ -2071,6 +2106,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 @@ -2090,122 +2127,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 @@ -2215,8 +2237,7 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do :ci_empty_pipeline, status: 'success', ref: 'master', - sha: '123', - project: project + sha: '123' ) end @@ -2225,8 +2246,7 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do :ci_empty_pipeline, status: 'success', ref: 'develop', - sha: '123', - project: project + sha: '123' ) end @@ -2235,8 +2255,7 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do :ci_empty_pipeline, status: 'success', ref: 'test', - sha: '456', - project: project + sha: '456' ) end @@ -2333,12 +2352,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 } @@ -2430,8 +2448,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') @@ -2508,6 +2528,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 @@ -2599,7 +2621,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 @@ -2642,7 +2666,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 @@ -2691,11 +2717,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 @@ -2721,7 +2748,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 @@ -2807,7 +2834,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| @@ -2819,7 +2846,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 @@ -2835,7 +2862,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') } @@ -2929,10 +2957,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 @@ -2969,9 +2996,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 } @@ -3018,6 +3043,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) @@ -3025,7 +3052,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) } @@ -3043,7 +3070,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) } @@ -3068,10 +3095,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) } @@ -3106,6 +3133,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 @@ -3150,6 +3179,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' @@ -3219,7 +3250,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 @@ -3320,7 +3351,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 @@ -3351,6 +3382,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) } @@ -3369,6 +3401,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 ) } @@ -3382,6 +3415,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) } @@ -3408,7 +3442,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) @@ -3417,24 +3451,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 @@ -3445,17 +3481,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 @@ -3463,20 +3499,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 @@ -3486,13 +3522,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 @@ -3503,17 +3539,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 @@ -3521,10 +3557,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 @@ -3534,13 +3570,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 @@ -3551,17 +3587,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 @@ -3581,10 +3617,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 @@ -3593,12 +3629,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 @@ -3616,13 +3652,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 @@ -3632,8 +3670,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) @@ -3653,13 +3691,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 @@ -3670,8 +3710,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 @@ -3689,13 +3729,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 @@ -3707,8 +3749,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 } @@ -3717,8 +3759,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({}) @@ -3736,13 +3778,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 @@ -3750,8 +3794,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 @@ -3767,6 +3811,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) } @@ -3807,7 +3852,7 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do context 'when pipeline ref is the default branch of the project' do let(:pipeline) do - build(:ci_empty_pipeline, status: :created, project: project, ref: project.default_branch) + build(:ci_empty_pipeline, :created, project: project, ref: project.default_branch) end it "returns true" do @@ -3817,7 +3862,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 @@ -3827,7 +3872,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 @@ -3907,10 +3952,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 @@ -3923,7 +3968,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 @@ -3950,7 +3995,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) } @@ -4004,6 +4049,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) } @@ -4062,6 +4109,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 @@ -4074,13 +4123,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) @@ -4104,10 +4155,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) @@ -4115,8 +4167,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) @@ -4129,7 +4181,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) @@ -4141,8 +4193,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) @@ -4155,6 +4208,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 @@ -4178,8 +4232,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 @@ -4203,7 +4259,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 @@ -4239,6 +4295,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 @@ -4250,21 +4308,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) @@ -4274,30 +4334,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) |