Chapter 25Lesson 01~170 minutes

Release Automation, Tags, GitHub Releases, Packages, and Container Registries: Core Concepts and Mental Model

Model release automation as controlled promotion of one verified source revision and one immutable artifact identity into releases, packages, and registries.

Release modelExact SHAVersionsProvenancePromotion

Learning objectives

  • Explain why release automation begins with exact source and artifact identity rather than a mutable branch name.
  • Distinguish Git tag, GitHub Release, Actions artifact, package version, container tag, container digest and provenance record.
  • Trace least-privilege publication from validated source through build-once output to consumer verification.
  • Recognize which release records are mutable aliases and which identities should remain immutable.
  • Inspect release/package state without changing it before any publication step.

1. The practical problem: publishing is a side effect, not another CI check

CI from Chapter 24 answered whether an exact revision was acceptable to integrate. Release automation adds durable external state: a tag can identify a commit, a GitHub Release can publish assets, a package registry can expose a version, and a container registry can expose both human-friendly tags and content-addressed digests. A green release job is therefore not enough; consumers need to know exactly which source and bytes were published.

The safest default is build once, identify the bytes, then promote those same bytes. Rebuilding separately for a release, staging environment and production creates multiple artifacts that may share a version label without sharing content.

2. Mental model: approved source becomes one verifiable release identity

Read the chain from left to right. An approved source revision is bound to a deliberate version/tag. The release workflow builds and tests once, computes a digest, optionally produces provenance, then publishes that same subject to one or more distribution surfaces. Consumers verify both the chosen version identity and the actual bytes.

Release causality and identity boundaries
flowchart TD
  A[Approved source SHA] --> B[Version + tag decision]
  B --> C[Release workflow revision]
  C --> D[Build/test once]
  D --> E[Artifact bytes + SHA-256 digest]
  E --> F[Optional provenance / attestation]
  E --> G[GitHub Release asset]
  E --> H[Package / OCI publication]
  H --> I[Immutable package version or image digest]
  G --> J[Consumer verification]
  I --> J
  F --> J

The arrows are identity-preserving obligations. A tag is not the artifact bytes. A release ID is not a container digest. A mutable latest tag may point somewhere new tomorrow, while an OCI digest identifies content.

3. Define each state before release changes it

Layer State to record Why it matters
Event/revision event, ref, exact source SHA, workflow SHA/path, run ID/attempt Proves which source and automation revision initiated publication.
Version/tag version string, tag name, tag target commit Version syntax is human policy; tag target is source identity.
Build subject filename/package/image, SHA-256 or OCI digest The digest is the byte/content identity consumers can verify.
GitHub Release release database ID, draft/prerelease/latest state, tag, assets A release is GitHub-owned publication metadata around a tag.
Package/registry namespace, package name/version, visibility/access, OCI digest Registry state can outlive the workflow and may have independent permissions.
Token/trust contents: write, packages: write, attestation permissions only where needed Publishing authority belongs only in the publishing job.
Provenance subject digest, signer/workflow identity, attestation ID/result Provenance binds claims to the exact subject; it does not replace testing.
Recovery deprecate/yank/supersede/delete policy and retained evidence A bad release should not be “fixed” by silently changing the bytes under the same version.

4. Read-only inspection comes before mutation

Before creating a release, prove the candidate commit and inspect existing tags/releases so you do not collide with an existing immutable identity.

git status --short
git rev-parse HEAD
git show -s --format='%H %cI %s' HEAD
git tag --points-at HEAD
gh release list --limit 20
gh api "repos/{owner}/{repo}/releases?per_page=20" --jq '.[] | [.id,.tag_name,.draft,.prerelease,.published_at] | @tsv'

For package or GHCR work, inspect the existing package identity and repository linkage before granting packages: write. A package can have access control distinct from its source repository, and a workflow repository must actually have package access.

5. Tags, releases, package versions and digests answer different questions

Identifier Answers Mutability warning
Git commit SHA Which source tree revision? Commit object identity is stable.
Git tag v1.2.3 Which source revision did this release name select? Ordinary tags can be moved unless protected/locked by policy.
GitHub Release ID Which release record in GitHub? Metadata can be editable; immutable-release settings protect tag/assets after publish.
Package version Which registry version name? Registry overwrite/yank rules vary by ecosystem.
Container tag :latest Which image does this alias currently reference? Mutable by design in many registries.
OCI digest @sha256:… Which image content? Content-addressed identity; preferred for promotion/verification.
Attestation subject digest Which bytes are covered by a signed claim? Valid only if verifier also checks expected signer/repository/workflow identity.

6. Put publishing authority only where publication happens

A build/test job generally needs contents: read or even permissions: {} when no checkout/API access is needed. Creating a Git tag or GitHub Release requires repository write authority; publishing a repository-associated GitHub Package/GHCR image normally uses GITHUB_TOKEN with packages: write. Do not give those rights to pull-request test jobs or every job in the workflow.

Security boundary: an action can access github.token even when you do not pass the token explicitly. Keep the job permission set narrow and treat every executed action/script in a publishing job as code running with that authority.

7. Immutable releases strengthen the release record

When release immutability is enabled, publishing locks the release-associated tag and assets. GitHub also creates a cryptographically verifiable release attestation covering the release tag, commit SHA and assets. The recommended flow is therefore draft → attach all assets → publish. Draft state remains mutable until publication.

Immutability is not the same as “nothing about the release can ever change.” GitHub still permits selected metadata such as title/release notes and prerelease/latest designation to change. Treat the protected tag and assets—not editable prose—as the integrity boundary.

8. GHCR uses both repository authorization and content identity

GitHub Container Registry supports OCI images. A workflow can use GITHUB_TOKEN to publish a package associated with its repository when package access permits it. Public GHCR images can be pulled anonymously. For promotion and deployment, record the pushed digest and prefer pulling name@sha256:… instead of assuming a mutable tag still points to the original image.

A package namespace matching a repository name does not by itself prove repository linkage. Publishing from a workflow with GITHUB_TOKEN commonly establishes the association for a new package, while pre-existing packages may require explicit Actions repository access.

9. Rollback means selecting known-good immutable content

A rollback should normally promote or redeploy a previously verified digest/version. It should not rebuild old source and call the result “the same release.” For ecosystems that support deprecation or yank semantics, preserve the bad version as historical evidence when policy permits and mark it unsuitable. For container registries, move a mutable deployment alias only after verifying the target digest.

Deleting a release is a destructive administrative action, not a debugging step. Preserve run/attempt, release ID, tag target, asset digest and provenance before cleanup. With immutable releases, deleted tag names cannot be reused, so unique lab versions are essential.

10. Lesson summary

A secure release is a mapping between exact source, exact bytes, explicit version, narrowly authorized publication and independently verifiable distribution state. Human-friendly tags and release pages help discovery; cryptographic digests and provenance establish artifact identity.

Next lesson

Release Automation, Tags, GitHub Releases, Packages, and Container Registries: Guided Hands-On Workflow

Continue with the next lesson to build on the current concepts, evidence, security boundaries, and operational practices.

Knowledge check

Why is main a poor release identity?

Does a GitHub Release asset digest identify the Git tag target?

Why should packages: write not be granted to a normal PR test job?

What does image@sha256:… give that image:latest does not?

If immutable releases are enabled, when should assets be attached?

Official references and version notes

  • About releases — GitHub Releases are based on Git tags and add release metadata/assets around a versioned source point.
  • Managing releases — Current release creation, editing and deletion behavior.
  • Immutable releases — Current tag/asset immutability and automatic release-attestation behavior.
  • GHCR — Current GitHub Container Registry authentication, package linking and digest guidance.
  • GitHub Packages permissions — Repository/granular package permissions and GitHub Actions access.
  • GITHUB_TOKEN authentication — Least-privilege token use in workflows.
  • gh release create — Current CLI release creation, --verify-tag and immutable-release handling.
  • gh release verify — Verification of cryptographically signed immutable-release attestations.
  • gh release verify-asset — Verify a local asset against the release attestation and digest.
  • actions/attest v4.2.2 — Immutable attestation action revision referenced by optional provenance examples.

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.