Add tag badges to the manifest detail header
What does this MR do and why?
Renders one badge per tag in the manifest detail page header, between
the H1 short digest and the existing kind badge, matching where the
design prototype places them. Tag badges use the info variant and a
monospace class; the kind badge stays neutral. An untagged manifest —
pulled by digest alone, so there's no tag row to render — shows no
badges at all. tags was added to the get_manifest query selection.
Render order follows the server, not a view-side sort
The view renders tags in the order they're served and does not
re-sort or re-cap them. The merged contract serves tags name
ascending and bounds the list by container.manifest_max_tags
(1,000). Re-sorting in the view would hide a server that stopped
sorting; re-capping would duplicate a bound the server already
applies.
Seed fidelity gap closed
That decision exposed a gap in the local Apollo mock: it seeded tags
by slicing a fixed TAG_NAMES list, which isn't alphabetical, so the
seed served them unsorted. mock_artifacts.js now sorts them, and a
new assertion in mock_artifacts_spec.js pins that every ladder's
tags come back name ascending — without it, an unsorted seed would
hide a view that forgot to render in order.
One Step 1 test updated
manifest_detail_spec.js had asserted the kind badge was the first
GlBadge on the page, which is no longer true now that tag badges
precede it. It now asserts the kind badge is a badge and sits outside
the heading, which was the test's actual intent. A new test pins the
ordering — tag badges then the kind badge — since that ordering is
what the design specifies and what could silently regress.
References
- Phase plan: gitlab-org/ops/artifact-registry!2461 (merged)
- Design prototype: https://gitlab-org.gitlab.io/ci-cd/package-stage/artifact-registry-design-proposal/
- Step 1, the manifest detail page this stacks on: !253776 (merged)
- Step 2, the tab bar (sibling, targets the same branch, touches a different slot): !254794 (merged)
- Step 3, the sidebar (sibling, targets the same branch, touches a different slot): !254805 (merged)
Screenshots or screen recordings
There's no meaningful "before" — the header carried no tag badges.
Every tag fits. Five or fewer tags render inline, with no overflow affordance:
More tags than the header shows. An index carrying 11 tags renders the first five and collapses the remaining six:
The collapsed tags, opened. Activating +6 more reveals the rest in an
"All tags" popover, so no tag is dropped from the page:
The overflow shots were taken against a locally widened tag seed — the committed
seed offers at most five tag names, so the collapsed state cannot be reached on a
stock GDK. The ManyTags and LongTagName Storybook stories added in this MR
cover it without that patch.
How to set up and validate locally
The manifest detail page isn't reachable by clicking yet — the container row link on the manifests table is Step 11, held until the GraphQL integration lands. So reach it by URL.
Image ids must come from the repository's own artifact list, since they're server-resolved, while manifest digests are derived from whatever image id they're handed.
-
Enable the flags in the rails console:
Feature.enable(:artifact_registry_ui) Feature.enable(:org_stage_experimental) -
Visit the tagged index:
/o/default/-/artifact_registry/acme/repositories/docker-images/b7dad7c9-c3f8-9264-5f55-3619a3c720a4/manifests/sha256%3A5e30d0925e30d0935e30d0945e30d0955e30d0965e30d0975e30d0985e30d099 -
Visit the untagged single image:
/o/default/-/artifact_registry/acme/repositories/docker-images/b7dad7c9-c3f8-9264-5f55-3619a3c720a4/manifests/sha256%3A2bae1fbf2bae1fc02bae1fc12bae1fc22bae1fc32bae1fc42bae1fc52bae1fc6
Verification
Driven in the GDK. The tagged index renders five badges reading
latest rc1 stable trixie v1 — name ascending — followed by the grey
Index · 3 platforms kind badge. The untagged single-image child
renders zero tag badges with its Image kind badge intact. Zero
console errors on both.
Full artifact registry Jest suite on both Vue 2 and Vue 3: 2160
passing, 64 of 65 suites green. repository_detail_spec.js fails
with 55 failures; verified pre-existing by running it at the base
commit with all changes stashed and getting the identical 55
failures.
ESLint clean at --max-warnings 0, Prettier clean. No new translated
strings — tag names are raw values, so locale/gitlab.pot is
untouched.
No changelog entry — the feature is dark behind artifact_registry_ui
and unreleased.
Stacked
Rebased onto master on 2026-09-10. Step 1
(!253776 (merged)) was squash-merged, so this
branch was cut off its old tip with git rebase --onto master rather than a plain rebase —
a squash leaves no matching patch ids, so a plain rebase would have tried to replay Step 1's
commits. This MR now targets master directly and carries only its own commit.
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.


