Parameterize the container install snippet builders
What does this MR do and why?
The Docker and OCI manifest detail page arriving with monolith/S06 Phase 2 renders a pull command for one manifest, naming a real image and either its tag or its digest. The container snippet builder is bound to the module placeholders instead: it composes image:tag against the repository URL and takes no image, tag or digest at all.
This parameterizes containerSections the way Step 14a parameterized the Maven and npm builders before the Phase 1 Overview tab consumed them. Nothing renders the new output yet — the Overview tab that consumes it is a later step, and the repository setup drawer is unchanged.
This is Step 0a of monolith/S06 Phase 2. The slice is prep/monolith-S06-phase2.md; the manifest-read contract it builds toward merged as ops/artifact-registry!2317.
Three things worth a reviewer's attention
The digest guard is deliberately separate from SAFE_COORDINATE. That charset is /^[A-Za-z0-9._~@/+-]+$/ — no colon — so sha256:… fails isSafe and the builder silently returns []. Adding a colon to it would have been the small fix and the wrong one: the charset guards Maven and npm coordinates, where a colon is a separator and never part of a value. CANONICAL_DIGEST sits beside it and applies only to the new reference.
tag takes no default in the destructure, and defaults only on the drawer path. A default in the signature would have an untagged manifest pull the literal image:tag. The prototype's single-platform child is exactly that case — untagged, pull-by-digest only. There is a one-line comment on this, because it is the edit a reader would plausibly "tidy up".
A caller naming a digest gets two blocks, not one. The design renders pull-by-tag and pull-by-digest as separate panels. A caller naming no digest — the setup drawer — keeps today's single block, which is what makes the change behaviour-preserving.
Screenshots or screen recordings
This MR renders no new output, so there is no "after" to show. What it must not change is the repository setup drawer, which is the only surface calling the builder today — captured here on master:
docker pull localhost:8080/acme/container/docker-images/image:tag — the image:tag placeholder this MR keeps as the default. snippets_spec.js, setup_snippets_spec.js and artifacts_empty_state_spec.js are what prove it byte-identical; the screenshot is the surface those specs stand in for.
How to set up and validate locally
This step changes no rendered output. The proof is in the specs:
yarn jest ee/spec/frontend/packages_and_registries/artifact_registry/repositories/detail/setup_instructions/ ee/spec/frontend/packages_and_registries/artifact_registry/repositories/detail/artifacts_empty_state_spec.jssetup_snippets_spec.jsandartifacts_empty_state_spec.jsare the behaviour-preservation witnesses — they render the container snippets through the untouched call sites.snippets_spec.jscovers the new arguments: the by-tag/by-digest pair, the untagged case, the podman client, and every malformed digest the guard refuses.
Both Vue versions pass (254 tests each).
MR acceptance checklist
Evaluate this MR against the MR acceptance checklist.
