cmux Release
Prefer the /release command. It determines the new version (minor by default), gathers the Changelog line from each PR merged since the last stable tag, updates CHANGELOG.md, runs ./scripts/bump-version.sh, commits, runs ./scripts/release-pretag-guard.sh, then tags and pushes.
Changelog source
Feature PRs don't edit CHANGELOG.md. Each PR description has a ## Changelog section with one user-facing line (Added, Changed, Fixed, or Removed, present tense) or none. At release time, /release step 2 fetches every PR merged since the last v* tag in one GraphQL query and classifies it with references/changelog-lines.jq:
- a Changelog line becomes an entry, with the PR link and
-- thanks @user! for authors and reporters outside the core team (lawrencecchen, austinywang, teamleaderleo) and bots;
none is skipped, and so is a PR undone by a revert later in the range (a reapply leaves it live);
- a revert of a PR that shipped in an earlier release gets its own line and is flagged for the human; reverts within the range are skipped;
- a PR with no section, or a line without an
Added/Changed/Fixed/Removed prefix, is listed for the human to check.
The release then folds any leftover ## Unreleased entries into the new version section and removes that heading.
The docs changelog page at web/app/[locale]/(landing)/docs/changelog/page.tsx renders from CHANGELOG.md, so there is no separate docs changelog source to update.
Version bumping
./scripts/bump-version.sh # minor (0.15.0 -> 0.16.0)
./scripts/bump-version.sh patch # 0.15.0 -> 0.15.1
./scripts/bump-version.sh major # 0.15.0 -> 1.0.0
./scripts/bump-version.sh 1.0.0 # explicit version
This updates MARKETING_VERSION and CURRENT_PROJECT_VERSION. The build number auto-increments and must increase for Sparkle auto-update to work. Bump the minor version unless explicitly asked otherwise.
Tagging
./scripts/release-pretag-guard.sh
git tag vX.Y.Z
git push origin vX.Y.Z
# Use the run ID created by the tag push; the shared waiter observes it without polling GitHub.
glaeda-gh wait run manaflow-ai/cmux/<run-id>
If the pretag guard fails, run ./scripts/bump-version.sh, commit the build-number bump, then retry.
Release artifacts and secrets
- The release assets are the universal
cmux-macos.dmg and the thin cmux-macos-arm64.dmg and cmux-macos-x86_64.dmg, each with its own appcast. The README download button and the Homebrew cask point to the universal releases/latest/download/cmux-macos.dmg.
- Installs read
appcast.xml, which scripts/ci/compose_stable_appcast.py builds from all three items so each install moves onto its own architecture in one update. Thin installs then read appcast-arm64.xml or appcast-x86_64.xml from the latest release, so every stable release must publish both, and only the highest version may be marked latest. The local scripts/build-sign-upload.sh builds only the universal DMG and publishes it under both per-arch feeds.
- Signing requires the GitHub secrets
APPLE_CERTIFICATE_BASE64, APPLE_CERTIFICATE_PASSWORD and APPLE_SIGNING_IDENTITY. CI notarization authenticates with the team App Store Connect API key (ASC_API_KEY_ID, ASC_API_ISSUER_ID, ASC_API_KEY_P8_BASE64) through scripts/ci/lib/notary-auth.sh, which decodes the key to a mode-600 temp file that the caller deletes. The local scripts/build-sign-upload.sh still uses an Apple ID and app-specific password.
Detailed reference