Releasing¶
Maintainer process. Reading a release is covered in Security.
What a tag publishes¶
Pushing a v* tag runs release.yml,
which produces:
| Artifact | Where |
|---|---|
| CLI archives for linux, darwin and windows on amd64 and arm64 | GitHub Release |
| A checksum file, plus a cosign bundle signing it | GitHub Release |
| An SPDX SBOM per archive | GitHub Release |
| A multi-arch container image, signed and attested | ghcr.io/ethan-kane-ops/k8s-pod-oom-oracle |
| The Helm chart, signed and attested | oci://ghcr.io/ethan-kane-ops/charts/oom-oracle |
Nothing is built on a laptop. just release writes the changelog, tags and
pushes; the workflow does the rest.
cosign is version-pinned, and bumping it is manual
release.yml pins cosign-release on all three installer steps. Pinning
the action by SHA says nothing about the binary it downloads, which
otherwise tracks the newest release. v0.1.0 failed on exactly that: cosign
v3 had changed sign-blob's flags, the signing step errored, and the tag
published an image and a chart with no archives. Dependabot updates the
action ref but not the version below it, so bump it by hand and let a
release-candidate tag prove it.
The daemon is Linux-only
Darwin and windows archives exist because inspect and watch are HTTP
clients, and the person reading a report is rarely on the node. daemon
needs a Linux kernel and says so if started elsewhere.
Cutting one¶
just release-preview # what the next version and changelog would be
just release-snapshot # build every artifact locally, publish nothing
just release minor # auto | patch | minor | major | vX.Y.Z
just release refuses to run when the working tree is dirty, when the tag
already exists, when just check fails, or when CHANGELOG.md has no
[Unreleased] heading to close.
Where the notes come from¶
A release section has two halves. Breaking changes and migration notes are
written by hand under ## [Unreleased] as the work lands, because no commit
subject can say which JSON field a consumer has to rename. The per-commit lists
are generated by git-cliff at tag time.
hack/changelog-release.sh merges them: it renames [Unreleased] to the version
being cut, folds the generated groups in underneath the hand-written prose, and
opens a fresh empty [Unreleased] above. One heading per version, prose first.
Neither of git-cliff's own modes can do this. -o regenerates the file from
commit subjects and deletes the hand-written notes outright. --prepend keeps
them but inserts its section above them, leaving two headings for one version;
hack/release-notes.sh stops at the first, so the published notes are commit
subjects and the migration notes are silently missing. release-notes.sh now
fails on a duplicated version heading rather than truncating, and
hack/changelog_test.go covers both paths.
Release notes come from the changelog¶
hack/release-notes.sh v0.1.0 prints the CHANGELOG.md section for a version.
just release runs it before tagging and the workflow runs it before building,
and both fail if the section is empty.
The alternative would be generating notes from commit subjects at release time.
That was the original behaviour, and it published a release whose only mention of
a renamed API field was fix(oom): filter the victim across PID namespaces.
The chart version is the tag¶
charts/oom-oracle/Chart.yaml states the version three times: version,
appVersion, and the image tag inside the artifacthub.io/images annotation.
The workflow refuses to publish when any of them disagrees with the tag, and it
checks after the image job has pushed, so a missed bump leaves a
half-published release.
just release sets all three through hack/chart-version.sh, so there is
nothing to remember. A chart whose version is not the version it installs is
worse than no chart, because it looks authoritative.
Artifact Hub¶
Registration is manual, one-off, and needs a public repository with a published chart. Both are now true.
- Add the repository at artifact hub:
| Field | Value |
|---|---|
| Kind | Helm charts |
| Name | oom-oracle |
| Display name | oom-oracle |
| URL | oci://ghcr.io/ethan-kane-ops/charts/oom-oracle |
The name becomes the URL segment, so the listing lands at
artifacthub.io/packages/helm/oom-oracle/oom-oracle. An OCI repository holds
one chart, so naming it after the chart rather than the owner keeps a second
chart from having to squat on the name.
- Copy the repository ID it issues into
artifacthub-repo.ymlat the repository root. just chart-claim.
Step 3 pushes that file to the chart's OCI repository under the artifacthub.io
tag, which is where Artifact Hub looks to confirm the listing belongs to this
project. Without it the chart still lists; it just is not a verified publisher.
The ordering is the part worth knowing: the ID does not exist until step 1, so
the file cannot be filled in ahead of time, and just chart-claim refuses to
push it empty. The owner name and email in that file are published to a public
registry, and the email has to match the Artifact Hub account because that match
is the ownership check.
Version metadata¶
--version reports the tag, the full commit and the commit date, injected with
-ldflags -X against internal/version. The commit date rather than the build
date, so the same source produces the same binary.
If a release goes wrong¶
Delete the tag locally and remotely, delete the GitHub Release, and cut the next patch version. Do not move a tag: the image is signed by digest, and a moved tag leaves a signature pointing at content nobody can reach.