| name | release-artifacts |
| version | 1.0 |
| last_updated | 2026-08-07T00:00:00.000Z |
| id | release-artifacts |
| one_line_purpose | Prepare, verify, and troubleshoot image release and promotion. |
| entry_point | docs/skills/release-artifacts/SKILL.md |
| category | ci-ops |
| mcp_compliance_level | partial |
| optimization_status | draft |
| status | active |
| dependencies | [] |
| tags | ["release","promotion","signing","verification"] |
| description | Covers the release and testing-to-main promotion workflows, digest and tag verification, and signing gates. Use when running a release or diagnosing a failed promotion. |
| metadata | {"type":"runbook","source-of-truth":[".github/workflows/execute-release.yml",".github/workflows/promote-testing-to-main.yml","docs/release.md"]} |
Release artifacts
Procedure
- Read the affected release workflow and reusable workflow inputs.
- Verify the exact image digest, tag, artifact name, and trigger.
- Confirm signing and end-to-end gates completed.
- Never bypass a failed trust or verification gate.
- Report the run ID and exact verification commands.
gh run list --repo projectbluefin/bluefin --limit 20
gh run view RUN_ID --repo projectbluefin/bluefin --log-failed
gh run watch RUN_ID --repo projectbluefin/bluefin --exit-status
Verify a stream tag against its gate
A stream tag (:testing, :stable) is a claim that a digest passed its gate.
Verify the claim rather than trusting the tag: resolve what the tag points at,
then confirm that digest actually passed.
skopeo inspect docker://ghcr.io/projectbluefin/bluefin:testing --format '{{.Digest}}'
gh run list --repo projectbluefin/bluefin --workflow post-testing-e2e.yml --limit 20
Without skopeo, the GHCR package API resolves the same mapping and also shows
which tags share one package version — co-located version and stream tags mean
the build pushed the stream tag, not a promotion:
gh api "/orgs/projectbluefin/packages/container/bluefin/versions?per_page=100" \
--jq '.[] | select(.metadata.container.tags | index("testing"))
| [.name, .created_at, (.metadata.container.tags | join(","))] | @tsv'
Then confirm the gate actually passed for that digest: a post-testing-e2e run
whose promote-to-testing job is skipped did not promote, whatever the
tag now points at. See
ci failure modes for reading those runs.
A promotion job reported as skipped while the stream tag still advanced means
something outside the gate is publishing it. Build-time tag computation is the
usual source: the bare stream tag can sit in the tag list that the push step
consumes, so excluding it from a conditional does not remove it from the push.
Filter the stream tag out of the list itself.
Never re-point or delete a published stream tag to "repair" this — that is
user-visible and belongs to a human.
Release consumes :testing as its : the release job resolves the
digest behind that tag rather than re-running end-to-end validation. The
gate is therefore the primary producer-side gate, and a
failure there must stop from advancing. The current
caller also sets , so the
reusable release gate re-tests the exact resolved digest before promoting it to
. When auditing an older promotion, inspect that run's job list to
confirm the release gate existed at the time; do not assume a current workflow
definition applied retroactively. A gate step that reports must never
be accepted as a pass — treat only an explicit success as validation.