Add a Type column to the container manifest table

What does this MR do and why?

Note

Targets !250140 (merged), which in turn targets !250074 (merged). Both merge first. The whole stack was rebased onto master after !249937 (merged) merged.

This change is behind the feature flag :artifact_registry_ui

The container manifest table listed Digest, Size, and Published, which left an index, a platform image, and a cosign signature as three indistinguishable rows of hex. This adds the Type column between Digest and Size, where the design proposal puts it, rendered from three contract fields the previous step deliberately left undeclared: media_type, artifact_type, and subject_digest.

Rendered When
Index no subject, and the media type is an OCI image index or a Docker manifest list
Image no subject, any other media type
Signature for <digest> subject present, a recognized cosign signature type
SBOM attestation for <digest> subject present, a recognized SBOM type
SLSA attestation for <digest> subject present, a recognized in-toto provenance type
<raw artifactType> for <digest> subject present, artifact type unrecognized
Referrer for <digest> subject present, no artifact type at all

subject_digest is checked first because the contract makes it the referrer discriminator: it holds the digest of the manifest a given manifest attaches to and is null on everything else. Media type only ever decides index versus image.

Changes

  • The classifier is pure and lives in utils.js. manifestType takes a manifest and returns the kind, the shortened subject digest, and the raw artifact type when it recognizes none — no Vue, so the branch coverage sits in utils_spec.js rather than in a component test.
  • Media types come from Artifact Registry's implementation, not its contract. api/openapi/v1.yaml types media_type as a bare 255-character string with no enum and no example. internal/format/oci/mediatype.go accepts exactly four, and its isIndexType predicate splits index from image on the OCI image index and the Docker manifest list — the same strings lib/container_registry/base_client.rb already lists here. Because the contract still permits any string, an unrecognized media type falls back to Image rather than rendering blank.
  • Artifact types are public convention, not a transcribed list — the weakest part of this MR. Artifact Registry enumerates none. The monolith had exactly one, an inline literal in the container registry's tags_list_row.vue, and it is a different cosign string from the one Artifact Registry's own tests use, so both are matched. The SBOM and SLSA sets come from the public cosign and in-toto conventions. This is why an unrecognized type renders its raw value: the recognized set can be wrong or incomplete without the column ever lying.
  • Two departures from the design proposal. The subject digest renders as text rather than a link to the subject manifest, because that target is version detail, which this slice does not own — the same call the Digest column already made. And an unrecognized referrer renders its raw artifact type rather than "Generic referrer", because two different novel types would otherwise read identically.
  • The raw type is middle-truncated with a tooltip and a max width. Without the width bound it stretched the column and pushed Size and Published across the row. The tests could not see that; the browser could. virtual_registries/.../upstreams/table.vue uses the same GlTruncate pattern in a GlTable cell.
  • The seed builds its manifest ladder in two passes, subjects first and then referrers, so every seeded subject_digest names a digest another manifest of the same image actually carries. A spec asserts that invariant, because a broken subject renders a plausible label pointing at nothing.
  • i18n uses whole phrases. One full message per known kind rather than a translatable noun dropped into a shared frame, so translators see the complete sentence. Image reuses the msgid the repository detail table already has, and the column header reuses ArtifactRegistry|Type.

Duplicating the two index media types here rather than importing the container registry's own keeps the artifact registry from depending on another feature's internal constants. Hoisting them to packages_and_registries/shared/ is worth a follow-up.

Screenshots or screen recordings

s18-type-referrer

Row six is the unrecognized artifact type, middle-truncated with its full value in a tooltip. Row seven is a referrer that carries no artifact type at all.

How to set up and validate locally

  1. Enable the flag: Feature.enable(:artifact_registry_ui).
  2. Visit /o/<organization>/-/artifact_registry/acme/repositories.
  3. Open payment-service (Docker), then oci-artifacts (OCI), and click an artifact name in each.
  4. Confirm every row's Type reads correctly, and that each for <digest> suffix matches the Digest cell of another row in the same table.
  5. Hover the unrecognized referrer's type and confirm the tooltip carries the full artifact type, and that the column does not stretch.
  6. Open payment-core (Maven) and ui-components (npm) and confirm the versions table is unchanged, still Version and Published.

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 Zack Cuddy

Merge request reports

Loading
Loading