Skip to content

Releasing

Releases are cut locally (there’s no CI) with semver tags. Each one gets:

  • a GitHub release with archives for Linux and macOS (amd64 and arm64), each with the binary, the licence, the changelog and the deploy/ files
  • a multi-arch image at ghcr.io/lukeskelhorn/ingle, also pushed as ghcr.io/lukeskelhorn/domus until v1.0
  • a matching release in Linear’s Ingle pipeline
  1. In a PR, move everything under ## [Unreleased] in CHANGELOG.md to a new ## [vX.Y.Z] - YYYY-MM-DD section (Added, Changed, Fixed, Upgrade notes), update the links at the bottom, and merge it.
  2. On an up-to-date main, try it first: VERSION=vX.Y.Z task release:dry. It runs the checks, builds both Docker architectures and all four archives, and prints the notes.
  3. Once per machine: gh auth login, and docker login ghcr.io -u <github user> with a token that has write:packages.
  4. VERSION=vX.Y.Z task release. It refuses to run off main, with uncommitted changes, out of step with origin, for an existing tag, or without a changelog section. Then it builds and pushes the image, tags, and publishes the GitHub release with that section as the notes. A version with a suffix (v1.0.0-rc.1) is marked as a pre-release.
  5. In Linear, attach the release’s issues to it in the Ingle pipeline and mark it Released. That moves them to Done.
  6. Update the docs. They aren’t versioned with the app, so update this site for anything the release changed, and bump the version in the examples on Without Docker.

The first image push creates the GHCR package as private. Make it public once, under the package’s settings on GitHub, so servers can pull it without logging in.

task build stamps the binary with git describe (for example v0.1.0-3-gabc1234-dirty), so ingle version, /healthz and Admin home always say what’s running.