Gate the Artifact registry detail header, connection test, and kebab

What does this MR do and why?

This MR delivers step 9 and step 10 of the plan in #628427 (closed): the detail page header and connection test control, and the detail page kebab menu.

The repository detail page joins the edit route as the second consumer of the userPermissions block, added in Step 3 and first wired up in Step 6. The detail query, get_repository_detail.query.graphql, now selects userPermissions inline for updateRepository, deleteRepository, and deleteArtifact, rather than through a fragment. So this step does not depend on any of the list-view steps.

Two controls gate on updateRepository: the Edit button in the page header, and the Test control in the sidebar's connection section. Two more gate in the kebab menu: the Delete repository item and the Clear cache item. Each item renders only when the block gives an explicit true for its matching permission. Copy repository URL stays ungated. It only depends on whether the instance has a client base URL configured, not on a permission verdict. A denied control or item is removed, not disabled. A disabled control would confirm the operation exists, per ADR-021 existence hiding.

When neither gated kebab item applies and no client base URL is set, the kebab now renders no toggle at all. An icon-only toggle that opens on an empty list would be a focusable control with nothing behind it. Removing the toggle avoids a dead end for keyboard and screen reader users.

The detail page passes the userPermissions block to the header, the sidebar, and the kebab menu as a prop. All three read the same block. The prop is undefined while the query loads, and holds the resolved block once loading stops. Every gated component reads its verdict only through the shared permissionAllows helper with the matching permission constant. So nothing renders on an unresolved block, or on anything short of an explicit true.

The detail query already used the cache-and-network fetch policy. Under that policy, a primed cache serves the cached page immediately while the network read is still in flight. Passing undefined until loading stops means the cached page renders at once, but the gated controls wait for the network answer. This matters because a verdict is per user, and the browser cannot tell a false verdict from a permissions object the server never sent. A control must never render from the cache alone.

The verdict stays advisory. Artifact Registry authorizes every request itself, so the gate only stops the UI from offering a control the user cannot use. The kebab component keeps dispatching the clear cache and delete mutations even when the verdict says allow and the backend then denies, and the existing error alert still shows. Specs pin this behavior for both actions.

Specs cover the Edit and Test controls being absent on a denied updateRepository and present when allowed, nothing gated rendering before the read resolves, and a cache-primed second mount that still issues a network request, hides Edit until it answers, and shows it once the answer allows. Jest specs also cover each kebab item's presence and absence across the denial combinations, the loading state before the block resolves, and the header passing the block through. Every gated component's spec confirms it calls permissionAllows with the declared constant.

A feature spec adds one accessibility example, on the detail page, confirming the gated controls disappear and the page stays axe clean when every verdict is denied. The matching list-page example is left out here. It depends on the list gating done in Steps 7 and 8, which are not on this branch. It belongs with step 8.

The feature spec at ee/spec/features/artifact_registry/repositories_spec.rb had stubs of the client's repository read that expected include_permissions: false. Because the detail query now selects userPermissions, the detail page's read passes include_permissions: true, while the packages read on the same page still passes false. The stubs now accept both, where both reads happen, and the resolved-repository example returns a repository carrying an allow-all permissions object on the permissions-carrying read.

The frontend fixture for the detail read now stubs Artifact Registry with a permissions object covering all nine repository actions, and expects include_permissions=true on the request. Existing specs and the Storybook story that mock the detail read now carry userPermissions, since Apollo warns on a missing selected field.

The frontend fixture spec at ee/spec/frontend/fixtures/artifact_registry/repository.rb already runs the real query and checks the full response field by field. The field list test in the Jest queries spec checked the same thing again, so it is dropped rather than extended.

Everything stays behind the default-off artifact_registry_ui feature flag, so there is no changelog entry.

References

Screenshots or screen recordings

Screenshots of the gated state are not available yet. The dev rig's Artifact Registry answers 503 to permission reads. See the rig blocker: gitlab-org/ops/artifact-registry#1297 (closed). The feature spec and the Jest specs in this MR cover the behavior.

How to set up and validate locally

  1. In a Rails console, enable the feature flag:
    Feature.enable(:artifact_registry_ui, organization)
  2. Regenerate the frontend fixture this MR changes:
    bin/rspec ee/spec/frontend/fixtures/artifact_registry/repository.rb
  3. Run the RSpec feature spec:
    bin/rspec ee/spec/features/artifact_registry/repositories_spec.rb
  4. Run the Jest specs this MR adds or changes:
    yarn jest ee/spec/frontend/packages_and_registries/artifact_registry/graphql/mock_resolvers_spec.js
    yarn jest ee/spec/frontend/packages_and_registries/artifact_registry/graphql/queries_spec.js
    yarn jest ee/spec/frontend/packages_and_registries/artifact_registry/repositories/detail/artifacts_table_spec.js
    yarn jest ee/spec/frontend/packages_and_registries/artifact_registry/repositories/detail/connection_section_spec.js
    yarn jest ee/spec/frontend/packages_and_registries/artifact_registry/repositories/detail/repository_actions_spec.js
    yarn jest ee/spec/frontend/packages_and_registries/artifact_registry/repositories/detail/repository_detail_spec.js
    yarn jest ee/spec/frontend/packages_and_registries/artifact_registry/repositories/detail/repository_sidebar_spec.js
  5. Open the organization's Artifact Registry pages. The gated control needs an Artifact Registry deployment that answers permissions.

MR acceptance checklist

Evaluate this MR against the MR acceptance checklist. It helps you analyze changes to reduce risks in quality, performance, reliability, security, and maintainability.

Edited by Rahul Chanila

Merge request reports

Loading
Loading