Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'spec/models/ci/ref_spec.rb')
-rw-r--r--spec/models/ci/ref_spec.rb168
1 files changed, 113 insertions, 55 deletions
diff --git a/spec/models/ci/ref_spec.rb b/spec/models/ci/ref_spec.rb
index 75071a17fa9..2727c7701b8 100644
--- a/spec/models/ci/ref_spec.rb
+++ b/spec/models/ci/ref_spec.rb
@@ -7,61 +7,6 @@ RSpec.describe Ci::Ref, feature_category: :continuous_integration do
it { is_expected.to belong_to(:project) }
- describe 'state machine transitions' do
- context 'unlock artifacts transition' do
- let(:ci_ref) { create(:ci_ref) }
- let(:unlock_previous_pipelines_worker_spy) { class_spy(::Ci::Refs::UnlockPreviousPipelinesWorker) }
-
- before do
- stub_const('Ci::Refs::UnlockPreviousPipelinesWorker', unlock_previous_pipelines_worker_spy)
- end
-
- context 'pipeline is locked' do
- let!(:pipeline) { create(:ci_pipeline, ci_ref_id: ci_ref.id, locked: :artifacts_locked) }
-
- where(:initial_state, :action, :count) do
- :unknown | :succeed! | 1
- :unknown | :do_fail! | 0
- :success | :succeed! | 1
- :success | :do_fail! | 0
- :failed | :succeed! | 1
- :failed | :do_fail! | 0
- :fixed | :succeed! | 1
- :fixed | :do_fail! | 0
- :broken | :succeed! | 1
- :broken | :do_fail! | 0
- :still_failing | :succeed | 1
- :still_failing | :do_fail | 0
- end
-
- with_them do
- context "when transitioning states" do
- before do
- status_value = Ci::Ref.state_machines[:status].states[initial_state].value
- ci_ref.update!(status: status_value)
- end
-
- it 'calls pipeline complete unlock artifacts service' do
- ci_ref.send(action)
-
- expect(unlock_previous_pipelines_worker_spy).to have_received(:perform_async).exactly(count).times
- end
- end
- end
- end
-
- context 'pipeline is unlocked' do
- let!(:pipeline) { create(:ci_pipeline, ci_ref_id: ci_ref.id, locked: :unlocked) }
-
- it 'does not unlock pipelines' do
- ci_ref.succeed!
-
- expect(unlock_previous_pipelines_worker_spy).not_to have_received(:perform_async)
- end
- end
- end
- end
-
describe '.ensure_for' do
let_it_be(:project) { create(:project, :repository) }
@@ -241,4 +186,117 @@ RSpec.describe Ci::Ref, feature_category: :continuous_integration do
let!(:model) { create(:ci_ref, project: parent) }
end
end
+
+ describe '#last_successful_ci_source_pipeline' do
+ let_it_be(:ci_ref) { create(:ci_ref) }
+
+ let(:ci_source) { Enums::Ci::Pipeline.sources[:push] }
+ let(:dangling_source) { Enums::Ci::Pipeline.sources[:parent_pipeline] }
+
+ subject(:result) { ci_ref.last_successful_ci_source_pipeline }
+
+ context 'when there are no successful CI source pipelines' do
+ let!(:running_ci_source) { create(:ci_pipeline, :running, ci_ref: ci_ref, source: ci_source) }
+ let!(:successful_dangling_source) { create(:ci_pipeline, :success, ci_ref: ci_ref, source: dangling_source) }
+
+ it { is_expected.to be_nil }
+ end
+
+ context 'when there are successful CI source pipelines' do
+ context 'and the latest pipeline is a successful CI source pipeline' do
+ let!(:failed_ci_source) { create(:ci_pipeline, :failed, ci_ref: ci_ref, source: ci_source) }
+ let!(:successful_dangling_source) { create(:ci_pipeline, :success, ci_ref: ci_ref, source: dangling_source, child_of: failed_ci_source) }
+ let!(:successful_ci_source) { create(:ci_pipeline, :success, ci_ref: ci_ref, source: ci_source) }
+
+ it 'returns the last successful CI source pipeline' do
+ expect(result).to eq(successful_ci_source)
+ end
+ end
+
+ context 'and there is a newer successful dangling source pipeline than the successful CI source pipelines' do
+ let!(:successful_ci_source_1) { create(:ci_pipeline, :success, ci_ref: ci_ref, source: ci_source) }
+ let!(:successful_ci_source_2) { create(:ci_pipeline, :success, ci_ref: ci_ref, source: ci_source) }
+ let!(:failed_ci_source) { create(:ci_pipeline, :failed, ci_ref: ci_ref, source: ci_source) }
+ let!(:successful_dangling_source) { create(:ci_pipeline, :success, ci_ref: ci_ref, source: dangling_source, child_of: failed_ci_source) }
+
+ it 'returns the last successful CI source pipeline' do
+ expect(result).to eq(successful_ci_source_2)
+ end
+
+ context 'and the newer successful dangling source is a child of a successful CI source pipeline' do
+ let!(:parent_ci_source) { create(:ci_pipeline, :success, ci_ref: ci_ref, source: ci_source) }
+ let!(:successful_child_source) { create(:ci_pipeline, :success, ci_ref: ci_ref, source: dangling_source, child_of: parent_ci_source) }
+
+ it 'returns the parent pipeline instead' do
+ expect(result).to eq(parent_ci_source)
+ end
+ end
+ end
+ end
+ end
+
+ describe '#last_unlockable_ci_source_pipeline' do
+ let(:ci_source) { Enums::Ci::Pipeline.sources[:push] }
+ let(:dangling_source) { Enums::Ci::Pipeline.sources[:parent_pipeline] }
+
+ let_it_be(:project) { create(:project) }
+ let_it_be(:ci_ref) { create(:ci_ref, project: project) }
+
+ subject(:result) { ci_ref.last_unlockable_ci_source_pipeline }
+
+ context 'when there are unlockable pipelines in the ref' do
+ context 'and the last CI source pipeline in the ref is unlockable' do
+ let!(:unlockable_ci_source_1) { create(:ci_pipeline, :success, project: project, ci_ref: ci_ref, source: ci_source) }
+ let!(:unlockable_ci_source_2) { create(:ci_pipeline, :blocked, project: project, ci_ref: ci_ref, source: ci_source) }
+
+ it 'returns the CI source pipeline' do
+ expect(result).to eq(unlockable_ci_source_2)
+ end
+
+ context 'and it has unlockable child pipelines' do
+ let!(:child) { create(:ci_pipeline, :success, project: project, ci_ref: ci_ref, source: dangling_source, child_of: unlockable_ci_source_2) }
+ let!(:child_2) { create(:ci_pipeline, :success, project: project, ci_ref: ci_ref, source: dangling_source, child_of: unlockable_ci_source_2) }
+
+ it 'returns the parent CI source pipeline' do
+ expect(result).to eq(unlockable_ci_source_2)
+ end
+ end
+
+ context 'and it has a non-unlockable child pipeline' do
+ let!(:child) { create(:ci_pipeline, :running, project: project, ci_ref: ci_ref, source: dangling_source, child_of: unlockable_ci_source_2) }
+
+ it 'returns the parent CI source pipeline' do
+ expect(result).to eq(unlockable_ci_source_2)
+ end
+ end
+ end
+
+ context 'and the last CI source pipeline in the ref is not unlockable' do
+ let!(:unlockable_ci_source) { create(:ci_pipeline, :skipped, project: project, ci_ref: ci_ref, source: ci_source) }
+ let!(:unlockable_dangling_source) { create(:ci_pipeline, :success, project: project, ci_ref: ci_ref, source: dangling_source, child_of: unlockable_ci_source) }
+ let!(:non_unlockable_ci_source) { create(:ci_pipeline, :running, project: project, ci_ref: ci_ref, source: ci_source) }
+ let!(:non_unlockable_ci_source_2) { create(:ci_pipeline, :running, project: project, ci_ref: ci_ref, source: ci_source) }
+
+ it 'returns the last unlockable CI source pipeline before it' do
+ expect(result).to eq(unlockable_ci_source)
+ end
+
+ context 'and it has unlockable child pipelines' do
+ let!(:child) { create(:ci_pipeline, :success, project: project, ci_ref: ci_ref, source: dangling_source, child_of: non_unlockable_ci_source) }
+ let!(:child_2) { create(:ci_pipeline, :success, project: project, ci_ref: ci_ref, source: dangling_source, child_of: non_unlockable_ci_source) }
+
+ it 'returns the last unlockable CI source pipeline before it' do
+ expect(result).to eq(unlockable_ci_source)
+ end
+ end
+ end
+ end
+
+ context 'when there are no unlockable pipelines in the ref' do
+ let!(:non_unlockable_pipeline) { create(:ci_pipeline, :running, project: project, ci_ref: ci_ref, source: ci_source) }
+ let!(:pipeline_from_another_ref) { create(:ci_pipeline, :success, source: ci_source) }
+
+ it { is_expected.to be_nil }
+ end
+ end
end