Chapter 24Lesson 05~355 minutes

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.

CheckpointCommit→ReleaseIdentityIdempotenceRollbackCleanup

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.
Availability baseline (verified 2026-08-22 against current GitLab 19.3 documentation). Project Releases, Releases API, release asset links, automatic release-evidence snapshots, changelog generation, protected tags, and the GitLab CLI release/changelog commands have Free-compatible paths on GitLab.com, Self-Managed, and Dedicated. Creating or updating a Release requires at least Developer access, but a protected tag can impose a stricter tag-creation/deletion boundary. Current 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 delete cleanup, 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-cli is 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.invalid and 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?

Why does the checkpoint delete the Release before the tag?

What should rollback consume?

A tag protection rule prevents cleanup. What is the correct response?

What is the role of the deployment fixture?

What does Chapter 25 add next?

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:

Next chapter

Chapter 25 — SAST, Secret Detection, Dependency Scanning, Container Scanning, DAST, and Coverage-Guided Security

Apply GitLab security scanners and security evidence to the exact source, dependency, container, and running-application identities that enter the release path.

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.

Ethereum / ERC-20
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0Send only Ethereum/ERC-20 compatible assets to this address.