Commit d7b039d8 authored by Alexandru Croitor's avatar Alexandru Croitor

Query jira projects by key or name and override max_page_size

Jira REST API endpoint returns all projects in one request,
so we override graphql default 100 items default page size to
the size of records returned from Jira API call.
parent f7272b77
...@@ -16,7 +16,14 @@ module Resolvers ...@@ -16,7 +16,14 @@ module Resolvers
response = jira_projects(name: name) response = jira_projects(name: name)
if response.success? if response.success?
response.payload[:projects] projects_array = response.payload[:projects]
GraphQL::Pagination::ArrayConnection.new(
projects_array,
# override default max_page_size to whatever the size of the response is,
# see https://gitlab.com/gitlab-org/gitlab/-/issues/231394
args.merge({ max_page_size: projects_array.size })
)
else else
raise Gitlab::Graphql::Errors::BaseError, response.message raise Gitlab::Graphql::Errors::BaseError, response.message
end end
......
...@@ -13,8 +13,6 @@ module Types ...@@ -13,8 +13,6 @@ module Types
field :projects, field :projects,
Types::Projects::Services::JiraProjectType.connection_type, Types::Projects::Services::JiraProjectType.connection_type,
null: true, null: true,
connection: false,
extensions: [Gitlab::Graphql::Extensions::ExternallyPaginatedArrayExtension],
description: 'List of all Jira projects fetched through Jira REST API', description: 'List of all Jira projects fetched through Jira REST API',
resolver: Resolvers::Projects::JiraProjectsResolver resolver: Resolvers::Projects::JiraProjectsResolver
end end
......
...@@ -6,7 +6,7 @@ module Jira ...@@ -6,7 +6,7 @@ module Jira
class ListService < Base class ListService < Base
extend ::Gitlab::Utils::Override extend ::Gitlab::Utils::Override
def initialize(jira_service, params: {}) def initialize(jira_service, params = {})
super(jira_service, params) super(jira_service, params)
@query = params[:query] @query = params[:query]
...@@ -33,9 +33,9 @@ module Jira ...@@ -33,9 +33,9 @@ module Jira
end end
def match_query?(jira_project) def match_query?(jira_project)
query = query.to_s.downcase downcase_query = query.to_s.downcase
jira_project&.key&.downcase&.include?(query) || jira_project&.name&.downcase&.include?(query) jira_project&.key&.downcase&.include?(downcase_query) || jira_project&.name&.downcase&.include?(downcase_query)
end end
def empty_payload def empty_payload
......
---
title: Query Jira projects by key or name and return all Jira projects in one query
merge_request: 37799
author:
type: fixed
...@@ -1051,7 +1051,6 @@ Autogenerated return type of JiraImportUsers ...@@ -1051,7 +1051,6 @@ Autogenerated return type of JiraImportUsers
| Name | Type | Description | | Name | Type | Description |
| --- | ---- | ---------- | | --- | ---- | ---------- |
| `active` | Boolean | Indicates if the service is active | | `active` | Boolean | Indicates if the service is active |
| `projects` | JiraProjectConnection | List of all Jira projects fetched through Jira REST API |
| `type` | String | Class name of the service | | `type` | String | Class name of the service |
## JiraUser ## JiraUser
......
...@@ -17,7 +17,7 @@ RSpec.describe Resolvers::Projects::JiraProjectsResolver do ...@@ -17,7 +17,7 @@ RSpec.describe Resolvers::Projects::JiraProjectsResolver do
end end
end end
context 'when project has no jira service' do context 'when project has no Jira service' do
let_it_be(:jira_service) { nil } let_it_be(:jira_service) { nil }
context 'when user is a maintainer' do context 'when user is a maintainer' do
...@@ -29,7 +29,7 @@ RSpec.describe Resolvers::Projects::JiraProjectsResolver do ...@@ -29,7 +29,7 @@ RSpec.describe Resolvers::Projects::JiraProjectsResolver do
end end
end end
context 'when project has jira service' do context 'when project has Jira service' do
let(:jira_service) { create(:jira_service, project: project) } let(:jira_service) { create(:jira_service, project: project) }
context 'when user is a developer' do context 'when user is a developer' do
...@@ -46,10 +46,11 @@ RSpec.describe Resolvers::Projects::JiraProjectsResolver do ...@@ -46,10 +46,11 @@ RSpec.describe Resolvers::Projects::JiraProjectsResolver do
end end
context 'when Jira connection is valid' do context 'when Jira connection is valid' do
include_context 'jira projects request context' include_context 'Jira projects request context'
it 'returns jira projects' do it 'returns Jira projects', :aggregate_failures do
jira_projects = resolve_jira_projects resolver = resolve_jira_projects
jira_projects = resolver.items
project_keys = jira_projects.map(&:key) project_keys = jira_projects.map(&:key)
project_names = jira_projects.map(&:name) project_names = jira_projects.map(&:name)
project_ids = jira_projects.map(&:id) project_ids = jira_projects.map(&:id)
...@@ -58,6 +59,23 @@ RSpec.describe Resolvers::Projects::JiraProjectsResolver do ...@@ -58,6 +59,23 @@ RSpec.describe Resolvers::Projects::JiraProjectsResolver do
expect(project_keys).to eq(%w(EX ABC)) expect(project_keys).to eq(%w(EX ABC))
expect(project_names).to eq(%w(Example Alphabetical)) expect(project_names).to eq(%w(Example Alphabetical))
expect(project_ids).to eq(%w(10000 10001)) expect(project_ids).to eq(%w(10000 10001))
expect(resolver.max_page_size).to eq(2)
end
context 'when filtering projects by name' do
it 'returns Jira projects', :aggregate_failures do
resolver = resolve_jira_projects({ name: 'ABC' })
jira_projects = resolver.items
project_keys = jira_projects.map(&:key)
project_names = jira_projects.map(&:name)
project_ids = jira_projects.map(&:id)
expect(jira_projects.size).to eq 1
expect(project_keys).to eq(%w(ABC))
expect(project_names).to eq(%w(Alphabetical))
expect(project_ids).to eq(%w(10001))
expect(resolver.max_page_size).to eq(1)
end
end end
end end
......
...@@ -8,7 +8,7 @@ RSpec.describe 'query Jira projects' do ...@@ -8,7 +8,7 @@ RSpec.describe 'query Jira projects' do
let_it_be(:current_user) { create(:user) } let_it_be(:current_user) { create(:user) }
let_it_be(:project) { create(:project) } let_it_be(:project) { create(:project) }
include_context 'jira projects request context' include_context 'Jira projects request context'
let(:services) { graphql_data_at(:project, :services, :edges) } let(:services) { graphql_data_at(:project, :services, :edges) }
let(:jira_projects) { services.first.dig('node', 'projects', 'nodes') } let(:jira_projects) { services.first.dig('node', 'projects', 'nodes') }
......
...@@ -66,16 +66,28 @@ RSpec.describe Jira::Requests::Projects::ListService do ...@@ -66,16 +66,28 @@ RSpec.describe Jira::Requests::Projects::ListService do
context 'when the request returns values' do context 'when the request returns values' do
before do before do
expect(client).to receive(:get).and_return([{ "key" => 'project1' }, { "key" => 'project2' }]) expect(client).to receive(:get).and_return([{ 'key' => 'pr1', 'name' => 'First Project' }, { 'key' => 'pr2', 'name' => 'Second Project' }])
end end
it 'returns a paylod with jira projets' do it 'returns a paylod with Jira projets' do
payload = subject.payload payload = subject.payload
expect(subject.success?).to be_truthy expect(subject.success?).to be_truthy
expect(payload[:projects].map(&:key)).to eq(%w(project1 project2)) expect(payload[:projects].map(&:key)).to eq(%w(pr1 pr2))
expect(payload[:is_last]).to be_truthy expect(payload[:is_last]).to be_truthy
end end
context 'when filtering projects by name' do
let(:params) { { query: 'first' } }
it 'returns a paylod with Jira projets' do
payload = subject.payload
expect(subject.success?).to be_truthy
expect(payload[:projects].map(&:key)).to eq(%w(pr1))
expect(payload[:is_last]).to be_truthy
end
end
end end
end end
end end
......
# frozen_string_literal: true # frozen_string_literal: true
RSpec.shared_context 'jira projects request context' do RSpec.shared_context 'Jira projects request context' do
let(:url) { 'https://jira.example.com' } let(:url) { 'https://jira.example.com' }
let(:username) { 'jira-username' } let(:username) { 'jira-username' }
let(:password) { 'jira-password' } let(:password) { 'jira-password' }
......
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