Commit f458b970 authored by Gabriel Mazetto's avatar Gabriel Mazetto

Merge branch 'tc-geo-mr-diffs-graphql' into 'master'

Geo: Implement GraphQL endpoint for MR diffs

Closes #215138

See merge request gitlab-org/gitlab!42363
parents de9eab66 a0784889
......@@ -6879,6 +6879,37 @@ type GeoNode {
"""
internalUrl: String
"""
Find merge request diff registries on this Geo node. Available only when
feature flag `geo_merge_request_diff_replication` is enabled
"""
mergeRequestDiffRegistries(
"""
Returns the elements in the list that come after the specified cursor.
"""
after: String
"""
Returns the elements in the list that come before the specified cursor.
"""
before: String
"""
Returns the first _n_ elements from the list.
"""
first: Int
"""
Filters registries by their ID
"""
ids: [ID!]
"""
Returns the last _n_ elements from the list.
"""
last: Int
): MergeRequestDiffRegistryConnection
"""
The interval (in days) in which the repository verification is valid. Once expired, it will be reverified
"""
......@@ -10676,6 +10707,86 @@ type MergeRequestCreatePayload {
mergeRequest: MergeRequest
}
"""
Represents the Geo sync and verification state of a Merge Request diff
"""
type MergeRequestDiffRegistry {
"""
Timestamp when the MergeRequestDiffRegistry was created
"""
createdAt: Time
"""
ID of the MergeRequestDiffRegistry
"""
id: ID!
"""
Error message during sync of the MergeRequestDiffRegistry
"""
lastSyncFailure: String
"""
Timestamp of the most recent successful sync of the MergeRequestDiffRegistry
"""
lastSyncedAt: Time
"""
ID of the Merge Request diff
"""
mergeRequestDiffId: ID!
"""
Timestamp after which the MergeRequestDiffRegistry should be resynced
"""
retryAt: Time
"""
Number of consecutive failed sync attempts of the MergeRequestDiffRegistry
"""
retryCount: Int
"""
Sync state of the MergeRequestDiffRegistry
"""
state: RegistryState
}
"""
The connection type for MergeRequestDiffRegistry.
"""
type MergeRequestDiffRegistryConnection {
"""
A list of edges.
"""
edges: [MergeRequestDiffRegistryEdge]
"""
A list of nodes.
"""
nodes: [MergeRequestDiffRegistry]
"""
Information to aid in pagination.
"""
pageInfo: PageInfo!
}
"""
An edge in a connection.
"""
type MergeRequestDiffRegistryEdge {
"""
A cursor for use in pagination.
"""
cursor: String!
"""
The item at the end of the edge.
"""
node: MergeRequestDiffRegistry
}
"""
An edge in a connection.
"""
......@@ -12091,7 +12202,7 @@ type PackageEdge {
}
"""
Represents the sync and verification state of a package file
Represents the Geo sync and verification state of a package file
"""
type PackageFileRegistry {
"""
......@@ -17503,7 +17614,7 @@ type TaskCompletionStatus {
}
"""
Represents the sync and verification state of a terraform state
Represents the Geo sync and verification state of a terraform state
"""
type TerraformStateRegistry {
"""
......
......@@ -19119,6 +19119,77 @@
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "mergeRequestDiffRegistries",
"description": "Find merge request diff registries on this Geo node. Available only when feature flag `geo_merge_request_diff_replication` is enabled",
"args": [
{
"name": "ids",
"description": "Filters registries by their ID",
"type": {
"kind": "LIST",
"name": null,
"ofType": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "ID",
"ofType": null
}
}
},
"defaultValue": null
},
{
"name": "after",
"description": "Returns the elements in the list that come after the specified cursor.",
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"defaultValue": null
},
{
"name": "before",
"description": "Returns the elements in the list that come before the specified cursor.",
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"defaultValue": null
},
{
"name": "first",
"description": "Returns the first _n_ elements from the list.",
"type": {
"kind": "SCALAR",
"name": "Int",
"ofType": null
},
"defaultValue": null
},
{
"name": "last",
"description": "Returns the last _n_ elements from the list.",
"type": {
"kind": "SCALAR",
"name": "Int",
"ofType": null
},
"defaultValue": null
}
],
"type": {
"kind": "OBJECT",
"name": "MergeRequestDiffRegistryConnection",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "minimumReverificationInterval",
"description": "The interval (in days) in which the repository verification is valid. Once expired, it will be reverified",
......@@ -29442,6 +29513,251 @@
"enumValues": null,
"possibleTypes": null
},
{
"kind": "OBJECT",
"name": "MergeRequestDiffRegistry",
"description": "Represents the Geo sync and verification state of a Merge Request diff",
"fields": [
{
"name": "createdAt",
"description": "Timestamp when the MergeRequestDiffRegistry was created",
"args": [
],
"type": {
"kind": "SCALAR",
"name": "Time",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "id",
"description": "ID of the MergeRequestDiffRegistry",
"args": [
],
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "ID",
"ofType": null
}
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "lastSyncFailure",
"description": "Error message during sync of the MergeRequestDiffRegistry",
"args": [
],
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "lastSyncedAt",
"description": "Timestamp of the most recent successful sync of the MergeRequestDiffRegistry",
"args": [
],
"type": {
"kind": "SCALAR",
"name": "Time",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "mergeRequestDiffId",
"description": "ID of the Merge Request diff",
"args": [
],
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "ID",
"ofType": null
}
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "retryAt",
"description": "Timestamp after which the MergeRequestDiffRegistry should be resynced",
"args": [
],
"type": {
"kind": "SCALAR",
"name": "Time",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "retryCount",
"description": "Number of consecutive failed sync attempts of the MergeRequestDiffRegistry",
"args": [
],
"type": {
"kind": "SCALAR",
"name": "Int",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "state",
"description": "Sync state of the MergeRequestDiffRegistry",
"args": [
],
"type": {
"kind": "ENUM",
"name": "RegistryState",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
}
],
"inputFields": null,
"interfaces": [
],
"enumValues": null,
"possibleTypes": null
},
{
"kind": "OBJECT",
"name": "MergeRequestDiffRegistryConnection",
"description": "The connection type for MergeRequestDiffRegistry.",
"fields": [
{
"name": "edges",
"description": "A list of edges.",
"args": [
],
"type": {
"kind": "LIST",
"name": null,
"ofType": {
"kind": "OBJECT",
"name": "MergeRequestDiffRegistryEdge",
"ofType": null
}
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "nodes",
"description": "A list of nodes.",
"args": [
],
"type": {
"kind": "LIST",
"name": null,
"ofType": {
"kind": "OBJECT",
"name": "MergeRequestDiffRegistry",
"ofType": null
}
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "pageInfo",
"description": "Information to aid in pagination.",
"args": [
],
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "OBJECT",
"name": "PageInfo",
"ofType": null
}
},
"isDeprecated": false,
"deprecationReason": null
}
],
"inputFields": null,
"interfaces": [
],
"enumValues": null,
"possibleTypes": null
},
{
"kind": "OBJECT",
"name": "MergeRequestDiffRegistryEdge",
"description": "An edge in a connection.",
"fields": [
{
"name": "cursor",
"description": "A cursor for use in pagination.",
"args": [
],
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "String",
"ofType": null
}
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "node",
"description": "The item at the end of the edge.",
"args": [
],
"type": {
"kind": "OBJECT",
"name": "MergeRequestDiffRegistry",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
}
],
"inputFields": null,
"interfaces": [
],
"enumValues": null,
"possibleTypes": null
},
{
"kind": "OBJECT",
"name": "MergeRequestEdge",
......@@ -35784,7 +36100,7 @@
{
"kind": "OBJECT",
"name": "PackageFileRegistry",
"description": "Represents the sync and verification state of a package file",
"description": "Represents the Geo sync and verification state of a package file",
"fields": [
{
"name": "createdAt",
......@@ -51004,7 +51320,7 @@
{
"kind": "OBJECT",
"name": "TerraformStateRegistry",
"description": "Represents the sync and verification state of a terraform state",
"description": "Represents the Geo sync and verification state of a terraform state",
"fields": [
{
"name": "createdAt",
......@@ -1548,6 +1548,21 @@ Autogenerated return type of MergeRequestCreate.
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
| `mergeRequest` | MergeRequest | The merge request after mutation |
### MergeRequestDiffRegistry
Represents the Geo sync and verification state of a Merge Request diff.
| Field | Type | Description |
| ----- | ---- | ----------- |
| `createdAt` | Time | Timestamp when the MergeRequestDiffRegistry was created |
| `id` | ID! | ID of the MergeRequestDiffRegistry |
| `lastSyncFailure` | String | Error message during sync of the MergeRequestDiffRegistry |
| `lastSyncedAt` | Time | Timestamp of the most recent successful sync of the MergeRequestDiffRegistry |
| `mergeRequestDiffId` | ID! | ID of the Merge Request diff |
| `retryAt` | Time | Timestamp after which the MergeRequestDiffRegistry should be resynced |
| `retryCount` | Int | Number of consecutive failed sync attempts of the MergeRequestDiffRegistry |
| `state` | RegistryState | Sync state of the MergeRequestDiffRegistry |
### MergeRequestPermissions
Check permissions for the current user on a merge request.
......@@ -1764,7 +1779,7 @@ Represents a package.
### PackageFileRegistry
Represents the sync and verification state of a package file.
Represents the Geo sync and verification state of a package file.
| Field | Type | Description |
| ----- | ---- | ----------- |
......@@ -2457,7 +2472,7 @@ Completion status of tasks.
### TerraformStateRegistry
Represents the sync and verification state of a terraform state.
Represents the Geo sync and verification state of a terraform state.
| Field | Type | Description |
| ----- | ---- | ----------- |
......
......@@ -633,7 +633,7 @@ the Admin Area UI, and Prometheus!
include ::Types::Geo::RegistryType
graphql_name 'WidgetRegistry'
description 'Represents the sync and verification state of a widget'
description 'Represents the Geo sync and verification state of a widget'
field :widget_id, GraphQL::ID_TYPE, null: false, description: 'ID of the Widget'
end
......@@ -672,6 +672,12 @@ the Admin Area UI, and Prometheus!
}
```
1. Update the GraphQL reference documentation:
```shell
bundle exec rake gitlab:graphql:compile_docs
```
Individual widget synchronization and verification data should now be available
via the GraphQL API!
......
# frozen_string_literal: true
module Geo
class MergeRequestDiffRegistryFinder
include FrameworkRegistryFinder
end
end
# frozen_string_literal: true
module Resolvers
module Geo
class MergeRequestDiffRegistriesResolver < BaseResolver
include RegistriesResolver
end
end
end
......@@ -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 :merge_request_diff_registries, ::Types::Geo::MergeRequestDiffRegistryType.connection_type,
null: true,
resolver: ::Resolvers::Geo::MergeRequestDiffRegistriesResolver,
description: 'Find merge request diff registries on this Geo node',
feature_flag: :geo_merge_request_diff_replication
field :package_file_registries, ::Types::Geo::PackageFileRegistryType.connection_type,
null: true,
resolver: ::Resolvers::Geo::PackageFileRegistriesResolver,
......
# frozen_string_literal: true
module Types
module Geo
# rubocop:disable Graphql/AuthorizeTypes because it is included
class MergeRequestDiffRegistryType < BaseObject
include ::Types::Geo::RegistryType
graphql_name 'MergeRequestDiffRegistry'
description 'Represents the Geo sync and verification state of a Merge Request diff'
field :merge_request_diff_id, GraphQL::ID_TYPE, null: false, description: 'ID of the Merge Request diff'
end
end
end
......@@ -7,7 +7,7 @@ module Types
include ::Types::Geo::RegistryType
graphql_name 'PackageFileRegistry'
description 'Represents the sync and verification state of a package file'
description 'Represents the Geo sync and verification state of a package file'
field :package_file_id, GraphQL::ID_TYPE, null: false, description: 'ID of the PackageFile'
end
......
......@@ -7,7 +7,7 @@ module Types
include ::Types::Geo::RegistryType
graphql_name 'TerraformStateRegistry'
description 'Represents the sync and verification state of a terraform state'
description 'Represents the Geo sync and verification state of a terraform state'
field :terraform_state_id, GraphQL::ID_TYPE, null: false, description: 'ID of the TerraformState'
end
......
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Geo::MergeRequestDiffRegistryFinder do
it_behaves_like 'a framework registry finder', :geo_merge_request_diff_registry
end
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Resolvers::Geo::MergeRequestDiffRegistriesResolver do
it_behaves_like 'a Geo registries resolver', :geo_merge_request_diff_registry
end
......@@ -11,7 +11,8 @@ RSpec.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 package_file_registries
minimum_reverification_interval merge_request_diff_registries
package_file_registries
terraform_state_registries terraform_state_version_registries
]
......
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe GitlabSchema.types['MergeRequestDiffRegistry'] do
it_behaves_like 'a Geo registry type'
it 'has the expected fields (other than those included in RegistryType)' do
expected_fields = %i[merge_request_diff_id]
expect(described_class).to have_graphql_fields(*expected_fields).at_least
end
end
......@@ -3,9 +3,7 @@
require 'spec_helper'
RSpec.describe Geo::MergeRequestDiffRegistry, :geo, type: :model do
let_it_be(:merge_request) { create(:merge_request) }
let_it_be(:merge_request_diff) { create(:merge_request_diff, merge_request: merge_request) }
let_it_be(:registry) { create(:geo_merge_request_diff_registry, merge_request_diff: merge_request_diff) }
let_it_be(:registry) { create(:geo_merge_request_diff_registry) }
specify 'factory is valid' do
expect(registry).to be_valid
......
......@@ -3,6 +3,13 @@
require 'spec_helper'
RSpec.describe 'Gets registries' do
it_behaves_like 'gets registries for', {
field_name: 'mergeRequestDiffRegistries',
registry_class_name: 'MergeRequestDiffRegistry',
registry_factory: :geo_merge_request_diff_registry,
registry_foreign_key_field_name: 'mergeRequestDiffId'
}
it_behaves_like 'gets registries for', {
field_name: 'packageFileRegistries',
registry_class_name: 'PackageFileRegistry',
......
......@@ -2,13 +2,7 @@
FactoryBot.define do
factory :merge_request_diff do
merge_request do
build(:merge_request) do |merge_request|
# MergeRequest should not create a MergeRequestDiff in the callback
allow(merge_request).to receive(:ensure_merge_request_diff)
end
end
association :merge_request, factory: :merge_request_without_merge_request_diff
state { :collected }
commits_count { 1 }
......
......@@ -286,5 +286,13 @@ FactoryBot.define do
merge_request.update!(labels: evaluator.labels)
end
end
factory :merge_request_without_merge_request_diff, class: 'MergeRequestWithoutMergeRequestDiff'
end
end
class MergeRequestWithoutMergeRequestDiff < ::MergeRequest
self.inheritance_column = :_type_disabled
def ensure_merge_request_diff; 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