Skip to content

Distribute via Homebrew; migrate release to GoReleaser#12

Merged
chenchaoyi merged 1 commit into
masterfrom
claude/homebrew-goreleaser
Jun 24, 2026
Merged

Distribute via Homebrew; migrate release to GoReleaser#12
chenchaoyi merged 1 commit into
masterfrom
claude/homebrew-goreleaser

Conversation

@chenchaoyi

Copy link
Copy Markdown
Owner

What

Adds Homebrew as an install channel for hammer and migrates the release
pipeline to GoReleaser — without disturbing the existing curl | sh
installer or the built-in hammer update.

brew install chenchaoyi/tap/hammer
# or: brew tap chenchaoyi/tap && brew install hammer

Backward compatibility (the hard constraint)

GoReleaser is configured to produce byte-compatible release assets, so the
curl installer and self-updater keep working untouched:

Asset Before After
archive hammer-<os>-<arch>.tar.gz / .zip same
checksums SHA256SUMS (sha256sum format, incl. install.sh) same
binary inside archive hammer / hammer.exe same
installer install.sh attached to release same

Verified with a local goreleaser release --snapshot: all five targets archive
to the exact prior names, SHA256SUMS matches the expected format, and the
tarball contains a hammer binary (which install.sh and hammer update's
isHammerBinary both accept).

Homebrew specifics

  • GoReleaser deprecated brews (formulae) → uses homebrew_casks. Casks are
    macOS-only, which is no regression: Linux already uses curl / hammer update.
  • The cask strips the Gatekeeper quarantine bit post-install (binaries are unsigned).
  • On a v* tag, GoReleaser regenerates the cask in
    chenchaoyi/homebrew-tap.

Workflow

  • v* tag push → real release + tap update
  • workflow_dispatch → snapshot dry-run (artifacts only), for validation

Prerequisite before the next release

Cross-repo push needs a PAT: add a classic PAT (repo scope) as the
HOMEBREW_TAP_TOKEN secret in this repo. Documented in the follow-up.

Tests

TestReleaseWorkflowPublishesInstaller updated to assert install.sh publishing +
stable asset names via .goreleaser.yaml and that the workflow runs goreleaser.
go test -race ./..., goreleaser check, gofmt all clean.

🤖 Generated with Claude Code

Adds a Homebrew install channel (`brew install chenchaoyi/tap/hammer`) without
disturbing the existing `curl | sh` installer or `hammer update`.

The release pipeline moves from the hand-rolled workflow to GoReleaser, which
cross-compiles the same five targets, archives them, emits SHA256SUMS, attaches
install.sh, and on a version tag regenerates the Homebrew cask in
chenchaoyi/homebrew-tap. Asset names are engineered to be byte-compatible with
the old workflow:

- hammer-<os>-<arch>.tar.gz / .zip   (unchanged)
- SHA256SUMS in sha256sum format      (unchanged; still includes install.sh)
- binary named `hammer` inside        (install.sh + updater both accept it)

so the curl installer and the self-updater keep working untouched.

GoReleaser deprecated `brews` (formulae) in favor of `homebrew_casks`, so the
binary ships as a cask. Casks are macOS-only in Homebrew, which is no regression:
Linux users already use the curl installer / `hammer update`. The cask strips
the Gatekeeper quarantine bit post-install since the binaries are unsigned.

workflow_dispatch now runs a snapshot dry-run (artifacts only); real releases
are cut by pushing a `v*` tag. Pushing the cask to the tap needs a PAT in the
HOMEBREW_TAP_TOKEN secret (the default GITHUB_TOKEN can't write to another repo).

TestReleaseWorkflowPublishesInstaller now asserts the installer + stable asset
names via .goreleaser.yaml and that the workflow invokes goreleaser.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@chenchaoyi chenchaoyi merged commit 6056e96 into master Jun 24, 2026
1 check passed
@chenchaoyi chenchaoyi deleted the claude/homebrew-goreleaser branch June 24, 2026 10:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant