Commit 1b2701da authored by Andreas Brandl's avatar Andreas Brandl

Merge branch 'pedropombeiro/334956-fix-nil-project-count' into 'master'

Return 0 for projectCount when no associated projects are found

See merge request gitlab-org/gitlab!65252
parents 93fdb790 1532944d
...@@ -54,10 +54,12 @@ module Types ...@@ -54,10 +54,12 @@ module Types
# rubocop: disable CodeReuse/ActiveRecord # rubocop: disable CodeReuse/ActiveRecord
def project_count def project_count
BatchLoader::GraphQL.for(runner.id).batch(key: :runner_project_count) do |ids, loader, args| BatchLoader::GraphQL.for(runner.id).batch(key: :runner_project_count) do |ids, loader, args|
counts = ::Ci::RunnerProject.select(:runner_id, 'COUNT(*) as count') counts = ::Ci::Runner.project_type
.where(runner_id: ids) .select(:id, 'COUNT(ci_runner_projects.id) as count')
.group(:runner_id) .left_outer_joins(:runner_projects)
.index_by(&:runner_id) .where(id: ids)
.group(:id)
.index_by(&:id)
ids.each do |id| ids.each do |id|
loader.call(id, counts[id]&.count) loader.call(id, counts[id]&.count)
......
...@@ -5,25 +5,25 @@ require 'spec_helper' ...@@ -5,25 +5,25 @@ require 'spec_helper'
RSpec.describe 'Query.runner(id)' do RSpec.describe 'Query.runner(id)' do
include GraphqlHelpers include GraphqlHelpers
let_it_be(:user) { create_default(:user, :admin) } let_it_be(:user) { create(:user, :admin) }
let_it_be(:active_runner) do let_it_be(:active_instance_runner) do
create(:ci_runner, :instance, description: 'Runner 1', contacted_at: 2.hours.ago, create(:ci_runner, :instance, description: 'Runner 1', contacted_at: 2.hours.ago,
active: true, version: 'adfe156', revision: 'a', locked: true, ip_address: '127.0.0.1', maximum_timeout: 600, active: true, version: 'adfe156', revision: 'a', locked: true, ip_address: '127.0.0.1', maximum_timeout: 600,
access_level: 0, tag_list: %w[tag1 tag2], run_untagged: true) access_level: 0, tag_list: %w[tag1 tag2], run_untagged: true)
end end
let_it_be(:inactive_runner) do let_it_be(:inactive_instance_runner) do
create(:ci_runner, :instance, description: 'Runner 2', contacted_at: 1.day.ago, active: false, create(:ci_runner, :instance, description: 'Runner 2', contacted_at: 1.day.ago, active: false,
version: 'adfe157', revision: 'b', ip_address: '10.10.10.10', access_level: 1, run_untagged: true) version: 'adfe157', revision: 'b', ip_address: '10.10.10.10', access_level: 1, run_untagged: true)
end end
def get_runner(id) def get_runner(id)
case id case id
when :active_runner when :active_instance_runner
active_runner active_instance_runner
when :inactive_runner when :inactive_instance_runner
inactive_runner inactive_instance_runner
end end
end end
...@@ -86,7 +86,7 @@ RSpec.describe 'Query.runner(id)' do ...@@ -86,7 +86,7 @@ RSpec.describe 'Query.runner(id)' do
end end
describe 'for active runner' do describe 'for active runner' do
it_behaves_like 'runner details fetch', :active_runner it_behaves_like 'runner details fetch', :active_instance_runner
context 'when tagList is not requested' do context 'when tagList is not requested' do
let(:query) do let(:query) do
...@@ -95,7 +95,7 @@ RSpec.describe 'Query.runner(id)' do ...@@ -95,7 +95,7 @@ RSpec.describe 'Query.runner(id)' do
let(:query_path) do let(:query_path) do
[ [
[:runner, { id: active_runner.to_global_id.to_s }] [:runner, { id: active_instance_runner.to_global_id.to_s }]
] ]
end end
...@@ -110,29 +110,30 @@ RSpec.describe 'Query.runner(id)' do ...@@ -110,29 +110,30 @@ RSpec.describe 'Query.runner(id)' do
end end
describe 'for inactive runner' do describe 'for inactive runner' do
it_behaves_like 'runner details fetch', :inactive_runner it_behaves_like 'runner details fetch', :inactive_instance_runner
end end
describe 'for multiple runners' do describe 'for multiple runners' do
let_it_be(:project1) { create(:project, :test_repo) } let_it_be(:project1) { create(:project, :test_repo) }
let_it_be(:project2) { create(:project, :test_repo) } let_it_be(:project2) { create(:project, :test_repo) }
let_it_be(:project_runner) do let_it_be(:project_runner1) { create(:ci_runner, :project, projects: [project1, project2], description: 'Runner 1') }
create(:ci_runner, :project, projects: [project1, project2], description: 'Runner 1', contacted_at: 2.hours.ago, let_it_be(:project_runner2) { create(:ci_runner, :project, projects: [], description: 'Runner 2') }
active: true, version: 'adfe156', revision: 'a', locked: true, ip_address: '127.0.0.1', maximum_timeout: 600,
access_level: 0, run_untagged: true)
end
let!(:job) { create(:ci_build, runner: project_runner) } let!(:job) { create(:ci_build, runner: project_runner1) }
context 'requesting project and job counts' do context 'requesting project and job counts' do
let(:query) do let(:query) do
%( %(
query { query {
projectRunner: runner(id: "#{project_runner.to_global_id}") { projectRunner1: runner(id: "#{project_runner1.to_global_id}") {
projectCount
jobCount
}
projectRunner2: runner(id: "#{project_runner2.to_global_id}") {
projectCount projectCount
jobCount jobCount
} }
activeRunner: runner(id: "#{active_runner.to_global_id}") { activeInstanceRunner: runner(id: "#{active_instance_runner.to_global_id}") {
projectCount projectCount
jobCount jobCount
} }
...@@ -141,17 +142,23 @@ RSpec.describe 'Query.runner(id)' do ...@@ -141,17 +142,23 @@ RSpec.describe 'Query.runner(id)' do
end end
before do before do
project_runner2.projects.clear
post_graphql(query, current_user: user) post_graphql(query, current_user: user)
end end
it 'retrieves expected fields' do it 'retrieves expected fields' do
runner1_data = graphql_data_at(:project_runner) runner1_data = graphql_data_at(:project_runner1)
runner2_data = graphql_data_at(:active_runner) runner2_data = graphql_data_at(:project_runner2)
runner3_data = graphql_data_at(:active_instance_runner)
expect(runner1_data).to match a_hash_including( expect(runner1_data).to match a_hash_including(
'jobCount' => 1, 'jobCount' => 1,
'projectCount' => 2) 'projectCount' => 2)
expect(runner2_data).to match a_hash_including( expect(runner2_data).to match a_hash_including(
'jobCount' => 0,
'projectCount' => 0)
expect(runner3_data).to match a_hash_including(
'jobCount' => 0, 'jobCount' => 0,
'projectCount' => nil) 'projectCount' => nil)
end end
...@@ -159,15 +166,15 @@ RSpec.describe 'Query.runner(id)' do ...@@ -159,15 +166,15 @@ RSpec.describe 'Query.runner(id)' do
end end
describe 'by regular user' do describe 'by regular user' do
let(:user) { create_default(:user) } let(:user) { create(:user) }
it_behaves_like 'retrieval by unauthorized user', :active_runner it_behaves_like 'retrieval by unauthorized user', :active_instance_runner
end end
describe 'by unauthenticated user' do describe 'by unauthenticated user' do
let(:user) { nil } let(:user) { nil }
it_behaves_like 'retrieval by unauthorized user', :active_runner it_behaves_like 'retrieval by unauthorized user', :active_instance_runner
end end
describe 'Query limits' do describe 'Query limits' do
...@@ -185,7 +192,7 @@ RSpec.describe 'Query.runner(id)' do ...@@ -185,7 +192,7 @@ RSpec.describe 'Query.runner(id)' do
let(:single_query) do let(:single_query) do
<<~QUERY <<~QUERY
{ {
active: #{runner_query(active_runner)} active: #{runner_query(active_instance_runner)}
} }
QUERY QUERY
end end
...@@ -193,8 +200,8 @@ RSpec.describe 'Query.runner(id)' do ...@@ -193,8 +200,8 @@ RSpec.describe 'Query.runner(id)' do
let(:double_query) do let(:double_query) do
<<~QUERY <<~QUERY
{ {
active: #{runner_query(active_runner)} active: #{runner_query(active_instance_runner)}
inactive: #{runner_query(inactive_runner)} inactive: #{runner_query(inactive_instance_runner)}
} }
QUERY QUERY
end end
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment