Add the artifact registry repositories table

What does this MR do and why?

The artifact registry repositories list rendered a heading and an empty state. It now renders the organization's repositories.

The table carries six columns: format with its ecosystem logo, name with a visibility affordance, type as a badge, downloads, size, and last updated. Counters reach the browser as strings through the BigInt scalar and default to zero, because a repository nothing has been published to yet carries neither. A repository whose content has never changed reads "Never" rather than leaving the cell blank.

The page derives its remaining states from the query: loading, populated, error, and not found. A failed query renders the service-unavailable alert with the heading intact, while a null connection renders the not-found component alone, so the view never confirms that an organization the viewer cannot see exists. The keyset pager holds its cursor in the route query, so a page survives a reload and can be shared.

An aria-live region announces the rendered result state. It enters the DOM with the page rather than with the first result, because a region that appears at the same moment as its content is not reliably announced. The shell's focus watcher narrows to the route path, so the cursor updates this change introduces no longer steal focus back to the shell and interrupt that announcement.

Visibility renders as private only. ADR-021 descopes both public and internal from the closed beta, because each grants read without a role assignment and so breaks closed-by-default. The read enum still decodes every value the registry can return.

Still client-side

The connection is resolved by the local Apollo resolvers in graphql/mock_resolvers.js; the GraphQL backend for it has not landed yet. The query document keeps its @client directive, so graphql-verify skips it. A later step removes the directive and binds the document to the schema.

References

  • Plan: docs/plans/monolith/2026-07-28-repositories-list.md, Step 4 (Repositories table)
  • The Type column and the stacked-layout alignment follow the Google Artifact Registry list table, ee/app/assets/javascripts/packages_and_registries/google_artifact_registry/components/list/table.vue
  • The visibility affordance follows app/assets/javascripts/vue_shared/components/visibility_icon_button.vue, which uses a focusable button so the tooltip opens on keyboard focus and not hover alone

Screenshots or screen recordings

State Result
Loading Header row with all six columns, aria-busy="true", live region reads "Loading repositories."
Empty "No repositories" / "This organization has no repositories yet."
Populated All six columns across Docker, Maven, npm, and OCI repositories
Error Non-dismissible service-unavailable alert, heading retained, no table
Not found Not-found component alone, no heading
Before After
Screenshot_2026-07-31_at_12.03.58_am Screenshot_2026-07-31_at_11.04.54_pm

How to set up and validate locally

  1. Enable the feature flag for your organization:

    Feature.enable(:artifact_registry_ui, Organizations::Organization.first)
  2. Seed the client-side store so the list renders rows, either by creating a repository through the UI's own create form, or by adding entries to mockRepositories in ee/app/assets/javascripts/packages_and_registries/artifact_registry/graphql/mock_resolvers.js.

  3. Visit /o/<organization>/-/artifact_registry/acme/repositories.

  4. Narrow the viewport below md to check the stacked layout.

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.

Related to #602638 (closed)

Edited by Rahul Chanila

Merge request reports

Loading
Loading