Releasing¶
grex uses semantic versioning driven by Conventional Commits. Maintainers cut releases by pushing a version tag; GoReleaser builds binaries and container images from that tag.
Published notes and install coordinates are mirrored on the docs site under Releases (changelog regenerated on each docs build from GitHub Releases).
Prerequisites¶
- Push access to the canonical repository (
dennisme/grex) - A clean
main(or the commit you intend to ship), with CI green svuinstalled:
How the version is chosen¶
svu next inspects git history since the
latest tag and prints the next version:
| Commit shape | Version bump |
|---|---|
fix: … (no breaking) |
patch |
feat: … (no breaking) |
minor |
BREAKING CHANGE: footer, or type!: |
major |
chore:, doc:, ci:, test:, … |
no bump (same as current tag) |
grex validates commit messages with commitizen (see
Contributing). Prefer types that match that schema so both
CI and svu agree.
Preview without tagging:
Cut a release¶
- Ensure the commit you want is on the default branch (or checkout that SHA).
- Confirm the next tag looks right:
- Create and push the tag (requires a clean working tree):
That recipe:
- Fetches remote tags so
svusees the latest release - Runs
svu next(for examplev0.2.0) - Creates the git tag on the current commit
- Pushes the tag to
origin
It does not touch deploy/charts/grex/Chart.yaml. That file's
version/appVersion are a fixed 0.0.0 placeholder; every workflow that
packages the chart overrides both with an explicit --version/
--app-version flag derived from the tag, so the committed file is never
read for a real release. See Helm chart versioning.
-
Watch CI:
-
goreleaser (tag) — binaries, container image, chart OCI push to GHCR
- helm-release (tag) — packages the chart, publishes it as its own
GitHub Release (
helm-grex-VERSION), pushes the updated repo index to thegh-pagesbranch - docs (runs after helm-release completes, plus push-to-
mainandrelease: published) — rebuilds Pages, mirroring thegh-pagesindex intohttps://dennisme.github.io/grex/charts/
Do not create release tags by hand unless you are fixing a one-off mistake;
just release-tag is just a thin wrapper around svu next + git tag +
git push, but it also checks for a clean tree and refuses to retag.
Manual equivalent¶
What the release pipeline publishes¶
Configuration lives in .goreleaser.yaml at the repository root, plus
.github/workflows/helm-release.yaml for the chart. On a version tag, these
publish:
| Artifact | Destination |
|---|---|
| Cross-compiled binaries (linux / darwin / windows × amd64 / arm64) | GitHub Release assets (archives + checksums.txt) |
| Container images | GHCR (ghcr.io/dennisme/grex) multi-arch (amd64 + arm64) |
Helm chart package (.tgz) |
Its own GitHub Release (helm-grex-VERSION), published by helm-release.yaml (cr) |
| Helm chart (OCI) | oci://ghcr.io/dennisme/charts/grex |
| Helm chart (Pages index) | https://dennisme.github.io/grex/charts/, cr pushes index.yaml to gh-pages, the docs workflow mirrors it in on the next run |
| Release notes (changelog) | GitHub Release body |
Image tags include {{ .Version }} (no v, matches chart appVersion),
{{ .Tag }} (with v), major/minor convenience tags, and latest. The chart
defaults image.tag to Chart.AppVersion, so a stock helm install pulls
the matching GHCR image.
Binaries embed version metadata via internal/buildinfo ldflags (same package
as just build). The release image is built from Dockerfile.goreleaser
(copies the GoReleaser binary into Alpine). The root Dockerfile remains for
local source builds and compose/Helm smoke tests.
Helm chart versioning¶
| Field | Source | Meaning |
|---|---|---|
Chart version (in Chart.yaml) |
fixed 0.0.0 placeholder, never edited |
Not read for a real release |
Chart version (as packaged/published) |
explicit --version "$VER" at package time, in goreleaser.yaml and helm-release.yaml |
Helm package / repo version |
Chart appVersion (as packaged/published) |
explicit --app-version "$VER", same string |
Default container image tag |
| Git tag | svu next (with v prefix) |
Triggers both goreleaser.yaml and helm-release.yaml |
For grex 1.0, chart version and app version stay equal to the grex release.
Chart-only fixes still ship as a normal grex patch release (no separate chart
version stream yet). Both workflows derive $VER the same way
(${GITHUB_REF_NAME#v}), so they can't drift from each other even though
they run independently.
Install after a release:
# Chart repository on GitHub Pages (index refreshed once helm-release + docs finish)
helm repo add grex https://dennisme.github.io/grex/charts/
helm repo update
helm upgrade --install grex grex/grex --version 0.2.0 -n grex --create-namespace
# Or pin an OCI artifact from GHCR (available as soon as the tag workflow finishes)
helm upgrade --install grex oci://ghcr.io/dennisme/charts/grex --version 0.2.0 \
-n grex --create-namespace
The Pages index reflects whatever helm-release.yaml last pushed to
gh-pages, not whatever's on main (there's nothing chart-related to
package from main anymore). Historical .tgz files are kept on each
chart's own GitHub Release and on GHCR (OCI).
Pretty release notes (changelog)¶
GoReleaser sets changelog.use: github-native, which calls GitHub’s
generate release notes
API. That is what produces real PR links:
Why not commit-log grouping? This repo mostly uses merge commits, so
subjects are plain feat: … without (#31). A commit-list changelog has no
PR URL to attach. GitHub-native walks merged pull requests between tags
instead.
Optional sections by PR label are configured in .github/release.yml
(✨ Features, 🐛 Bug Fixes, …, catch-all). Label PRs when you want them sorted;
unlabeled PRs still appear under Other Changes with a link.
The release footer (Docker / Helm install / docs) is still appended by GoReleaser after the generated notes.
Preview (needs gh auth):
gh api repos/dennisme/grex/releases/generate-notes \
-f tag_name=v0.2.0 -f target_commitish=main \
--jq .body
Checklist before tagging¶
- [ ] Target commit is what you intend to ship (usually tip of
main) - [ ] Conventional commits since the last tag reflect the intended bump
- [ ]
just test/just lint(and any relevant chart or compose checks) pass - [ ] Docs and user-facing notes match the change set
- [ ]
svu nextshows the version you expect - [ ] You are pushing the tag to the repository that runs the release workflow
After the release¶
- Confirm the GitHub Releases page lists the new app tag with its binary archives
- Confirm a second GitHub Release
helm-grex-<version>exists with the chart.tgzasset (published byhelm-release.yaml) - Confirm the GHCR image
ghcr.io/dennisme/grex:<version>exists - Confirm the OCI chart
oci://ghcr.io/dennisme/charts/grexis pullable at that version - Confirm
helm-release.yamlfinished (it pushes the updated index togh-pages), then confirm the docs workflow'sworkflow_runtrigger fired after it so the chart repo indexes the new chart - Confirm the docs workflow also ran on the release published event so Releases → Changelog includes the new notes
Troubleshooting¶
svu not found
Install it (see Prerequisites).
Tag already exists
just release-tag refuses to retag. Either there is nothing bump-worthy since
the last release, or your local tags are stale—run git fetch --tags and
check svu current / svu next.
Wrong bump level
svu only sees commit messages. A user-facing break needs feat!: / fix!:
or a BREAKING CHANGE: footer; pure feat: commits stay on minor.
Workflow did not run
Confirm the tag was pushed to the repo that owns
.github/workflows/goreleaser.yaml, and that the workflow triggers on that
tag pattern.
Chart repo on Pages shows the old version
cr (in helm-release.yaml) publishes the chart's GitHub Release before
it finishes pushing the updated index.yaml to gh-pages. The docs
workflow's workflow_run trigger waits for helm-release.yaml to fully
complete before mirroring the index, so this should self-correct once that
run finishes. If helm-release.yaml failed outright, re-run it (or push a
no-op tag fix) rather than editing gh-pages by hand.
Related¶
- Contributing — conventional commits and PR CI
- Install — how operators obtain binaries and images
- Design notes on versioning and GoReleaser in the SPEC design