diff options
Diffstat (limited to 'spec/models/ci/runner_spec.rb')
-rw-r--r-- | spec/models/ci/runner_spec.rb | 112 |
1 files changed, 93 insertions, 19 deletions
diff --git a/spec/models/ci/runner_spec.rb b/spec/models/ci/runner_spec.rb index 3e5d068d780..ff3551d2a18 100644 --- a/spec/models/ci/runner_spec.rb +++ b/spec/models/ci/runner_spec.rb @@ -40,41 +40,39 @@ RSpec.describe Ci::Runner do context 'runner_type validations' do let_it_be(:group) { create(:group) } let_it_be(:project) { create(:project) } - let(:group_runner) { create(:ci_runner, :group, groups: [group]) } - let(:project_runner) { create(:ci_runner, :project, projects: [project]) } - let(:instance_runner) { create(:ci_runner, :instance) } it 'disallows assigning group to project_type runner' do - project_runner.groups << build(:group) + project_runner = build(:ci_runner, :project, groups: [group]) expect(project_runner).not_to be_valid expect(project_runner.errors.full_messages).to include('Runner cannot have groups assigned') end it 'disallows assigning group to instance_type runner' do - instance_runner.groups << build(:group) + instance_runner = build(:ci_runner, :instance, groups: [group]) expect(instance_runner).not_to be_valid expect(instance_runner.errors.full_messages).to include('Runner cannot have groups assigned') end it 'disallows assigning project to group_type runner' do - group_runner.projects << build(:project) + group_runner = build(:ci_runner, :instance, projects: [project]) expect(group_runner).not_to be_valid expect(group_runner.errors.full_messages).to include('Runner cannot have projects assigned') end it 'disallows assigning project to instance_type runner' do - instance_runner.projects << build(:project) + instance_runner = build(:ci_runner, :instance, projects: [project]) expect(instance_runner).not_to be_valid expect(instance_runner.errors.full_messages).to include('Runner cannot have projects assigned') end it 'fails to save a group assigned to a project runner even if the runner is already saved' do - group.runners << project_runner - expect { group.save! } + project_runner = create(:ci_runner, :project, projects: [project]) + + expect { create(:group, runners: [project_runner]) } .to raise_error(ActiveRecord::RecordInvalid) end end @@ -352,6 +350,8 @@ RSpec.describe Ci::Runner do end describe '#can_pick?' do + using RSpec::Parameterized::TableSyntax + let_it_be(:pipeline) { create(:ci_pipeline) } let(:build) { create(:ci_build, pipeline: pipeline) } let(:runner_project) { build.project } @@ -365,6 +365,11 @@ RSpec.describe Ci::Runner do let(:other_project) { create(:project) } let(:other_runner) { create(:ci_runner, :project, projects: [other_project], tag_list: tag_list, run_untagged: run_untagged) } + before do + # `can_pick?` is not used outside the runners available for the project + stub_feature_flags(ci_runners_short_circuit_assignable_for: false) + end + it 'cannot handle builds' do expect(other_runner.can_pick?(build)).to be_falsey end @@ -432,9 +437,32 @@ RSpec.describe Ci::Runner do expect(runner.can_pick?(build)).to be_truthy end end + + it 'does not query for owned or instance runners' do + expect(described_class).not_to receive(:owned_or_instance_wide) + + runner.can_pick?(build) + end + + context 'when feature flag ci_runners_short_circuit_assignable_for is disabled' do + before do + stub_feature_flags(ci_runners_short_circuit_assignable_for: false) + end + + it 'does not query for owned or instance runners' do + expect(described_class).to receive(:owned_or_instance_wide).and_call_original + + runner.can_pick?(build) + end + end end context 'when runner is not shared' do + before do + # `can_pick?` is not used outside the runners available for the project + stub_feature_flags(ci_runners_short_circuit_assignable_for: false) + end + context 'when runner is assigned to a project' do it 'can handle builds' do expect(runner.can_pick?(build)).to be_truthy @@ -502,6 +530,29 @@ RSpec.describe Ci::Runner do it { is_expected.to be_falsey } end end + + context 'matches tags' do + where(:run_untagged, :runner_tags, :build_tags, :result) do + true | [] | [] | true + true | [] | ['a'] | false + true | %w[a b] | ['a'] | true + true | ['a'] | %w[a b] | false + true | ['a'] | ['a'] | true + false | ['a'] | ['a'] | true + false | ['b'] | ['a'] | false + false | %w[a b] | ['a'] | true + end + + with_them do + let(:tag_list) { runner_tags } + + before do + build.tag_list = build_tags + end + + it { is_expected.to eq(result) } + end + end end describe '#status' do @@ -844,27 +895,50 @@ RSpec.describe Ci::Runner do end describe '#pick_build!' do + let(:build) { create(:ci_build) } + let(:runner) { create(:ci_runner) } + context 'runner can pick the build' do it 'calls #tick_runner_queue' do - ci_build = build(:ci_build) - runner = build(:ci_runner) - allow(runner).to receive(:can_pick?).with(ci_build).and_return(true) - expect(runner).to receive(:tick_runner_queue) - runner.pick_build!(ci_build) + runner.pick_build!(build) end end context 'runner cannot pick the build' do - it 'does not call #tick_runner_queue' do - ci_build = build(:ci_build) - runner = build(:ci_runner) - allow(runner).to receive(:can_pick?).with(ci_build).and_return(false) + before do + build.tag_list = [:docker] + end + it 'does not call #tick_runner_queue' do expect(runner).not_to receive(:tick_runner_queue) - runner.pick_build!(ci_build) + runner.pick_build!(build) + end + end + + context 'build picking improvement enabled' do + before do + stub_feature_flags(ci_reduce_queries_when_ticking_runner_queue: true) + end + + it 'does not check if the build is assignable to a runner' do + expect(runner).not_to receive(:can_pick?) + + runner.pick_build!(build) + end + end + + context 'build picking improvement disabled' do + before do + stub_feature_flags(ci_reduce_queries_when_ticking_runner_queue: false) + end + + it 'checks if the build is assignable to a runner' do + expect(runner).to receive(:can_pick?).and_call_original + + runner.pick_build!(build) end end end |