Buzz has three independent release lanes, each driven by a release PR — no human ever pushes a git tag:
| Lane | Recipe | Artifact |
|---|---|---|
| Desktop | just release-desktop |
Signed desktop app (macOS/Linux) |
| Relay | just release-relay |
ghcr.io/block/buzz container image |
| Mobile | just release-mobile |
Buzz mobile app (tag is the sprout_ref for the internal build) |
The three lanes version independently: the desktop version lives in
desktop/package.json, the relay version in crates/buzz-relay/Cargo.toml, and
the mobile version in mobile/pubspec.yaml.
The mobile lane publishes a mobile-v<version> tag that is consumed
manually, cross-repo, as the sprout_ref input to the internal
buzz-releases Buildkite pipeline (iOS dogfood → Block Comp Portal, App Store →
TestFlight — see Internal Releases). The OSS lane is
tag-only by design: OSS block/buzz CI cannot trigger CI in the private
buzz-releases repo (infosec), so a human cuts the internal build from the tag
rather than auto-dispatching across that boundary.
# Desktop release (next patch version)
just release-desktop
# Desktop patch / minor / explicit
just release-desktop patch
just release-desktop 0.4.0
just release-desktop 1.0.0
# Relay release (same argument forms)
just release-relay
just release-relay 0.4.0
# Mobile release (same argument forms)
just release-mobile
just release-mobile 0.4.0just release-desktop creates a version-bump/<version> PR; just release-relay creates a relay-release/<version> PR; just release-mobile
creates a mobile-release/<version> PR. Each bumps its own version manifest,
regenerates lockfiles, and appends a changelog entry. Merge the PR to trigger
the build automatically (the mobile tag is instead the sprout_ref a human
feeds the internal build — see above).
Re-running any of these recipes with the same version is safe — it detects the
existing branch and PR, resets to current main, regenerates the changelog
with any new commits, and updates the PR in place.
All three lanes share one engine; they differ only in which version manifest they bump, which branch prefix they use, and what the merge triggers.
just release-desktopruns locally onmain— computes the next version, creates (or reuses) aversion-bump/<version>branch, bumps the desktop manifests, regenerates lockfiles, generates a changelog entry inCHANGELOG.md, commits, pushes, and opens (or updates) a PR.- Merge the PR — the
auto-tag-on-release-pr-mergeworkflow detects theversion-bump/*branch merge and pushes av<version>tag. - Tag triggers
release.yml— builds, signs, notarizes, and publishes the desktop app for macOS and Linux.
just release-relayruns locally onmain— computes the next relay version, creates (or reuses) arelay-release/<version>branch, bumpscrates/buzz-relay/Cargo.toml, regeneratesCargo.lock, generates a changelog entry incrates/buzz-relay/CHANGELOG.md, commits, pushes, and opens (or updates) a PR.- Merge the PR — the
auto-tag-on-release-pr-mergeworkflow detects therelay-release/*branch merge and pushes arelay-v<version>tag. - Auto-tag dispatches
docker.yml— the same workflow then triggersdocker.ymlwith the version and tag ref, which builds the multi-arch relay image and publishesghcr.io/block/buzz:<version>(plus:<major>.<minor>,:<major>, and:latestfor stable releases). Prereleases (relay-v<version>-rc.1) publish only the prerelease tag and do not move:latest. (The dispatch — rather than relying ondocker.yml'spush: tagstrigger — is required because GitHub suppresseson: pushfor tags pushed by the workflow's ownGITHUB_TOKEN; the desktop lane dispatchesrelease.ymlfor the same reason.)
Every push to main continues to build and publish :main + :sha-<7> tags
(the rolling development image). The :latest tag tracks the latest stable
relay release only — it does not move on main pushes or prereleases.
just release-mobileruns locally onmain— computes the next mobile version, creates (or reuses) amobile-release/<version>branch, bumpsmobile/pubspec.yaml(preserving the+buildnumber), regeneratesmobile/pubspec.lock, generates a changelog entry inmobile/CHANGELOG.md, commits, pushes, and opens (or updates) a PR.- Merge the PR — the
auto-tag-on-release-pr-mergeworkflow detects themobile-release/*branch merge and pushes amobile-v<version>tag. - The tag is consumed manually, cross-repo — nothing in OSS
block/buzzbuilds on the tag (OSS CI must not trigger CI in the privatebuzz-releasesrepo — infosec). A human feeds themobile-v<version>tag as thesprout_refinput to the internalbuzz-releasesBuildkite pipeline, which builds and ships iOS to Block Comp Portal (dogfood) and TestFlight (App Store, opt-in). See Internal Releases.
The argument forms below apply to release-desktop, release-relay, and
release-mobile:
| Command | Version | Example |
|---|---|---|
just release-desktop |
Next patch | 0.3.0 → 0.3.1 |
just release-desktop patch |
Next patch | 0.3.0 → 0.3.1 |
just release-desktop 0.4.0 |
Explicit minor | 0.3.1 → 0.4.0 |
just release-desktop 1.0.0 |
Explicit | 1.0.0 |
just bump-desktop-version <version> (desktop lane) updates these files:
| File | Field |
|---|---|
desktop/package.json |
"version" |
desktop/src-tauri/tauri.conf.json |
"version" |
desktop/src-tauri/Cargo.toml |
version (under [package]) |
It also regenerates pnpm-lock.yaml and desktop/src-tauri/Cargo.lock.
just bump-relay-version <version> (relay lane) updates
crates/buzz-relay/Cargo.toml (version under [package]) and regenerates the
workspace Cargo.lock.
just bump-mobile-version <version> (mobile lane) updates
mobile/pubspec.yaml (version:, preserving the +build number) and
regenerates mobile/pubspec.lock.
If the automated flow isn't suitable (e.g., building from a non-main ref):
- Go to Actions > Release in the GitHub UI
- Click Run workflow
- Provide the semver version (no
vprefix) and the ref to build from
After the OSS release ships, trigger an internal build via the sprout-releases Buildkite pipeline. See the buzz-releases README for the full step-by-step instructions and input field reference.
Each release produces two GitHub releases:
-
v<version>— the user-facing release with the.dmginstaller (macOS). -
buzz-desktop-latest— a rolling pre-release for the Tauri auto-updater containinglatest.jsonand each platform's signed updater artifact plus its.sigsignature (.tar.gzon macOS,.AppImageon Linux, and_alpha-unsigned.exeon Windows).
The release workflow builds two separate macOS DMGs — Apple
Silicon (darwin-aarch64, the release job) and Intel
(darwin-x86_64, the release-macos-x64 job) — plus Linux .deb and
.AppImage. Both macOS DMGs are codesigned, notarized, and attached to
the same v<version> release. Intel users download the _x64.dmg.
The Linux AppImage is post-processed by desktop/scripts/fix-appimage.sh,
which strips infra libraries over-bundled by linuxdeploy (they crash on
Mesa 25+ / GLib 2.88 distros — see
tauri-apps/tauri#15665)
and re-signs the artifact. As a result the AppImage relies on the
host's Wayland/GStreamer/graphics stack and requires GLib >= 2.72
(Ubuntu 22.04 or newer). The release-linux job builds inside a
ubuntu:22.04 container for broad GLIBC compatibility.
-
Write access to the
block/buzzGitHub repository -
ghCLI authenticated (gh auth status) -
The following GitHub Actions secrets must be configured:
Secret Purpose BUZZ_UPDATER_PUBLIC_KEYTauri updater public key (minisign) TAURI_SIGNING_PRIVATE_KEYTauri updater private key TAURI_SIGNING_PRIVATE_KEY_PASSWORDPassword for the private key
Switch to main and pull latest before running the release recipe.
Commit or stash your changes before running the release recipe.
Re-run the release recipe (just release-desktop, just release-relay, or just release-mobile) from an up-to-date main. It resets the branch to current main, regenerates the changelog and PR body to include the new commits, and force-pushes the updated branch.
The version string must be valid semver: MAJOR.MINOR.PATCH with an optional pre-release suffix. Do not include a v prefix.
Verify that the buzz-desktop-latest release exists and contains a
valid latest.json. The manifest covers all four platform keys
(darwin-aarch64, darwin-x86_64, linux-x86_64,
windows-x86_64); a missing entry usually means that platform's
release job failed — check the workflow run.