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.manifestTypetakes 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 inutils_spec.jsrather than in a component test. - Media types come from Artifact Registry's implementation, not its contract.
api/openapi/v1.yamltypesmedia_typeas a bare 255-character string with noenumand noexample.internal/format/oci/mediatype.goaccepts exactly four, and itsisIndexTypepredicate splits index from image on the OCI image index and the Docker manifest list — the same stringslib/container_registry/base_client.rbalready lists here. Because the contract still permits any string, an unrecognized media type falls back toImagerather 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.vueuses the sameGlTruncatepattern in aGlTablecell. - The seed builds its manifest ladder in two passes, subjects first and then referrers, so every
seeded
subject_digestnames 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.
Imagereuses the msgid the repository detail table already has, and the column header reusesArtifactRegistry|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
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
- Enable the flag:
Feature.enable(:artifact_registry_ui). - Visit
/o/<organization>/-/artifact_registry/acme/repositories. - Open
payment-service(Docker), thenoci-artifacts(OCI), and click an artifact name in each. - Confirm every row's Type reads correctly, and that each
for <digest>suffix matches the Digest cell of another row in the same table. - Hover the unrecognized referrer's type and confirm the tooltip carries the full artifact type, and that the column does not stretch.
- Open
payment-core(Maven) andui-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.
