diff options
Diffstat (limited to 'spec/models/ci/pipeline_spec.rb')
-rw-r--r-- | spec/models/ci/pipeline_spec.rb | 184 |
1 files changed, 146 insertions, 38 deletions
diff --git a/spec/models/ci/pipeline_spec.rb b/spec/models/ci/pipeline_spec.rb index 4f53b6b4418..782a4206c36 100644 --- a/spec/models/ci/pipeline_spec.rb +++ b/spec/models/ci/pipeline_spec.rb @@ -26,6 +26,8 @@ describe Ci::Pipeline, :mailer do it { is_expected.to have_many(:trigger_requests) } it { is_expected.to have_many(:variables) } it { is_expected.to have_many(:builds) } + it { is_expected.to have_many(:bridges) } + it { is_expected.to have_many(:job_artifacts).through(:builds) } it { is_expected.to have_many(:auto_canceled_pipelines) } it { is_expected.to have_many(:auto_canceled_jobs) } it { is_expected.to have_many(:sourced_pipelines) } @@ -51,6 +53,27 @@ describe Ci::Pipeline, :mailer do expect(Project.reflect_on_association(:all_pipelines).has_inverse?).to eq(:project) expect(Project.reflect_on_association(:ci_pipelines).has_inverse?).to eq(:project) end + + describe '#latest_builds' do + it 'has a one to many relationship with its latest builds' do + _old_build = create(:ci_build, :retried, pipeline: pipeline) + latest_build = create(:ci_build, :expired, pipeline: pipeline) + + expect(pipeline.latest_builds).to contain_exactly(latest_build) + end + end + + describe '#downloadable_artifacts' do + let(:build) { create(:ci_build, pipeline: pipeline) } + + it 'returns downloadable artifacts that have not expired' do + downloadable_artifact = create(:ci_job_artifact, :codequality, job: build) + _expired_artifact = create(:ci_job_artifact, :junit, :expired, job: build) + _undownloadable_artifact = create(:ci_job_artifact, :trace, job: build) + + expect(pipeline.downloadable_artifacts).to contain_exactly(downloadable_artifact) + end + end end describe '#set_status' do @@ -99,6 +122,17 @@ describe Ci::Pipeline, :mailer do end end + describe '.for_iid' do + subject { described_class.for_iid(iid) } + + let(:iid) { '1234' } + let!(:pipeline) { create(:ci_pipeline, iid: '1234') } + + it 'returns the pipeline' do + is_expected.to contain_exactly(pipeline) + end + end + describe '.for_sha' do subject { described_class.for_sha(sha) } @@ -1007,19 +1041,6 @@ describe Ci::Pipeline, :mailer do subject { pipeline.ordered_stages } - context 'when using legacy stages' do - before do - stub_feature_flags( - ci_pipeline_persisted_stages: false, - ci_atomic_processing: false - ) - end - - it 'returns legacy stages in valid order' do - expect(subject.map(&:name)).to eq %w[build test] - end - end - context 'when using atomic processing' do before do stub_feature_flags( @@ -1051,7 +1072,6 @@ describe Ci::Pipeline, :mailer do context 'when using persisted stages' do before do stub_feature_flags( - ci_pipeline_persisted_stages: true, ci_atomic_processing: false ) end @@ -1079,7 +1099,7 @@ describe Ci::Pipeline, :mailer do end describe 'state machine' do - let(:current) { Time.now.change(usec: 0) } + let(:current) { Time.current.change(usec: 0) } let(:build) { create_build('build1', queued_at: 0) } let(:build_b) { create_build('build2', queued_at: 0) } let(:build_c) { create_build('build3', queued_at: 0) } @@ -2633,38 +2653,34 @@ describe Ci::Pipeline, :mailer do end end - shared_examples 'enqueues the notification worker' do - it 'enqueues PipelineUpdateCiRefStatusWorker' do - expect(PipelineUpdateCiRefStatusWorker).to receive(:perform_async).with(pipeline.id) - expect(PipelineNotificationWorker).not_to receive(:perform_async).with(pipeline.id) + context 'with success pipeline' do + it_behaves_like 'sending a notification' do + before do + perform_enqueued_jobs do + pipeline.succeed + end + end + end + + it 'enqueues PipelineNotificationWorker' do + expect(PipelineNotificationWorker) + .to receive(:perform_async).with(pipeline.id, ref_status: :success) pipeline.succeed end - context 'when ci_pipeline_fixed_notifications is disabled' do + context 'when pipeline is not the latest' do before do - stub_feature_flags(ci_pipeline_fixed_notifications: false) + create(:ci_pipeline, :success, project: project, ci_ref: pipeline.ci_ref) end - it 'enqueues PipelineNotificationWorker' do - expect(PipelineUpdateCiRefStatusWorker).not_to receive(:perform_async).with(pipeline.id) - expect(PipelineNotificationWorker).to receive(:perform_async).with(pipeline.id) + it 'does not pass ref_status' do + expect(PipelineNotificationWorker) + .to receive(:perform_async).with(pipeline.id, ref_status: nil) - pipeline.succeed - end - end - end - - context 'with success pipeline' do - it_behaves_like 'sending a notification' do - before do - perform_enqueued_jobs do - pipeline.succeed - end + pipeline.succeed! end end - - it_behaves_like 'enqueues the notification worker' end context 'with failed pipeline' do @@ -2679,7 +2695,12 @@ describe Ci::Pipeline, :mailer do end end - it_behaves_like 'enqueues the notification worker' + it 'enqueues PipelineNotificationWorker' do + expect(PipelineNotificationWorker) + .to receive(:perform_async).with(pipeline.id, ref_status: :failed) + + pipeline.drop + end end context 'with skipped pipeline' do @@ -2703,6 +2724,69 @@ describe Ci::Pipeline, :mailer do end end + describe 'updates ci_ref when pipeline finished' do + context 'when ci_ref exists' do + let!(:pipeline) { create(:ci_pipeline, :running) } + + it 'updates the ci_ref' do + expect(pipeline.ci_ref) + .to receive(:update_status_by!).with(pipeline).and_call_original + + pipeline.succeed! + end + end + + context 'when ci_ref does not exist' do + let!(:pipeline) { create(:ci_pipeline, :running, ci_ref_presence: false) } + + it 'does not raise an exception' do + expect { pipeline.succeed! }.not_to raise_error + end + end + end + + describe '#ensure_ci_ref!' do + subject { pipeline.ensure_ci_ref! } + + shared_examples_for 'protected by feature flag' do + context 'when feature flag is disabled' do + before do + stub_feature_flags(ci_pipeline_fixed_notifications: false) + end + + it 'does not do anything' do + expect(Ci::Ref).not_to receive(:ensure_for) + + subject + end + end + end + + context 'when ci_ref does not exist yet' do + let!(:pipeline) { create(:ci_pipeline, ci_ref_presence: false) } + + it_behaves_like 'protected by feature flag' + + it 'creates a new ci_ref and assigns it' do + expect { subject }.to change { Ci::Ref.count }.by(1) + + expect(pipeline.ci_ref).to be_present + end + end + + context 'when ci_ref already exists' do + let!(:pipeline) { create(:ci_pipeline) } + + it_behaves_like 'protected by feature flag' + + it 'fetches a new ci_ref and assigns it' do + expect { subject }.not_to change { Ci::Ref.count } + + expect(pipeline.ci_ref).to be_present + end + end + end + describe '#find_job_with_archive_artifacts' do let!(:old_job) { create(:ci_build, name: 'rspec', retried: true, pipeline: pipeline) } let!(:job_without_artifacts) { create(:ci_build, name: 'rspec', pipeline: pipeline) } @@ -2741,6 +2825,30 @@ describe Ci::Pipeline, :mailer do end end + describe '#latest_report_builds' do + 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) + 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) + + 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) + + expect(pipeline.latest_report_builds).to contain_exactly(test_build) + end + end + describe '#has_reports?' do subject { pipeline.has_reports?(Ci::JobArtifact.test_reports) } |