| Channel | Mechanism | Automatic? |
|---|---|---|
| GitHub Release | GoReleaser via release.yml on tag push |
Yes |
| GitHub draft prerelease | GoReleaser via rc-release.yml on RC tag push or manual dispatch |
Yes |
Homebrew tap (gastownhall/gascity) |
release.yml writes an asset-based formula after archives upload |
Yes |
Homebrew core (Homebrew/homebrew-core) |
BrewTestBot autobump, once listed | Yes (~3h delay) |
The homebrew-core submission is in progress. Until it lands and is added to the autobump list, users install via brew install gascity.
./scripts/bump-version.sh X.Y.Z --commit --tag --pushThis rewrites the [Unreleased] section of CHANGELOG.md into [X.Y.Z] - YYYY-MM-DD, commits, tags vX.Y.Z, and pushes. GitHub Actions takes it from there.
Use the RC Release workflow to produce downloadable release-candidate archives for manual verification without updating Homebrew or publishing the stable release.
Recommended path:
- Run the RC gate on the intended release branch or commit.
- Open Actions → RC Release → Run workflow.
- Set
tag_nameto an RC tag such asv1.2.0-rc1. - Set
target_refto the exact RC-gate-passing commit SHA.
The workflow creates the annotated RC tag if needed, builds GoReleaser archives for linux/darwin × amd64/arm64, and creates a GitHub draft prerelease with generated GoReleaser notes and downloadable assets. It does not update the Homebrew tap, create attestations, or mark the release latest.
Tag creation on the dispatch path uses the gastownhall-release-tagger
GitHub App (an Integration bypass actor on the "Protect release tags"
ruleset), minted per-run from the RELEASE_TAGGER_APP_ID /
RELEASE_TAGGER_APP_PRIVATE_KEY repository secrets — the workflow's default
GITHUB_TOKEN is deliberately NOT a bypass actor, so arbitrary workflows
cannot create, move, or delete v* tags. The tagger token is minted only
when the dispatch must create a new tag; re-dispatching an already-existing
RC tag re-drafts it without the tagger secrets. If the app secrets are missing
on a create dispatch, the workflow fails with instructions instead of a bare
GH013; the manual-tag path below always works for members of the
release-maintainers bypass team.
Because the tagger App token is a bypass actor, pushing the newly created tag
re-fires rc-release.yml on that tag push. To avoid drafting the same RC
twice, a dispatch that creates the tag stops after pushing it, and the
resulting tag-push run is the one that builds the GoReleaser draft. A dispatch
for a tag that already exists — and every direct tag push — goes straight to
the draft build.
You can also push an existing RC tag manually:
git tag -a vX.Y.Z-rcN <commit> -m "Release vX.Y.Z-rcN"
git push origin vX.Y.Z-rcNPushing an RC tag triggers rc-release.yml. The stable release.yml jobs
skip tags containing a prerelease suffix, so RC tags do not run the Homebrew
or stable publishing path.
If you want to do the steps by hand:
- Edit
CHANGELOG.md: move[Unreleased]contents under a new## [X.Y.Z] - YYYY-MM-DDsection. - Commit:
git add CHANGELOG.md git commit -m "chore: release vX.Y.Z" - Tag and push:
git tag -a vX.Y.Z -m "Release vX.Y.Z" git push origin HEAD git push origin vX.Y.Z
Version numbers live only in the git tag — there is no Version constant in Go source to keep in sync. cmd/gc/cmd_version.go has var version = "dev" that the Makefile and .goreleaser.yml inject at build time via -X main.version=$(VERSION).
.github/workflows/release.yml fires on stable vMAJOR.MINOR.PATCH tags and
runs, in order:
- Reject
replacedirectives ingo.mod— they breakgo install ...@latestand bottle builds in homebrew-core. make check-version-tag— asserts the tag is a cleanvMAJOR.MINOR.PATCHwith no pre-release suffix. RC/beta tags are handled byrc-release.ymlinstead.- GoReleaser — builds binaries for linux/darwin × amd64/arm64 and creates the GitHub Release with grouped changelog (
feat:→ Features,fix:→ Bug Fixes, others → Others). - Release attestations — downloads the published checksum manifest, uploads an SPDX SBOM asset, and creates GitHub artifact attestations for the release archives.
- Homebrew tap update — downloads the published checksums and writes an asset-based formula to
gastownhall/homebrew-gascity.
Forks skip publish/announce steps automatically via the --skip=publish --skip=announce flag (the workflow checks github.repository != 'gastownhall/gascity').
make check-version-tag # no-op unless HEAD is a release tag
grep '^replace' go.mod # should print nothing
goreleaser check # also enforced by CIThe release workflow automatically overwrites Formula/gascity.rb in the gastownhall/homebrew-gascity repo on every tag push. Publishing is GitHub App only: HOMEBREW_TAP_APP_ID and HOMEBREW_TAP_APP_PRIVATE_KEY must be configured in repository secrets for an app installed on gastownhall/homebrew-gascity with contents write.
The tap formula installs prebuilt release assets, so users do not need Go or a source build:
brew install gascityThe intended long-term user-facing Homebrew path is homebrew-core:
brew install gascityUntil the core formula lands, the tap is the public install path. After core lands, keep the tap available for emergency updates while normal releases flow through homebrew-core.
Once the formula is merged to Homebrew/homebrew-core and added to the autobump list, the flow becomes:
- Tag push → GoReleaser creates GitHub Release (as today).
- BrewTestBot polls releases every ~3h, opens a PR to homebrew-core bumping the formula's
urlandsha256. - Homebrew maintainers merge; bottles are built for macOS (arm64 + x86_64) and Linux.
brew upgrade gascitypicks up the new version worldwide.
Manual brew bump-formula-pr is refused for autobump formulae. If the bot stalls, check https://github.com/Homebrew/homebrew-core/pulls?q=gascity for stuck PRs.
| File | What changes | Updated by |
|---|---|---|
CHANGELOG.md |
[Unreleased] → [X.Y.Z] - DATE |
scripts/bump-version.sh |
Git tag vX.Y.Z |
Created and pushed | scripts/bump-version.sh |
| GitHub Release page | Created with binaries + grouped changelog | GoReleaser in release.yml |
| Release SBOM + attestations | SPDX SBOM uploaded and release archives attested | attest-release in release.yml |
gastownhall/homebrew-gascity/Formula/gascity.rb |
asset URLs + sha256 updated |
update-homebrew-formula in release.yml |
This is expected. Tags with suffixes such as -rc1, -beta, or -alpha.1
are intentionally excluded from the stable release.yml publishing jobs. Use
the RC Release workflow for release candidates.
go.mod contains a replace directive. These break go install ...@latest and homebrew-core bottle builds. Remove the directive and commit before tagging.
Check .github/workflows/release.yml still matches tags: v*. Verify the tag was pushed to origin (git ls-remote origin refs/tags/vX.Y.Z).
Check the Homebrew tap GitHub App credentials in repo secrets: HOMEBREW_TAP_APP_ID and HOMEBREW_TAP_APP_PRIVATE_KEY. The app must be installed on gastownhall/homebrew-gascity with contents write. The workflow intentionally fails instead of falling back to a long-lived token.
While on the tap: a tag push updates the tap directly; users pick it up on the next brew update && brew upgrade gascity. If the formula wasn't updated, see above.
After homebrew-core lands: the autobump bot runs every ~3h. After ~6h without a PR, check https://github.com/Homebrew/homebrew-core/pulls?q=gascity.