Releasing¶
A release is: bump the version, record it in CHANGELOG.md, tag the
commit, push the tag. Pushing a v* tag is the trigger — CI takes it from
there. There is no separate "publish" step and no dry-run mode on a normal
push: the moment a v* tag lands on GitHub, a public release is being
built.
Steps¶
-
Bump
VERSION. One line, no trailing newline content beyond the version itself —0.13.1, following semver. Patch for fixes, minor for features, major for breaking changes (same rule as everywhere else in this project). -
Add a
CHANGELOG.mdsection. Keep a Changelog format, newest on top:
## [0.13.1] - 2026-09-22
### Fixed
- What changed, in the past tense, one bullet per notable change.
The heading must read exactly ## [X.Y.Z] - date — CI's release-notes
extraction is an awk script matching ^## \[VERSION\] literally
against the tag (minus its v). A mismatched or missing heading means
the GitHub Release ships with a placeholder body instead of real notes.
-
Commit. Conventional Commits, matching this project's normal convention:
chore: cut 0.13.1 — <short summary>. -
Tag. An annotated tag,
vX.Y.Z, message following the sameX.Y.Z — <short summary>shape as the commit:
- Push both.
The tag push is what matters — .github/workflows/release.yml triggers
on any v* tag, whether or not main was pushed first (though push
main too; a tag whose commit never reaches the default branch is
confusing to browse later).
What CI does¶
Once the tag lands, .github/workflows/release.yml runs unattended:
- Checks out the tag.
- Builds
nixosConfigurations.installer.config.system.build.isoImage— a full ISO build, so this takes a while. - Copies the result to two filenames (each with a
.sha256alongside it), the same bytes both times: gisnix-installer.iso— always this name, never one with the version baked in. That is what makeshttps://github.com/kartoza/gisnix/releases/latest/download/gisnix-installer.isoa permanent link, which is what the docs site's download button points at.gisnix-installer-vX.Y.Z.iso— a hard link to the same file, named for this specific release, for grabbing an exact version rather than whatever "latest" currently means (testing a fix, pinning to a known-good ISO, browsing several versions on the Releases page).- Extracts this version's section out of
CHANGELOG.md(step 2 above) as the release body. - Publishes a GitHub Release named
gisnix vX.Y.Z, tagvX.Y.Z, with both ISOs and both checksums attached.
No manual "are you sure" gate exists beyond the tag push itself — treat
git push origin vX.Y.Z as the point of no return, not the commit before
it.
If a release build needs re-running without a new tag (a fixed CI script, say), trigger it by hand: Actions → Release → Run workflow, supplying the existing tag name. This re-runs the same build/publish steps against that tag without requiring a new version.
Downstream: bump the pin¶
Cutting a GISNIX release does not, by itself, change what any consumer
(nix-config, or any other downstream flake) actually builds — a consumer
pins GISNIX to a specific tag in its own flake.nix (url =
"github:kartoza/gisnix/vX.Y.Z") and has to bump that explicitly, then
relock:
Bumping the pin string in flake.nix before the tag actually exists on
GitHub leaves the flake unable to lock at all — nix flake lock/nix
develop/anything that touches the lock file fails outright until either
the tag is pushed or the pin is reverted. Land the GISNIX release first,
confirm the tag is actually on GitHub (git ls-remote --tags
git@github.com:kartoza/gisnix.git), then bump the downstream pin.