diff options
Diffstat (limited to 'spec/services/ci/register_job_service_spec.rb')
-rw-r--r-- | spec/services/ci/register_job_service_spec.rb | 147 |
1 files changed, 79 insertions, 68 deletions
diff --git a/spec/services/ci/register_job_service_spec.rb b/spec/services/ci/register_job_service_spec.rb index 839a3c53f07..c4b1e2133ed 100644 --- a/spec/services/ci/register_job_service_spec.rb +++ b/spec/services/ci/register_job_service_spec.rb @@ -11,9 +11,37 @@ module Ci let!(:shared_runner) { create(:ci_runner, :instance) } let!(:specific_runner) { create(:ci_runner, :project, projects: [project]) } let!(:group_runner) { create(:ci_runner, :group, groups: [group]) } - let!(:pending_job) { create(:ci_build, pipeline: pipeline) } + let!(:pending_job) { create(:ci_build, :pending, :queued, pipeline: pipeline) } describe '#execute' do + context 'checks database loadbalancing stickiness' do + subject { described_class.new(shared_runner).execute } + + before do + project.update!(shared_runners_enabled: false) + end + + it 'result is valid if replica did caught-up' do + allow(Gitlab::Database::LoadBalancing).to receive(:enable?) + .and_return(true) + + expect(Gitlab::Database::LoadBalancing::Sticking).to receive(:all_caught_up?) + .with(:runner, shared_runner.id) { true } + + expect(subject).to be_valid + end + + it 'result is invalid if replica did not caught-up' do + allow(Gitlab::Database::LoadBalancing).to receive(:enable?) + .and_return(true) + + expect(Gitlab::Database::LoadBalancing::Sticking).to receive(:all_caught_up?) + .with(:runner, shared_runner.id) { false } + + expect(subject).not_to be_valid + end + end + shared_examples 'handles runner assignment' do context 'runner follow tag list' do it "picks build with the same tag" do @@ -76,11 +104,11 @@ module Ci let!(:project3) { create :project, shared_runners_enabled: true } let!(:pipeline3) { create :ci_pipeline, project: project3 } let!(:build1_project1) { pending_job } - let!(:build2_project1) { FactoryBot.create :ci_build, pipeline: pipeline } - let!(:build3_project1) { FactoryBot.create :ci_build, pipeline: pipeline } - let!(:build1_project2) { FactoryBot.create :ci_build, pipeline: pipeline2 } - let!(:build2_project2) { FactoryBot.create :ci_build, pipeline: pipeline2 } - let!(:build1_project3) { FactoryBot.create :ci_build, pipeline: pipeline3 } + let!(:build2_project1) { create(:ci_build, :pending, :queued, pipeline: pipeline) } + let!(:build3_project1) { create(:ci_build, :pending, :queued, pipeline: pipeline) } + let!(:build1_project2) { create(:ci_build, :pending, :queued, pipeline: pipeline2) } + let!(:build2_project2) { create(:ci_build, :pending, :queued, pipeline: pipeline2) } + let!(:build1_project3) { create(:ci_build, :pending, :queued, pipeline: pipeline3) } context 'when using fair scheduling' do context 'when all builds are pending' do @@ -227,17 +255,17 @@ module Ci let!(:pipeline3) { create(:ci_pipeline, project: project3) } let!(:build1_project1) { pending_job } - let!(:build2_project1) { create(:ci_build, pipeline: pipeline) } - let!(:build3_project1) { create(:ci_build, pipeline: pipeline) } - let!(:build1_project2) { create(:ci_build, pipeline: pipeline2) } - let!(:build2_project2) { create(:ci_build, pipeline: pipeline2) } - let!(:build1_project3) { create(:ci_build, pipeline: pipeline3) } + let!(:build2_project1) { create(:ci_build, :queued, pipeline: pipeline) } + let!(:build3_project1) { create(:ci_build, :queued, pipeline: pipeline) } + let!(:build1_project2) { create(:ci_build, :queued, pipeline: pipeline2) } + let!(:build2_project2) { create(:ci_build, :queued, pipeline: pipeline2) } + let!(:build1_project3) { create(:ci_build, :queued, pipeline: pipeline3) } # these shouldn't influence the scheduling let!(:unrelated_group) { create(:group) } let!(:unrelated_project) { create(:project, group_runners_enabled: true, group: unrelated_group) } let!(:unrelated_pipeline) { create(:ci_pipeline, project: unrelated_project) } - let!(:build1_unrelated_project) { create(:ci_build, pipeline: unrelated_pipeline) } + let!(:build1_unrelated_project) { create(:ci_build, :pending, :queued, pipeline: unrelated_pipeline) } let!(:unrelated_group_runner) { create(:ci_runner, :group, groups: [unrelated_group]) } it 'does not consider builds from other group runners' do @@ -318,7 +346,7 @@ module Ci subject { described_class.new(specific_runner).execute } context 'with multiple builds are in queue' do - let!(:other_build) { create :ci_build, pipeline: pipeline } + let!(:other_build) { create(:ci_build, :pending, :queued, pipeline: pipeline) } before do allow_any_instance_of(Ci::RegisterJobService).to receive(:builds_for_project_runner) @@ -359,7 +387,7 @@ module Ci let!(:specific_runner) { create(:ci_runner, :project, projects: [project]) } context 'when a job is protected' do - let!(:pending_job) { create(:ci_build, :protected, pipeline: pipeline) } + let!(:pending_job) { create(:ci_build, :pending, :queued, :protected, pipeline: pipeline) } it 'picks the job' do expect(execute(specific_runner)).to eq(pending_job) @@ -367,7 +395,7 @@ module Ci end context 'when a job is unprotected' do - let!(:pending_job) { create(:ci_build, pipeline: pipeline) } + let!(:pending_job) { create(:ci_build, :pending, :queued, pipeline: pipeline) } it 'picks the job' do expect(execute(specific_runner)).to eq(pending_job) @@ -375,7 +403,7 @@ module Ci end context 'when protected attribute of a job is nil' do - let!(:pending_job) { create(:ci_build, pipeline: pipeline) } + let!(:pending_job) { create(:ci_build, :pending, :queued, pipeline: pipeline) } before do pending_job.update_attribute(:protected, nil) @@ -391,7 +419,7 @@ module Ci let!(:specific_runner) { create(:ci_runner, :project, :ref_protected, projects: [project]) } context 'when a job is protected' do - let!(:pending_job) { create(:ci_build, :protected, pipeline: pipeline) } + let!(:pending_job) { create(:ci_build, :pending, :queued, :protected, pipeline: pipeline) } it 'picks the job' do expect(execute(specific_runner)).to eq(pending_job) @@ -399,7 +427,7 @@ module Ci end context 'when a job is unprotected' do - let!(:pending_job) { create(:ci_build, pipeline: pipeline) } + let!(:pending_job) { create(:ci_build, :pending, :queued, pipeline: pipeline) } it 'does not pick the job' do expect(execute(specific_runner)).to be_nil @@ -407,7 +435,7 @@ module Ci end context 'when protected attribute of a job is nil' do - let!(:pending_job) { create(:ci_build, pipeline: pipeline) } + let!(:pending_job) { create(:ci_build, :pending, :queued, pipeline: pipeline) } before do pending_job.update_attribute(:protected, nil) @@ -421,7 +449,7 @@ module Ci context 'runner feature set is verified' do let(:options) { { artifacts: { reports: { junit: "junit.xml" } } } } - let!(:pending_job) { create(:ci_build, :pending, pipeline: pipeline, options: options) } + let!(:pending_job) { create(:ci_build, :pending, :queued, pipeline: pipeline, options: options) } subject { execute(specific_runner, params) } @@ -457,7 +485,7 @@ module Ci shared_examples 'validation is active' do context 'when depended job has not been completed yet' do - let!(:pre_stage_job) { create(:ci_build, :manual, pipeline: pipeline, name: 'test', stage_idx: 0) } + let!(:pre_stage_job) { create(:ci_build, :pending, :queued, :manual, pipeline: pipeline, name: 'test', stage_idx: 0) } it { expect(subject).to eq(pending_job) } end @@ -494,7 +522,7 @@ module Ci shared_examples 'validation is not active' do context 'when depended job has not been completed yet' do - let!(:pre_stage_job) { create(:ci_build, :manual, pipeline: pipeline, name: 'test', stage_idx: 0) } + let!(:pre_stage_job) { create(:ci_build, :pending, :queued, :manual, pipeline: pipeline, name: 'test', stage_idx: 0) } it { expect(subject).to eq(pending_job) } end @@ -519,7 +547,7 @@ module Ci let!(:pre_stage_job) { create(:ci_build, :success, pipeline: pipeline, name: 'test', stage_idx: 0) } let!(:pending_job) do - create(:ci_build, :pending, + create(:ci_build, :pending, :queued, pipeline: pipeline, stage_idx: 1, options: { script: ["bash"], dependencies: ['test'] }) end @@ -530,7 +558,7 @@ module Ci end context 'when build is degenerated' do - let!(:pending_job) { create(:ci_build, :pending, :degenerated, pipeline: pipeline) } + let!(:pending_job) { create(:ci_build, :pending, :queued, :degenerated, pipeline: pipeline) } subject { execute(specific_runner, {}) } @@ -545,7 +573,7 @@ module Ci context 'when build has data integrity problem' do let!(:pending_job) do - create(:ci_build, :pending, pipeline: pipeline) + create(:ci_build, :pending, :queued, pipeline: pipeline) end before do @@ -570,7 +598,7 @@ module Ci context 'when build fails to be run!' do let!(:pending_job) do - create(:ci_build, :pending, pipeline: pipeline) + create(:ci_build, :pending, :queued, pipeline: pipeline) end before do @@ -612,12 +640,12 @@ module Ci context 'when only some builds can be matched by runner' do let!(:specific_runner) { create(:ci_runner, :project, projects: [project], tag_list: %w[matching]) } - let!(:pending_job) { create(:ci_build, pipeline: pipeline, tag_list: %w[matching]) } + let!(:pending_job) { create(:ci_build, :pending, :queued, pipeline: pipeline, tag_list: %w[matching]) } before do # create additional matching and non-matching jobs - create_list(:ci_build, 2, pipeline: pipeline, tag_list: %w[matching]) - create(:ci_build, pipeline: pipeline, tag_list: %w[non-matching]) + create_list(:ci_build, 2, :pending, :queued, pipeline: pipeline, tag_list: %w[matching]) + create(:ci_build, :pending, :queued, pipeline: pipeline, tag_list: %w[non-matching]) end it 'observes queue size of only matching jobs' do @@ -665,7 +693,7 @@ module Ci end context 'when there is another build in queue' do - let!(:next_pending_job) { create(:ci_build, pipeline: pipeline) } + let!(:next_pending_job) { create(:ci_build, :pending, :queued, pipeline: pipeline) } it 'skips this build and picks another build' do expect(Gitlab::Ci::Queue::Metrics.queue_operations_total).to receive(:increment) @@ -683,11 +711,7 @@ module Ci end end - context 'when ci_register_job_service_one_by_one is enabled' do - before do - stub_feature_flags(ci_register_job_service_one_by_one: true) - end - + context 'when a long queue is created' do it 'picks builds one-by-one' do expect(Ci::Build).to receive(:find).with(pending_job.id).and_call_original @@ -697,9 +721,17 @@ module Ci include_examples 'handles runner assignment' end - context 'when ci_register_job_service_one_by_one is disabled' do + context 'when joining with pending builds table' do + before do + stub_feature_flags(ci_pending_builds_queue_join: true) + end + + include_examples 'handles runner assignment' + end + + context 'when not joining with pending builds table' do before do - stub_feature_flags(ci_register_job_service_one_by_one: false) + stub_feature_flags(ci_pending_builds_queue_join: false) end include_examples 'handles runner assignment' @@ -747,8 +779,8 @@ module Ci end context 'when project already has running jobs' do - let!(:build2) { create( :ci_build, :running, pipeline: pipeline, runner: shared_runner) } - let!(:build3) { create( :ci_build, :running, pipeline: pipeline, runner: shared_runner) } + let!(:build2) { create(:ci_build, :running, pipeline: pipeline, runner: shared_runner) } + let!(:build3) { create(:ci_build, :running, pipeline: pipeline, runner: shared_runner) } it 'counts job queuing time histogram with expected labels' do allow(attempt_counter).to receive(:increment) @@ -831,42 +863,21 @@ module Ci end context 'when max queue depth is reached' do - let!(:pending_job) { create(:ci_build, :pending, :degenerated, pipeline: pipeline) } - let!(:pending_job_2) { create(:ci_build, :pending, :degenerated, pipeline: pipeline) } - let!(:pending_job_3) { create(:ci_build, :pending, pipeline: pipeline) } + let!(:pending_job) { create(:ci_build, :pending, :queued, :degenerated, pipeline: pipeline) } + let!(:pending_job_2) { create(:ci_build, :pending, :queued, :degenerated, pipeline: pipeline) } + let!(:pending_job_3) { create(:ci_build, :pending, :queued, pipeline: pipeline) } before do stub_const("#{described_class}::MAX_QUEUE_DEPTH", 2) end - context 'when feature is enabled' do - before do - stub_feature_flags(gitlab_ci_builds_queue_limit: true) - end + it 'returns 409 conflict' do + expect(Ci::Build.pending.unstarted.count).to eq 3 - it 'returns 409 conflict' do - expect(Ci::Build.pending.unstarted.count).to eq 3 + result = described_class.new(specific_runner).execute - result = described_class.new(specific_runner).execute - - expect(result).not_to be_valid - expect(result.build).to be_nil - end - end - - context 'when feature is disabled' do - before do - stub_feature_flags(gitlab_ci_builds_queue_limit: false) - end - - it 'returns a valid result' do - expect(Ci::Build.pending.unstarted.count).to eq 3 - - result = described_class.new(specific_runner).execute - - expect(result).to be_valid - expect(result.build).to eq pending_job_3 - end + expect(result).not_to be_valid + expect(result.build).to be_nil end end |