Show Maven local upstreams in the registry upstream list

What does this MR do and why?

Related to #611501. The frontend is in !261005, stacked on this MR, for 19.6.

A Maven virtual registry upstream row points at either a remote or a local upstream, but GraphQL only exposes the remote one, through the non-null upstream field. When a registry has a local upstream, upstream is null on that row, the whole registry resolves to null, and the UI shows "No upstreams yet".

This MR adds:

  • targetUpstream on MavenRegistryUpstreamWithUpstream. It returns the MavenTargetUpstream union (MavenUpstream or MavenLocalUpstream): the remote upstream if set, otherwise the local one, like resolved_upstream and the REST API.
  • MavenLocalUpstream. Its localGroup and localProject fields expose only id, fullPath and webUrl, and are null when the viewer can't read the target.

upstream is unchanged: non-null, remote only.

Why the frontend is separate:

@gl_introduced handles the missing targetUpstream field, but the old backend also lacks MavenLocalUpstream, so the inline fragment crashes query analysis instead of falling back to null.

Executing a tagged missing field containing ... on NoSuchType { id } raises:

NoMethodError: undefined method graphql_name' for nil graphql/analysis/field_usage.rb:15:in on_leave_field'

Follow-up: remove upstream once the frontend reads targetUpstream, as agreed in !253638 (comment 3975662077).

Performance

targetUpstream and the local target fields are batch loaded. The N+1 spec allows one extra query per added local row, for the read_group/read_project check. A registry has at most 20 upstreams.

How to set up and validate locally

  1. In a top-level group, create a Maven virtual registry with a remote upstream, then attach a local upstream that targets a group or project.

  2. In GraphiQL (/-/graphql-explorer), run (replace <id>):

    {
      virtualRegistriesPackagesMavenRegistry(id: "gid://gitlab/VirtualRegistries::Packages::Maven::Registry/<id>") {
        registryUpstreams {
          position
          targetUpstream {
            __typename
            ... on MavenUpstream { name url }
            ... on MavenLocalUpstream { name localGroup { fullPath } localProject { fullPath } }
          }
        }
      }
    }
  3. All rows return in position order: remote rows as MavenUpstream, local rows as MavenLocalUpstream with their target path.

  4. On master, targetUpstream doesn't exist. Querying upstream instead returns registry: null with "Cannot return null for non-nullable field MavenRegistryUpstreamWithUpstream.upstream". upstream behaves the same on this branch.

Recordings

Before: on master, the registry query returns registry: null with the non-null error

After: targetUpstream returns remote and local upstreams in position order

G1_RECORDING_PLACEHOLDER

Viewer who can't read the local targets: local upstreams return with their targets null and no errors

Edited by Fiona McCawley

Merge request reports

Loading
Loading