diff options
Diffstat (limited to 'spec/models/ci/pipeline_spec.rb')
-rw-r--r-- | spec/models/ci/pipeline_spec.rb | 217 |
1 files changed, 198 insertions, 19 deletions
diff --git a/spec/models/ci/pipeline_spec.rb b/spec/models/ci/pipeline_spec.rb index 3f9e882ea52..013581c0d94 100644 --- a/spec/models/ci/pipeline_spec.rb +++ b/spec/models/ci/pipeline_spec.rb @@ -35,6 +35,7 @@ describe Ci::Pipeline, :mailer do it { is_expected.to have_one(:source_pipeline) } it { is_expected.to have_one(:triggered_by_pipeline) } it { is_expected.to have_one(:source_job) } + it { is_expected.to have_one(:pipeline_config) } it { is_expected.to validate_presence_of(:sha) } it { is_expected.to validate_presence_of(:status) } @@ -1007,22 +1008,22 @@ describe Ci::Pipeline, :mailer do end end - describe '#duration', :sidekiq_might_not_need_inline do + describe '#duration', :sidekiq_inline do context 'when multiple builds are finished' do before do travel_to(current + 30) do build.run! - build.success! + build.reload.success! build_b.run! build_c.run! end travel_to(current + 40) do - build_b.drop! + build_b.reload.drop! end travel_to(current + 70) do - build_c.success! + build_c.reload.success! end end @@ -1043,7 +1044,7 @@ describe Ci::Pipeline, :mailer do end travel_to(current + 5.minutes) do - build.success! + build.reload.success! end end @@ -1182,6 +1183,38 @@ describe Ci::Pipeline, :mailer do end end + describe 'auto devops pipeline metrics' do + using RSpec::Parameterized::TableSyntax + + let(:pipeline) { create(:ci_empty_pipeline, config_source: config_source) } + let(:config_source) { :auto_devops_source } + + where(:action, :status) do + :succeed | 'success' + :drop | 'failed' + :skip | 'skipped' + :cancel | 'canceled' + end + + with_them do + context "when pipeline receives action '#{params[:action]}'" do + subject { pipeline.public_send(action) } + + it { expect { subject }.to change { auto_devops_pipelines_completed_total(status) }.by(1) } + + context 'when not auto_devops_source?' do + let(:config_source) { :repository_source } + + it { expect { subject }.not_to change { auto_devops_pipelines_completed_total(status) } } + end + end + end + + def auto_devops_pipelines_completed_total(status) + Gitlab::Metrics.counter(:auto_devops_pipelines_completed_total, 'Number of completed auto devops pipelines').get(status: status) + end + end + def create_build(name, *traits, queued_at: current, started_from: 0, **opts) create(:ci_build, *traits, name: name, @@ -1552,6 +1585,30 @@ describe Ci::Pipeline, :mailer do end end + describe '#needs_processing?' do + using RSpec::Parameterized::TableSyntax + + subject { pipeline.needs_processing? } + + where(:processed, :result) do + nil | true + false | true + true | false + end + + with_them do + let(:build) do + create(:ci_build, :success, pipeline: pipeline, name: 'rubocop') + end + + before do + build.update_column(:processed, processed) + end + + it { is_expected.to eq(result) } + end + end + shared_context 'with some outdated pipelines' do before do create_pipeline(:canceled, 'ref', 'A', project) @@ -1749,16 +1806,27 @@ describe Ci::Pipeline, :mailer do subject { described_class.bridgeable_statuses } it { is_expected.to be_an(Array) } - it { is_expected.not_to include('created', 'preparing', 'pending') } + it { is_expected.not_to include('created', 'waiting_for_resource', 'preparing', 'pending') } end - describe '#status', :sidekiq_might_not_need_inline do + describe '#status', :sidekiq_inline do let(:build) do create(:ci_build, :created, pipeline: pipeline, name: 'test') end subject { pipeline.reload.status } + context 'on waiting for resource' do + before do + allow(build).to receive(:requires_resource?) { true } + allow(Ci::ResourceGroups::AssignResourceFromResourceGroupWorker).to receive(:perform_async) + + build.enqueue + end + + it { is_expected.to eq('waiting_for_resource') } + end + context 'on prepare' do before do # Prevent skipping directly to 'pending' @@ -1782,7 +1850,7 @@ describe Ci::Pipeline, :mailer do context 'on run' do before do build.enqueue - build.run + build.reload.run end it { is_expected.to eq('running') } @@ -1841,7 +1909,7 @@ describe Ci::Pipeline, :mailer do it 'updates does not change pipeline status' do expect(pipeline.statuses.latest.slow_composite_status).to be_nil - expect { pipeline.update_status } + expect { pipeline.update_legacy_status } .to change { pipeline.reload.status } .from('created') .to('skipped') @@ -1854,7 +1922,7 @@ describe Ci::Pipeline, :mailer do end it 'updates pipeline status to running' do - expect { pipeline.update_status } + expect { pipeline.update_legacy_status } .to change { pipeline.reload.status } .from('created') .to('running') @@ -1867,7 +1935,7 @@ describe Ci::Pipeline, :mailer do end it 'updates pipeline status to scheduled' do - expect { pipeline.update_status } + expect { pipeline.update_legacy_status } .to change { pipeline.reload.status } .from('created') .to('scheduled') @@ -1882,7 +1950,7 @@ describe Ci::Pipeline, :mailer do end it 'raises an exception' do - expect { pipeline.update_status } + expect { pipeline.update_legacy_status } .to raise_error(HasStatus::UnknownStatusError) end end @@ -2170,11 +2238,11 @@ describe Ci::Pipeline, :mailer do stub_full_request(hook.url, method: :post) end - context 'with multiple builds', :sidekiq_might_not_need_inline do + context 'with multiple builds', :sidekiq_inline do context 'when build is queued' do before do - build_a.enqueue - build_b.enqueue + build_a.reload.enqueue + build_b.reload.enqueue end it 'receives a pending event once' do @@ -2184,10 +2252,10 @@ describe Ci::Pipeline, :mailer do context 'when build is run' do before do - build_a.enqueue - build_a.run - build_b.enqueue - build_b.run + build_a.reload.enqueue + build_a.reload.run! + build_b.reload.enqueue + build_b.reload.run! end it 'receives a running event once' do @@ -2248,6 +2316,7 @@ describe Ci::Pipeline, :mailer do :created, pipeline: pipeline, name: name, + stage: "stage:#{stage_idx}", stage_idx: stage_idx) end end @@ -2704,4 +2773,114 @@ describe Ci::Pipeline, :mailer do end end end + + describe '#parent_pipeline' do + let(:project) { create(:project) } + let(:pipeline) { create(:ci_pipeline, project: project) } + + context 'when pipeline is triggered by a pipeline from the same project' do + let(:upstream_pipeline) { create(:ci_pipeline, project: pipeline.project) } + + before do + create(:ci_sources_pipeline, + source_pipeline: upstream_pipeline, + source_project: project, + pipeline: pipeline, + project: project) + end + + it 'returns the parent pipeline' do + expect(pipeline.parent_pipeline).to eq(upstream_pipeline) + end + + it 'is child' do + expect(pipeline).to be_child + end + end + + context 'when pipeline is triggered by a pipeline from another project' do + let(:upstream_pipeline) { create(:ci_pipeline) } + + before do + create(:ci_sources_pipeline, + source_pipeline: upstream_pipeline, + source_project: upstream_pipeline.project, + pipeline: pipeline, + project: project) + end + + it 'returns nil' do + expect(pipeline.parent_pipeline).to be_nil + end + + it 'is not child' do + expect(pipeline).not_to be_child + end + end + + context 'when pipeline is not triggered by a pipeline' do + it 'returns nil' do + expect(pipeline.parent_pipeline).to be_nil + end + + it 'is not child' do + expect(pipeline).not_to be_child + end + end + end + + describe '#child_pipelines' do + let(:project) { create(:project) } + let(: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) } + + before do + create(:ci_sources_pipeline, + source_pipeline: pipeline, + source_project: pipeline.project, + pipeline: downstream_pipeline, + project: pipeline.project) + end + + it 'returns the child pipelines' do + expect(pipeline.child_pipelines).to eq [downstream_pipeline] + end + + it 'is parent' do + expect(pipeline).to be_parent + end + end + + context 'when pipeline triggered other pipelines on another project' do + let(:downstream_pipeline) { create(:ci_pipeline) } + + before do + create(:ci_sources_pipeline, + source_pipeline: pipeline, + source_project: pipeline.project, + pipeline: downstream_pipeline, + project: downstream_pipeline.project) + end + + it 'returns empty array' do + expect(pipeline.child_pipelines).to be_empty + end + + it 'is not parent' do + expect(pipeline).not_to be_parent + end + end + + context 'when pipeline did not trigger any pipelines' do + it 'returns empty array' do + expect(pipeline.child_pipelines).to be_empty + end + + it 'is not parent' do + expect(pipeline).not_to be_parent + end + end + end end |