Chapter 24Lesson 01~300 minutes

Releases, Tags, Release CLI, Evidence, Changelogs, and Deployment Traceability: Concepts, Architecture, and Mental Model

Model a production release as a chain from Git commit and tag through GitLab Release metadata, assets, changelog, release evidence, immutable artifact/image identities, and deployment records.

Mental modelGit tagRelease objectEvidenceChangelogTraceability

Learning objectives

  • Separate a Git tag/ref from the GitLab Release object layered on that tag.
  • Trace source commit → tag → Release → asset/package/image digest → deployment evidence.
  • Explain automatic release evidence and its tier-specific extensions without treating evidence as a security attestation.
  • Choose current glab/API automation rather than deprecated release-cli.
  • Use generated changelogs as structured release input while preserving human review.
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. The practical problem: a release name is not enough

Chapters 22 and 23 gave packages and OCI images durable coordinates and digests. A production release must now connect those objects back to the exact source and delivery event. “Version 2.4.0 shipped” is weak evidence unless an operator can answer: which commit did v2.4.0 name, which pipeline built the deliverables, which immutable package or image digest was distributed, what Release metadata described it, and which deployment consumed that identity?

Git provides commit and tag objects. GitLab adds a hosted Release object, release notes, assets/links, evidence snapshots, API/CLI automation, and relationships to milestones and deployment activity. Do not collapse these layers into one abstraction.

2. Git tag versus GitLab Release object

Layer Object Identity / mutation Operational meaning
Git Commit Content-addressed commit SHA; immutable object. Source state.
Git Lightweight tag Ref name pointing at an object; tag ref can be deleted/recreated if policy permits. Human version selector. No tag message object.
Git Annotated tag Tag object with message/tagger that points to another object. Version selector plus Git-native annotation.
GitLab Release Hosted metadata associated with a tag: name, notes, date, assets, links, evidence. Product-facing release record.
Package/OCI Package version / image digest Registry identity; digest/hash is stronger than mutable names/links. Binary/content actually consumed.
GitLab environment Deployment Record linking job/commit/environment/status. What GitLab believes was deployed.

A Release is not a second Git commit and it is not the binary itself. It is metadata anchored to a tag. Deleting a Release leaves the tag; deleting the tag associated with a Release removes the Release too.

3. Mental model: release as a chain of independently verifiable identities

Release traceability chain
flowchart TD
  C[Commit SHA] --> T[Git tag vX.Y.Z]
  T --> R[GitLab Release]
  P[Pipeline / job] --> A[Package hash or OCI digest]
  A --> R
  R --> V[Release evidence JSON]
  A --> D[Deployment / environment]
  C --> P
  D --> O[Operational rollback record]

The tag connects release metadata to source. The pipeline connects source to produced content. A package checksum or OCI digest names the deliverable. A deployment record should resolve to the same source/artifact identity. Release evidence snapshots surrounding metadata, but it does not replace independent artifact verification.

4. Read-only inspection before release mutation

Before creating or editing a release, prove current state from at least two surfaces:

git fetch --tags --prune
git status --short
git rev-parse HEAD
git tag --list "v*" --sort=-version:refname | head -n 10

glab release list -F json --per-page 20
# Inspect a known release without editing it:
glab release view v1.2.3 -F json

For machine-readable API evidence, use GET /projects/:id/releases and GET /projects/:id/releases/:tag_name. Record project, tag, Release creation/release timestamps, returned commit SHA, asset links, and evidence file path. Never infer a binary digest merely because it is linked from a release.

5. Current automation interfaces: glab, release keyword, REST API

For new automation, prefer glab, the CI release keyword, or the Releases API. release-cli is deprecated since GitLab 18.0 and scheduled for removal in 20.0.

release_job:
  stage: release
  image: registry.gitlab.com/gitlab-org/cli:latest
  rules:
    - if: $CI_COMMIT_TAG
  variables:
    GLAB_ENABLE_CI_AUTOLOGIN: "true"
  script:
    - echo "Release metadata will be created after this job script succeeds."
  release:
    tag_name: $CI_COMMIT_TAG
    name: "Release $CI_COMMIT_TAG"
    description: "CHANGELOG.md"

Authentication nuance: for CI job-token auto-login, set GLAB_ENABLE_CI_AUTOLOGIN=true. Do not set GITLAB_TOKEN=$CI_JOB_TOKEN; glab sends GITLAB_TOKEN as a private-token header, which the Releases API does not accept as a job token and can result in 404 Not Found.

6. Assets are references; durability depends on the target

A Release includes automatically generated source archives plus optional asset links. An asset link has a display name and URL; it can point to a Generic Package, container/package download, documentation, runbook, or other durable service. The Release does not magically copy the referenced bytes unless your chosen workflow explicitly uploads them somewhere durable.

Asset pattern Strength Risk / recommendation
Generic Package version Project-scoped version + file checksum metadata. Good release-asset backend; verify exact version/hash.
OCI image digest Content-addressed manifest identity. Excellent deployment coordinate; link/report digest explicitly.
Job artifact URL Easy to generate. Usually ephemeral; expiry or manual deletion can break release links.
External HTTPS URL Can point anywhere. Treat mutable URL as indirection; preserve checksum/digest/provenance separately.
Source archive auto-link Derived from repository tag. Useful for source distribution; not a compiled binary identity.

7. Release evidence: audit snapshot, not cryptographic trust

When a release is created, GitLab creates release-evidence JSON automatically on Free/Premium/Ultimate across all offerings. The snapshot can include release metadata and related records; matching packages may be included when package versions match the release tag convention. Current tier-specific extensions matter:

  • Automatic snapshot: Free-compatible.
  • Collect another evidence snapshot on demand: Premium/Ultimate, Self-Managed/Dedicated.
  • Preserve report artifacts as release evidence: Ultimate.

The evidence SHA identifies the evidence snapshot. It does not assert that a package/image is vulnerability-free, signed by a trusted key, reproducibly built, or safe to deploy. Those are separate controls/evidence sources.

8. Changelog generation: structured commit data, not automatic editorial judgment

GitLab changelog generation selects commits using a configured Git trailer, by default Changelog, and emits Markdown. The default values such as added, fixed, changed, deprecated, removed, security, performance, and other give maintainers a useful taxonomy.

git commit -m "Harden release verification

Changelog: security"

glab changelog generate --version 1.2.0 --from <old_sha> --to <new_sha> > release-notes.md

Generated notes are evidence of selected commit metadata, not a substitute for human explanation of breaking changes, migration steps, compatibility, or known limitations.

9. Tags are release governance, not decoration

Because release metadata is anchored to tags, tag creation/deletion policy is part of release governance. Protected tags are Free across all offerings and can restrict who may create matching release tags. Maintainers/Owners configure the rules; deleting a protected tag requires GitLab UI/API and appropriate permission.

A particularly dangerous failure is deleting and recreating a release tag after consumers have cached or deployed the earlier ref. The same tag text can then name a different commit. Preserve the original incident evidence, restore by a new version/tag when possible, and use protected-tag policy to reduce this class of mutation.

10. Traceability invariant

A production release record is strong when the following invariant is independently checkable:

tag_commit_sha == release.commit.id == build_source_sha
release_asset_hash_or_digest == deployed_artifact_hash_or_digest
deployment.commit_sha == intended_release_commit_sha

Not every GitLab object stores every equality directly, so operators collect the chain from Git, Release API, package/container metadata, pipeline/job evidence, and environment/deployment records.

11. DevOps connection

Release governance reduces two forms of pressure: ambiguity (“which binary is this?”) and ceremony (“we have a release page, so we must be compliant”). The goal is a small, automatable chain of durable identities and explicit permissions. That chain supports rollback, incident response, audit, customer distribution, and later security policy without making the Release page the single source of truth for everything.

Knowledge check

Does a GitLab Release create a new Git commit?

Which deletion leaves the other object intact: deleting the Release or deleting the tag?

Why is an OCI digest stronger release evidence than the tag latest?

Why should new CI automation avoid release-cli?

Does release evidence prove the linked artifact is secure?

Summary

Git commits and tags provide source identity; GitLab Releases provide hosted metadata; package hashes/OCI digests provide deliverable identity; deployment records provide operational state; release evidence and changelogs add audit/context. A trustworthy release ties these layers together without pretending any one layer proves all the others.

Official references

Primary sources used for the current GitLab 19.3 behavior taught in this lesson:

Next lesson

Guided Hands-On Workflow and Core Operations

Create a disposable release, inspect it through Git/glab/API, attach durable synthetic identity, generate a controlled changelog, and verify the whole chain before cleanup.

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.