Skip to content

Releasing Antiphon

The whole distribution story hangs off signed git tags on the canonical repository at git.sr.ht/~donquinleone/antiphon. The version string is derived from git describe at build and package time and is written nowhere else, so a release is one new signed tag: pushing it drives CI to build the binary and bump every channel.

Cutting a release

  1. Gate green on master, and scan the tag delta for leaked personal data:
cargo fmt --all --check \
  && cargo clippy --workspace --all-targets --locked \
       -- -D warnings \
  && cargo test --workspace --locked
git log --stat vLAST..HEAD    # a public eye: no real names,
                              # addresses, private domains

The repository is pseudonymous, so anything traceable is a leak and must be purged from history before the tag, not just from the tip.

  1. Tag and push. Write the notes to a file, cut a signed annotated tag, and push it to origin:
git tag -s vX.Y.Z -F notes-vX.Y.Z.txt
git push origin master
git push origin vX.Y.Z

That is the whole release. The tag push triggers release.yml; nothing else is done by hand.

  1. Watch the release build and confirm every channel landed (below).

What the tag build does

release.yml is submitted only for tag pushes, through the git.sr.ht submitter filter, so a branch push landing on the tagged commit can no longer race it:

submitter:
  git.sr.ht:
    enabled: true
    allow-refs:
      - "refs/tags/v*"

On the tag it, in order:

  1. Builds the release binaries --locked (linked with mold for speed), packages antiphon-vX.Y.Z-x86_64-linux-gnu.tar.gz (the two binaries, the systemd, dinit, runit and autostart service files, LICENSE and README.md) with a .sha256 sidecar, and uploads both as tag artefacts.
  2. Fetches the git tag archive SourceHut generates and takes its sha256, the value the source-building packagers pin.
  3. Pushes the version bump to each channel repository over one CI deploy key: the Homebrew tap (url + sha256), the AUR (PKGBUILD, with .SRCINFO regenerated by makepkg on the runner), and the copr-spec repo (Version:).
  4. Mirrors master and the tag to the GitHub mirror.

The channel bump commits are metadata and are unsigned; the tag and the binary are signed at the source. The build guest carries none of the local git identity routing, so release.yml sets the pseudonym identity explicitly before committing.

Verify the release

hut builds list                      # release.yml green, once
curl -fsSLI \
  https://git.sr.ht/~donquinleone/antiphon/refs/download/vX.Y.Z/antiphon-vX.Y.Z-x86_64-linux-gnu.tar.gz
brew update && brew info antiphon    # tap shows stable X.Y.Z

The download must return 200. Check the AUR (antiphon) and the copr-spec repo advanced to X.Y.Z, and that the GitHub mirror carries the tag. There is no aarch64 tarball; arm machines build from source through the AUR packages, the Nix flake, cargo or Homebrew.

The channel repositories

Packaging does not live in this repository; each channel is its own source of truth, and release.yml bumps it in place:

Channel Repository
Homebrew git.sr.ht/~donquinleone/homebrew-antiphon
AUR ssh://aur@aur.archlinux.org/antiphon.git
Copr git.sr.ht/~donquinleone/copr-spec (SCM source)
Mirror github.com/DonQuinleone/antiphon

antiphon-git on the AUR tracks master, derives its version from git describe, and needs no release-time attention. Copr rebuilds from the copr-spec repo's .copr/Makefile; wire the Copr project's SCM source to that repo once.

One-time provisioning

The tag build pushes with a single dedicated CI SSH key, held as a build secret. To set it up:

  1. Generate a keypair (ssh-keygen -t ed25519).
  2. Add the public key to the SourceHut account (reaches the tap and copr-spec repos), the AUR maintainer account, and GitHub.
  3. Store the private key as a builds.sr.ht SSH key secret, and reference its UUID in release.yml's secrets: and environment.ci_key.

sr.ht and the AUR only accept SSH for push, so this is an SSH key rather than a token. Sign-everything still holds for what a human publishes (the tag and binary) while the automated metadata bumps are unsigned.

The docs site

This site is built by git.sr.ht/~donquinleone/antiphon-docs and auto-publishes: .build.yml deploys the master tip to docs.antiphon.net through hut pages, after a strict build that fails red on broken links or orphan pages. Push to master to publish.

The landing page

The landing page at antiphon.net is built by the antiphon.net repository and auto-publishes its master tip the same way. Update it when a release adds user-visible features, then merge to master.

The one-command installer

dist/install.sh is served live at https://antiphon.net/install.sh. It climbs a ladder and stops at the first rung that fits the machine:

  1. macOS: the tap and brew install antiphon.
  2. Arch: an AUR helper (paru, then yay); with neither it prints the manual makepkg route and falls through.
  3. Any Linux with nix: nix profile install from the flake.
  4. x86_64 Linux: the latest tag's verified tarball into ${XDG_BIN_HOME:-~/.local/bin}.
  5. Last resort: cargo install --locked from the repository.

The antiphon.net repository carries a byte-identical copy at its root; keep the two in step when the script changes.

aarch64 artefacts

The build fleet currently refuses to boot any arm image, so there is no prebuilt aarch64 tarball yet; arm users build natively through the AUR packages, the Nix flake, Homebrew or cargo. Revisit with sr.ht support before promising an arm tarball anywhere.