Chapter 22Lesson 03~175 minutes

Tags, Releases, Release CLI, Changelogs, Evidence, Asset Links, and Release-Orchestration Pipelines: Configuration, Design Choices, and Tradeoffs

Choose deliberately among the release keyword, glab, the Releases API, generated or curated notes, protected tags, and immutable or mutable asset publication strategies.

DesignProtected tagsRelease APITradeoffsAuditability

Learning objectives

  • Choose among the YAML release keyword, glab, and direct API calls based on idempotency, auditability, and failure isolation.
  • Choose between pre-created/annotated tags and scripted tag creation without losing exact SHA identity.
  • Balance generated changelogs with curated release notes while keeping the commit range reproducible.
  • Design asset links around immutable/versioned storage rather than moving URLs.
  • Map protected-tag rules and token choice to least privilege and bounded recovery.

1. Design frame: release automation is a public API for your build evidence

A release pipeline is not merely a convenient last stage. It publishes a durable identity that downstream humans, systems, and later deployments may trust. Design it like an API: define required inputs (exact SHA, version, artifact digest), allowable side effects (tag/release/links), authorization, idempotency behavior, and how a caller can verify or supersede the result.

2. Current platform assumptions verified for this chapter

Capability Current assumption used in the lessons Design consequence
Releases/API Free/Premium/Ultimate; Developer+ can create/update/delete releases, subject to protected-tag permissions. Use role/tag controls as part of publication authorization.
YAML release Uses glab; current docs require glab >= 1.58.0; job still needs script. Pin/record tool identity and do not depend on deprecated release-cli.
release-cli Deprecated in GitLab 18.0, planned removal in 20.0. Migration target is glab, not new release-cli scripting.
Changelog Free; CLI path requires glab >= 1.30.0 and commit trailers. Bound from/to/version inputs.
Base release evidence Evidence snapshot is available with releases on all tiers. Treat it as metadata evidence, then add your own digest/provenance evidence.
Protected tags Role-based protection is Free; some granular user/group options have higher-tier requirements. Mandatory design does not depend on paid granular rules.

3. YAML release versus glab versus Releases API

Approach Strengths Risks / constraints Prefer when
release keyword Declarative, visible in compiled CI config, release action tied to job success. Creation fails if release already exists; depends on runner glab; less suited to complex update flows. One release should be created once from a known tag/SHA.
glab release Ergonomic create/update/view/delete commands, CI auto-login with job token. CLI defaults can create missing tag from default branch unless --ref is explicit; CLI version matters. You need explicit scripted updates or richer asset handling.
Releases API Precise HTTP verbs/status codes; easy to preserve request/response evidence. More shell/JSON complexity; authentication/header mistakes are easy. Automation platforms or diagnostics need exact API semantics.

Do not combine all three mechanisms in one job simply because they exist. More mechanisms means more token paths, more update semantics, and more ways to accidentally treat a partial success as complete publication.

4. Pre-created annotated tag versus release-time tag creation

A pre-created tag separates source authorization from release metadata creation. It is easier to inspect the ref before publishing. Release-time creation reduces steps, but it makes explicit ref selection essential. Protected tags can further restrict who may create release refs.

Choice Maintainability / auditability Failure isolation Rollback / cleanup
Pre-create exact protected tag Clear: tag/SHA can be reviewed independently before release job. Tag failure is distinct from release-record failure. Release record can be deleted while retaining tag; tag cleanup requires separate authorization.
Create tag in release job Compact workflow but combines two mutations. Release error may leave partial state depending on mechanism. Need to inspect both tag and release before retry.
Annotated tag Carries a tag message and tag object identity. More metadata to verify/sign if your policy uses signatures. Still must preserve target commit SHA.
Lightweight tag Simple ref directly to commit. Less tag-level metadata. Fine when release record provides notes and policy does not require annotated tags.

5. Generated notes versus curated notes

Generated notes scale well and reduce omissions when commits use consistent trailers. Curated notes communicate impact better. A robust model uses generated data as a reproducible base, then treats human edits as release metadata whose author/time are preserved—not as a rewrite of the release’s source or artifact identity.

glab changelog generate \
  --from "$PREVIOUS_RELEASE_SHA" \
  --to "$TARGET_SHA" \
  --version "$VERSION" \
  > generated-notes.md

# Curator may add context, but these immutable fields stay machine-produced:
printf '\nSource SHA: `%s`\nArtifact SHA-256: `%s`\n' \
  "$TARGET_SHA" "$ARTIFACT_SHA256" >> generated-notes.md

6. Immutable assets versus external mutable URLs

Asset links are references; they do not copy the target into a magical immutable store. A URL like https://downloads.example/app/latest.zip is operationally convenient and evidentially weak. A versioned package coordinate, container digest, commit-SHA raw path, or content-addressed object plus digest is auditable.

Asset pattern Consumer convenience Integrity / auditability Recommended use
Moving latest URL High Low unless separately signed/digested and archived Never as the sole release identity.
Job artifact URL Medium Pipeline-linked but retention/expiration can break later downloads Short-lived evidence, not durable release distribution.
Commit-SHA raw URL Medium Immutable repository content for committed files Good teaching/small metadata artifacts.
Generic package version / container digest High Strong version/digest identity and distribution semantics Preferred durable release asset model; Chapter 23.

7. Protected tags and publication authorization

Release write permission and tag-creation permission are related but not identical. GitLab documents that a user creating/updating/deleting a release associated with a protected tag must also be permitted to create that protected tag. This makes a protected tag namespace a useful release authorization boundary.

A broad PAT with api can often do much more than the release needs. Prefer CI_JOB_TOKEN where the endpoint supports it; otherwise use a narrowly scoped project/group token and isolate it to the release job/ref. Never print it for debugging.

8. Idempotency and retries: “try again” is a state transition, not a button

Before retrying a failed release job, inspect whether the tag exists, whether the release exists, whether asset links were already added, and whether evidence was collected. The YAML release keyword fails if the release already exists; glab release create can update an existing release. Those different semantics must be part of the retry design.

LAB_TAG="v0.0.0-ch22-lab.${CI_PIPELINE_ID}"

# Inspect first.
git ls-remote --tags origin "refs/tags/$LAB_TAG"
GLAB_ENABLE_CI_AUTOLOGIN=true glab release view "$LAB_TAG" --repo "$CI_PROJECT_PATH" || true

# Decide whether the correct action is create, update, repair an asset link,
# or do nothing. Do not blindly rerun a non-idempotent release mutation.

9. Worked decision table

Scenario Recommended approach Trust/tier prerequisite Observable proof
One immutable release per protected tag Pre-create protected tag, then YAML release. Free role-based tag protection; authorized tag creator. Tag target SHA + compiled job + release API response + artifact digest.
Release notes need post-publication typo fix glab or PUT /releases/:tag to update metadata only. Developer+ and protected-tag permission if applicable. Release tag/SHA unchanged; only description timestamp/content changes.
Central platform publishes many projects Direct API or glab -R with narrow project identity and explicit tag/SHA contract. Cross-project authorization intentionally configured. Caller identity, target project/tag/SHA, response code, audit log where available.
Long-lived binary distribution Release record links to versioned registry/package identity, not job artifact. Registry permissions; Free path depends on selected registry format. Package version/digest + release link + consumer hash.

10. Keep state boundaries explicit

State layer Evidence to capture Why release correctness depends on it
Source/revision CI_PIPELINE_SOURCE, ref, CI_COMMIT_SHA, tag object/target SHA Proves exactly which repository state the release claims to represent.
Compiled configuration Merged YAML, release-job inclusion/rules, image/tool identity Proves which orchestration GitLab actually compiled.
Job/runner Pipeline/job IDs, actor, runner/executor, glab --version Separates configuration intent from execution context.
Identity/trust CI_JOB_TOKEN or narrowly scoped alternative, protected-tag rule Shows who was authorized to create/update the tag/release.
Artifact/evidence Artifact SHA-256, evidence snapshot path, changelog input range Connects release metadata to exact bytes and review evidence.
External/distribution Asset URL, immutable path/digest, consumer re-download digest Proves consumers retrieve the same object you verified.
Governance/recovery Exact tag/release ID, superseding record, deletion decision Makes rollback or cleanup bounded instead of “delete latest”.

A release does not authorize deployment, and a deployment approval does not validate the release artifact. Similarly, a green release job does not prove a downstream registry or external link is healthy. Keep build evidence, publication authorization, release metadata, deployment authorization, and external state independently observable.

11. Design checklist

  • Exact VERSION, tag, and SHA are inputs, never inferred from “latest”.
  • Artifact digest comes from the tested artifact, not a release-time rebuild.
  • Choose one primary publication mechanism and document its retry/update semantics.
  • Use protected tag namespaces to reduce accidental publication.
  • Prefer job token over broader credentials where supported.
  • Keep changelog range/configuration reproducible.
  • Link to immutable/versioned assets and verify consumer-side digest.

Knowledge check

Why can a YAML release job and glab release create behave differently on a retry?

What does a protected tag add to release governance?

Why are generated changelogs not enough for provenance?

When is a job artifact a weak release asset?

A release already exists but only the notes contain a typo. Should you delete and recreate it?

Next lesson

Diagnostics, failure modes, security, and performance

Break the release chain deliberately: wrong tag target, rebuilt artifact, mutable asset drift, over-broad token, and ambiguous cleanup—then repair each from preserved evidence.

Version and compatibility note

GitLab and GitLab Runner evolve continuously. Treat version-sensitive YAML, runner/executor behavior, APIs, security features, policy controls, tiers, and deprecations as assumptions to verify against the current official GitLab documentation before production use. Preserve the exact project/ref/SHA, compiled configuration, pipeline/job IDs, runner/tool versions, and external target evidence used for any reproducible lab or incident record.

Official references and version notes

Documentation verification date: 2026-09-12. Releases, changelogs, the Releases API, release links, base release evidence, and role-based protected tags are documented across Free/Premium/Ultimate unless a narrower tier is explicitly called out. The current YAML release flow uses glab; current docs require glab 1.58.0 or later. release-cli was deprecated in GitLab 18.0 and is planned for removal in 20.0. The lesson treats additional evidence recollection and some evidence/report enrichment as optional where current docs specify narrower tier/offerings.

Current assumptions used in this chapter: Version-sensitive YAML, Runner/executor behavior, APIs, security features, policy controls, tiers, and deprecations must be verified against the exact GitLab, GitLab Runner, tool, and external-system versions used in production. Preserve the exact project/ref/SHA, compiled configuration, pipeline/job IDs, runner/tool versions, and external target evidence used for reproducible work.

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
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0 Send only Ethereum/ERC-20 compatible assets to this address.