Commit decd2c8f authored by Mike Kozono's avatar Mike Kozono

Add packageFileRegistry to GraphQL API

Accessible through a geoNode object.
parent ea81dd8c
......@@ -22,6 +22,11 @@ module Types
field :selective_sync_shards, type: [GraphQL::STRING_TYPE], null: true, description: 'The repository storages whose projects should be synced, if `selective_sync_type` == `shards`'
field :selective_sync_namespaces, ::Types::NamespaceType.connection_type, null: true, method: :namespaces, description: 'The namespaces that should be synced, if `selective_sync_type` == `namespaces`'
field :minimum_reverification_interval, GraphQL::INT_TYPE, null: true, description: 'The interval (in days) in which the repository verification is valid. Once expired, it will be reverified'
field :package_file_registries, ::Types::Geo::PackageFileRegistryType.connection_type,
null: true,
resolver: ::Resolvers::Geo::PackageFileRegistriesResolver,
description: 'Package file registries of the GeoNode',
feature_flag: :geo_self_service_framework
end
end
end
......@@ -11,7 +11,7 @@ describe GitlabSchema.types['GeoNode'] do
repos_max_capacity verification_max_capacity
container_repositories_max_capacity sync_object_storage
selective_sync_type selective_sync_shards selective_sync_namespaces
minimum_reverification_interval
minimum_reverification_interval package_file_registries
]
expect(described_class).to have_graphql_fields(*expected_fields)
......
# frozen_string_literal: true
require 'spec_helper'
describe 'Gets registries' do
it_behaves_like 'gets registries for', {
field_name: 'packageFileRegistries',
registry_class_name: 'PackageFileRegistry',
registry_factory: :package_file_registry,
registry_foreign_key_field_name: 'packageFileId'
}
end
# frozen_string_literal: true
RSpec.shared_examples 'gets registries for' do |args|
let(:field_name) { args[:field_name] }
let(:registry_class_name) { args[:registry_class_name] }
let(:registry_factory) { args[:registry_factory] }
let(:registry_foreign_key_field_name) { args[:registry_foreign_key_field_name] }
let(:registry_foreign_key) { registry_foreign_key_field_name.underscore }
let(:field_name_sym) { field_name.underscore.to_sym }
include GraphqlHelpers
include EE::GeoHelpers
let_it_be(:secondary) { create(:geo_node) }
let!(:registry1) { create(registry_factory) }
let!(:registry2) { create(registry_factory) }
let(:query) do
<<~QUERY
{
geoNode {
#{field_name} {
nodes {
#{all_graphql_fields_for(registry_class_name)}
}
}
}
}
QUERY
end
let(:current_user) { create(:user, :admin) }
before do
stub_current_geo_node(secondary)
stub_current_node_name(secondary.name)
end
it_behaves_like 'a working graphql query' do
before do
post_graphql(query, current_user: current_user)
end
end
it 'returns registries' do
expected = [registry1, registry2].map do |registry|
registry_to_graphql_data_hash(registry)
end
post_graphql(query, current_user: current_user)
actual = graphql_data_at(:geo_node, field_name_sym, :nodes)
expect(actual).to eq(expected)
end
context 'when paginating' do
let!(:expected_registry1) { create(registry_factory) }
let!(:expected_registry2) { create(registry_factory) }
def query(registries_params)
<<~QUERY
{
geoNode {
#{field_name}(#{registries_params}) {
edges {
node {
id
}
cursor
}
pageInfo {
endCursor
hasNextPage
}
}
}
}
QUERY
end
it 'supports cursor-based pagination' do
post_graphql(query('first: 2'), current_user: current_user)
edges = graphql_data_at(:geo_node, field_name_sym, :edges)
page_info = graphql_data_at(:geo_node, field_name_sym, :page_info)
has_next_page = graphql_data_at(:geo_node, field_name_sym, :page_info, :has_next_page)
expect(edges.size).to eq(2)
expect(page_info).to be_present
expect(has_next_page).to eq(true)
end
it 'returns the correct page of registries' do
# Get first page
post_graphql(query('first: 2'), current_user: current_user)
end_cursor = graphql_data_at(:geo_node, field_name_sym, :page_info, :end_cursor)
# Get second page
post_graphql(query("first: 2, after: \"#{end_cursor}\""), current_user: current_user)
response_data = JSON.parse(response.body).dig('data', 'geoNode', GraphqlHelpers.fieldnamerize(field_name), 'edges')
first_result = response_data.first['node']
second_result = response_data.second['node']
expect(first_result).to eq('id' => expected_registry1.to_global_id.to_s)
expect(second_result).to eq('id' => expected_registry2.to_global_id.to_s)
end
end
context 'when the geo_self_service_framework feature is disabled' do
before do
stub_feature_flags(geo_self_service_framework: false)
end
it 'errors when requesting registries' do
post_graphql(query, current_user: current_user)
expect_graphql_errors_to_include(/Field '#{field_name}' doesn't exist on type 'GeoNode'/)
end
end
def registry_to_graphql_data_hash(registry)
{
'id' => registry.to_global_id.to_s,
registry_foreign_key_field_name => registry.send(registry_foreign_key).to_s,
'state' => registry.state_name.to_s.upcase,
'retryCount' => registry.retry_count,
'lastSyncFailure' => registry.last_sync_failure,
'retryAt' => registry.retry_at,
'lastSyncedAt' => registry.last_synced_at,
'createdAt' => registry.created_at.iso8601
}
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