Add artifact registry GraphQL resolver foundation
What does this MR do and why?
Lands the monolith/S03 GraphQL foundation for the Artifact Registry in a single MR, on the ee/lib client track. Per ADR-014, the monolith owns the GraphQL layer that fronts the Artifact Registry REST API. This MR ships the reusable resolver behaviors every AR slice composes, and no concrete type, query, mutation, or field:
ArtifactRegistry::RendersErrors(ee/app/graphql/resolvers/concerns/artifact_registry/renders_errors.rb): maps the client's typed exceptions to GraphQL outcomes per the spec's Error cases table, including the query-vs-mutation split andrequest_idpreservation. The fail-closed no-credential case (anAuthorizationErrorcarrying no HTTP status) renders service-unavailable and is reported to error tracking, since a wiring misconfiguration must not disappear into an existence-hiding null.Gitlab::Graphql::Errors::ArtifactRegistry::ServiceUnavailable(ee/lib/gitlab/graphql/errors/artifact_registry.rb): the distinct service-unavailable error, machine-distinguishable from an authorization null.Resolvers::ArtifactRegistry::BaseResolver(ee/app/graphql/resolvers/artifact_registry/base_resolver.rb): gates on theartifact_registry_uiflag (a flag-off query resolves null with no client call), composes the error concern, and obtains the client through the loaded resource.ArtifactRegistry::CachesClient(ee/app/models/concerns/artifact_registry/caches_client.rb): memoizes one client per principal on the loaded resource, so a multi-field query builds the client once per request (theContainerRepository#registrypattern).ArtifactRegistry::PaginatesLists(ee/app/graphql/resolvers/concerns/artifact_registry/paginates_lists.rb): keyset connection adapter built onGitlab::Graphql::ExternallyPaginatedArray, with the outboundlimitclamped to the field's effectivemax_page_size(the connection machinery only caps returned nodes, not the limit sent to the service).
All four live under the ArtifactRegistry namespace, which config/bounded_contexts.yml registers.
Compared with the gem-track PoC, the ee/lib client wires its own monolith inputs (base URL, correlation ID, error tracking, credential exchange), so the client-acquisition concern reduces to a memoized construction bound to current_user and no configuration changes are needed (the Gitlab.config.artifact_registry stanza and the feature flag already landed with the client MRs).
Everything is dark behind the default-off artifact_registry_ui flag; no changelog per the changelog guidelines.
User-facing strings
The error concern adds one msgid, ArtifactRegistry|Artifact Registry returned an error., for the case the service does not describe itself (an ApiError message comes from the service's error envelope, so it needs no translation). Its casing follows the ArtifactRegistry| strings already shipped around it, such as ArtifactRegistry|The Artifact Registry service is unavailable..
The documentation word list asks for lowercase when writing about the container registry and carries no artifact registry entry yet, so the lowercase form is arguably the correct one. Lowercasing this single msgid would split the casing inside one file, so the eight affected ArtifactRegistry| msgids, their Ruby and Vue call sites, and a word list entry are left to a follow-up MR.
Target branch and rebase
The client MRs !244245 (merged) (client step 1) and !245331 (merged) (client steps 2+3) have merged, so this MR targets master directly. The branch is rebased onto master: the stacked client commits are dropped in favor of the merged versions, and the diff now carries only the GraphQL foundation.
References
- Issue: #607608 (closed)
- Epic: gitlab-org#22452
- Spec: https://gitlab.com/gitlab-org/ops/artifact-registry/-/blob/main/docs/specs/monolith/S03-graphql-foundation.md
- Plan: https://gitlab.com/gitlab-org/ops/artifact-registry/-/blob/main/docs/plans/monolith/2026-07-07-graphql-foundation.md
- PoC this is adapted from (gem track): !247833 (closed)
How to set up and validate locally
The slice ships no schema surface. Behavior is verified through the isolation specs:
bin/rspec ee/spec/graphql/resolvers/concerns/artifact_registry/renders_errors_spec.rb \
ee/spec/graphql/resolvers/artifact_registry/base_resolver_spec.rb \
ee/spec/models/concerns/artifact_registry/caches_client_spec.rb \
ee/spec/graphql/resolvers/concerns/artifact_registry/paginates_lists_spec.rbMR acceptance checklist
Evaluate this MR against the MR acceptance checklist.