Checkpoint Lab — Releases, Tags, Release CLI, Evidence, Changelogs, and Deployment Traceability
Build and independently verify one disposable release chain from commit to tag to Release object to durable artifact/image reference, prove rerun behavior, document rollback consequences, and clean up in the right order.
Learning objectives
- Predict the complete commit/tag/Release relationship before mutation.
- Create or simulate a durable asset/package/image link and verify immutable identity.
- Demonstrate an idempotent rerun decision path without duplicate releases.
- Document rollback and deletion consequences before cleanup.
- Remove Release/tag/lab state in the safe order and independently verify absence.
glab release delete documentation requires
Maintainer-or-higher, so the fully scripted glab cleanup path is
Maintainer-scoped; Developer-level learners can use the documented
UI/Releases API path where permitted or simulate cleanup. On-demand
evidence recollection is Premium/Ultimate and limited to
Self-Managed/Dedicated; retaining report artifacts as release evidence
is Ultimate. release-cli was deprecated in GitLab 18.0
and is scheduled for removal in 20.0; use glab or the
Releases API for new automation. The mandatory labs use only a
disposable project/tag, synthetic asset links or package/image
coordinates, and no paid feature.
1. Checkpoint mission
Create one complete disposable release chain and prove every important identity independently:
commit SHA → Git tag → GitLab Release → durable/synthetic artifact identity → release evidence → deployment reference fixture
No real production deploy is required. A synthetic package/image reference is acceptable if you clearly label it; a real disposable Generic Package or OCI digest is even better. The objective is reasoning and evidence, not cloud spend.
2. Preflight assumptions
- GitLab 19.3-compatible instance; Free path is sufficient.
-
Developer-or-higher project role for create/update Release
operations. Use Maintainer-or-higher for the fully scripted
glab release deletecleanup, or use the documented UI/Releases API path/simulation where your role permits. - Tag pattern chosen so current protected-tag policy permits the disposable tag; do not weaken policy.
-
Git and current
glab;release-cliis not used. - No production package/image/environment, real token, or customer-facing version is touched.
3. Prediction ledger — write before execution
| State | Prediction |
|---|---|
| Commit |
RELEASE_SHA is the exact intended source.
|
| Tag |
v0.24.1-lab resolves to
RELEASE_SHA.
|
| Release | Exactly one Release exists for the tag. |
| Artifact/image | Ledger records one checksum/digest and a durable/synthetic coordinate. |
| Evidence | Automatic evidence path/SHA is associated with the Release. |
| Rerun | Second automation pass detects existing Release and performs no duplicate create. |
| Cleanup | Delete Release → verify tag remains → delete tag/branch → verify absence. |
4. Create deterministic source and notes
On a disposable branch:
git switch -c ch24/checkpoint
printf "checkpoint release identity\n" > ch24-checkpoint.txt
git add ch24-checkpoint.txt
git commit -m "Add Chapter 24 checkpoint
Changelog: added"
BASE_SHA="$(git rev-parse HEAD^)"
RELEASE_SHA="$(git rev-parse HEAD)"
TAG=v0.24.1-lab
cat > release-notes.md <<'EOF'
## Chapter 24 checkpoint
This is a disposable release. No production deployment.
EOF
printf "release_sha=%s\ntag=%s\n" "$RELEASE_SHA" "$TAG" | tee ch24-checkpoint-ledger.txt
5. Establish an artifact/package/image identity before the Release
Choose one:
- Free live option: publish one tiny Generic Package file and record its SHA-256.
- OCI option: use a disposable image from Chapter 23 and record the manifest/index digest.
-
Simulation: write a fixture coordinate under
example.invalidand a clearly labeled synthetic SHA-256.
artifact_coordinate=https://example.invalid/packages/ch24/v0.24.1-lab/checkpoint.txt
artifact_sha256=fixture:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
The Release link will be a navigation aid. The hash/digest is the content identity.
6. Create, push, and prove the tag
Use an annotated tag and verify the commit it resolves to:
git tag -a "$TAG" "$RELEASE_SHA" -m "Disposable Chapter 24 checkpoint"
git rev-list -n 1 "$TAG" | tee ch24-tag-commit.txt
test "$(cat ch24-tag-commit.txt)" = "$RELEASE_SHA"
git push -u origin ch24/checkpoint
git push origin "refs/tags/$TAG"
git ls-remote --tags origin "refs/tags/$TAG" "refs/tags/$TAG^{}"
7. Generate and review the changelog
Generate the changelog data using an explicit semantic version and commit range:
glab changelog generate --version 0.24.1 --from "$BASE_SHA" --to "$RELEASE_SHA" > checkpoint-changelog.md
cat checkpoint-changelog.md
Predict whether the checkpoint commit appears before you run the command. If it does not, diagnose the trailer/range instead of hand-editing the generated evidence.
8. First automation pass: inspect then create
Make the operation idempotent from the beginning:
if glab release view "$TAG" -F json > checkpoint-release-existing.json 2>/dev/null; then
echo "unexpected pre-existing Release; inspect and stop" >&2
exit 1
else
glab release create "$TAG" --name "Checkpoint $TAG" -F release-notes.md
fi
glab release view "$TAG" -F json > checkpoint-release.json
If using a real durable package/image, add its asset link through
glab release create options or the release-links API
only after the identity ledger is complete.
9. Verify commit/tag/Release identity
Compare independent values:
TAG_COMMIT="$(git rev-list -n 1 "$TAG")"
RELEASE_COMMIT="$(python - <<'PY2'
import json
r=json.load(open("checkpoint-release.json"))
print(r["commit"]["id"] )
PY2
)"
printf "tag_commit=%s\nrelease_commit=%s\n" "$TAG_COMMIT" "$RELEASE_COMMIT" | tee checkpoint-identity.txt
test "$TAG_COMMIT" = "$RELEASE_COMMIT"
test "$RELEASE_COMMIT" = "$RELEASE_SHA"
Also capture the Release evidence_sha and evidence file
path when present. If using a live package/image, re-query the
registry and compare the hash/digest to the ledger.
10. Create a deployment traceability fixture
No cloud is required. Record the exact intended production coordinate:
release_tag=v0.24.1-lab
source_sha=<exact RELEASE_SHA>
artifact_coordinate=<generic-package-url-or-oci-repository@digest>
artifact_hash_or_digest=<exact hash/digest>
environment=simulation/ch24
deployment_status=not-deployed-simulation
This demonstrates the handoff contract: an environment/deployment operation must consume the same immutable identity the Release ledger recorded.
11. Second automation pass: prove idempotent behavior
Rerun the release logic. This time the Release must exist. Compare identity and stop without duplicate creation:
glab release view "$TAG" -F json > checkpoint-release-rerun.json
python - <<'PY2'
import json,sys
r=json.load(open("checkpoint-release-rerun.json"))
expected=open("ch24-tag-commit.txt").read().strip()
actual=r.get("commit",{}).get("id")
print("existing release commit:", actual)
if actual != expected:
sys.exit("identity mismatch: refuse update")
print("identity matches; no duplicate create required")
PY2
If notes/assets intentionally changed, use a documented update path after this identity check. Idempotence means converging on desired state, not refusing every safe update.
12. Safe failure injection: wrong expected SHA
Change only the local expected value, not the remote release:
EXPECTED_SHA=0000000000000000000000000000000000000000
ACTUAL_SHA="$(git rev-list -n 1 "$TAG")"
if [ "$EXPECTED_SHA" != "$ACTUAL_SHA" ]; then
echo "release gate: expected SHA mismatch; no mutation performed" >&2
fi
Interpretation: release automation should fail before modifying metadata/assets when source identity is inconsistent. This is the same fail-closed principle used for registry digests and deployment gates.
13. Document rollback and deletion consequences before cleanup
Write the answers before deleting anything:
- Rollback selects the previously verified package/hash or OCI digest, not a rebuild of the old tag.
- Deleting the Release removes its Release assets/metadata but leaves the Git tag.
- Deleting the associated Git tag removes the Release too if it still exists.
- Deleting/recreating a tag can change what downstream consumers resolve; use a new version instead of rewriting history whenever possible.
- Release evidence is audit context, not proof the artifact is secure.
14. Cleanup with read-after-delete verification
Preserve final JSON/ledger/changelog first. Then deliberately demonstrate Release/tag independence:
glab release view "$TAG" -F json > checkpoint-release-final.json
# Destructive, disposable Release only:
glab release delete "$TAG" --yes # current glab docs: Maintainer-or-higher
# The tag must still exist after Release deletion:
git ls-remote --exit-code --tags origin "refs/tags/$TAG" >/dev/null
# Now remove disposable tag and branch:
git push origin ":refs/tags/$TAG"
git push origin --delete ch24/checkpoint
# Verify tag is gone:
if git ls-remote --exit-code --tags origin "refs/tags/$TAG" >/dev/null 2>&1; then
echo "tag remains after cleanup" >&2
exit 1
fi
echo "verified Chapter 24 cleanup"
If protected-tag policy applies, use the authorized GitLab UI/API deletion path or leave the tag and document why cleanup cannot proceed. Do not unprotect production tag patterns for a lab.
15. Final verification checklist
- Project/ref/source SHA were captured before mutation.
- Tag resolved to the intended commit.
- Release commit matched tag/source independently.
- Artifact/package/image coordinate had an independent checksum/digest.
- Changelog range/trailers were explicit.
- Automatic evidence metadata was captured where available.
- Rerun inspected existing state and did not create a duplicate/conflicting Release.
- Rollback uses known immutable artifact identity.
- Release deletion was shown not to delete the tag.
- Tag/branch cleanup was verified without bypassing protection.
16. What Chapter 24 adds to the production GitLab operating model
You now have a release operating contract: version tags are governed refs; GitLab Releases are discoverable metadata; durable packages/images carry immutable binary identity; changelogs structure change communication; evidence snapshots record surrounding GitLab state; deployments must consume the same immutable identity; and automation is idempotent and fail-closed on identity mismatch. Chapter 25 applies security scanners to the source and build artifacts that enter this release chain.
Knowledge check
What must match before an idempotent rerun updates an existing Release?
At minimum the existing Release/tag commit identity must match the expected source; then compare the desired mutable metadata/assets before updating.
Why does the checkpoint delete the Release before the tag?
To prove the documented semantics: deleting the Release leaves the Git tag, while tag deletion can remove an associated Release.
What should rollback consume?
The previously verified immutable package checksum or OCI digest recorded for that release, not a newly rebuilt artifact from the old tag.
A tag protection rule prevents cleanup. What is the correct response?
Leave the protected state or use the authorized UI/API path with the proper role; do not weaken governance for the lab.
What is the role of the deployment fixture?
It proves the handoff contract that deployment must consume the same source/artifact identity recorded by the Release chain.
What does Chapter 25 add next?
Security scanning evidence—SAST, secret/dependency/container/DAST and related coverage—bound to source/build identities before release promotion.
Summary
The checkpoint created and verified the full release chain, demonstrated a fail-closed/idempotent rerun, separated Release deletion from tag deletion, and documented rollback around immutable artifact identity. The resulting model is suitable for automation, audit, incident response, and deployment traceability.
Official references
Primary sources used for the current GitLab 19.3 behavior taught in this lesson:
- GitLab Docs — Releases
- GitLab Docs — Project releases API
- GitLab Docs — Release links API
- GitLab Docs — Release evidence
- GitLab Docs — Release fields and assets
- GitLab Docs — release-cli (deprecated)
- GitLab CI/CD YAML — release keyword
- GitLab CLI — release
- GitLab CLI — release create
- GitLab CLI — release view
- GitLab CLI — release list
- GitLab Docs — Changelogs
- GitLab CLI — changelog generate
- GitLab Docs — Repositories API changelog endpoints
- GitLab Docs — Protected tags
Keep the academy open
Support free, practical DevOps education.
Every lesson is designed to remain readable in a browser, downloadable from GitHub, and usable without a paid learning platform. Contributions help expand and maintain the curriculum.
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0Send only Ethereum/ERC-20 compatible assets to this
address.