packaging.md

  1# Packaging and releases
  2
  3Packaging is part of the baseline when the project is meant to be installed,
  4not an afterthought.
  5
  6Read `mise.md` for build task templates before adding package tasks. For CLI,
  7TUI, and MCP binaries, also read `cli.md` for version-policy guidance.
  8
  9## Choose the artifact
 10
 11- **Plain CLI/MCP server**: cross-compiled binaries are usually enough.
 12- **System service**: add systemd/OpenRC files and consider nFPM packages.
 13- **Desktop/Wails app**: use nFPM for Linux packages, desktop files, icons, and
 14  WebKit runtime dependencies; use Wails/NSIS for Windows installers when
 15  needed.
 16- **Library**: no binary packaging unless examples/tools are part of the repo.
 17
 18## Version gating
 19
 20Package tasks should fail on ambiguous versions. Prefer exact tags for release
 21packages. For Git-tagged releases, a package task can gate on an exact tag:
 22
 23```sh
 24version=$(git describe --tags --exact-match 2>/dev/null) || {
 25  echo "Error: package builds require an exact vMAJOR.MINOR.PATCH tag" >&2
 26  exit 1
 27}
 28version=${version#v}
 29```
 30
 31For jj-backed projects, use the project's agreed jj/git-derived release command
 32instead. Do not infer package versions from Go `BuildInfo` unless the project
 33explicitly chose that policy. For development builds, `VERSION=dev` is fine;
 34for packages, be stricter.
 35
 36## nFPM baseline
 37
 38```yaml
 39# yaml-language-server: $schema=https://nfpm.goreleaser.com/static/schema.json
 40name: example
 41arch: ${GOARCH}
 42version: ${VERSION}
 43release: ${RELEASE:-1}
 44section: utils
 45priority: optional
 46maintainer: Amolith <amolith@secluded.site>
 47description: Short human description
 48homepage: https://example.invalid
 49license: LicenseRef-MutuaL-1.2
 50
 51contents:
 52  - src: build/pkg/example
 53    dst: /usr/bin/example
 54```
 55
 56For desktop apps, add:
 57
 58```yaml
 59contents:
 60  - src: build/pkg/example
 61    dst: /usr/bin/example
 62  - src: packaging/example.desktop
 63    dst: /usr/share/applications/example.desktop
 64  - src: dist/example.png
 65    dst: /usr/share/icons/hicolor/512x512/apps/example.png
 66
 67overrides:
 68  deb:
 69    depends:
 70      - libwebkit2gtk-4.1-0
 71    recommends:
 72      - xdg-utils
 73  rpm:
 74    depends:
 75      - (webkit2gtk4.1 or libwebkit2gtk-4_1-0)
 76  apk:
 77    depends:
 78      - webkit2gtk-4.1
 79  archlinux:
 80    depends:
 81      - webkit2gtk-4.1
 82```
 83
 84## mise package tasks
 85
 86Use hidden preparation tasks for version, icon conversion, package build, and
 87optional compression. Visible tasks should be simple: `pkg`, `pkg:deb`,
 88`pkg:rpm`, `pkg:apk`, `pkg:arch`.
 89
 90Minimal visible tasks look like this:
 91
 92```toml
 93[tasks."pkg:deb"]
 94description = "Build a deb package"
 95env = { RELEASE = "1" }
 96run = "nfpm package -f packaging/nfpm.yaml -p deb -t build/pkg"
 97
 98[tasks."pkg:rpm"]
 99description = "Build an rpm package"
100env = { RELEASE = "1" }
101run = "nfpm package -f packaging/nfpm.yaml -p rpm -t build/pkg"
102```
103
104UPX is optional. Use it for Linux binaries when size matters; do not assume it
105works well for every OS or binary format.
106
107## Cross-compilation
108
109- `CGO_ENABLED=0` makes plain Go binaries easy to cross-compile.
110- For CLI, TUI, and MCP release binaries, prefer `netgo`, `osusergo`, optional
111  project-specific `static_build`, `-d -s -w -buildid=`, and
112  `-extldflags=-static` when dependencies are pure Go.
113- Treat Go VCS build metadata as a policy choice, not the package version
114  source. If a package needs exact version or commit strings, derive them in the
115  package task and inject them. If a release intentionally relies on Go
116  `BuildInfo`, make that explicit and consider `-buildvcs=true`.
117- Wails/Linux builds require native CGO and WebKitGTK.
118- Windows Wails cross-builds from Linux need mingw-w64; NSIS packages need
119  `makensis`.
120- macOS desktop builds require macOS unless a project has proven otherwise.
121
122Document these constraints in task descriptions and preconditions rather than
123letting users discover linker failures.