Skip to content

Hand off Homebrew to a hand-maintained source-built formula in the tap - #26

Merged
kevdoran merged 3 commits into
mainfrom
brew-formula
Jul 4, 2026
Merged

Hand off Homebrew to a hand-maintained source-built formula in the tap#26
kevdoran merged 3 commits into
mainfrom
brew-formula

Conversation

@kevdoran

@kevdoran kevdoran commented Jun 23, 2026

Copy link
Copy Markdown
Owner

Closes #21

Why this changed direction

The earlier version of this PR distributed pj via GoReleaser's brews: (formula) key. That key was deprecated in GoReleaser v2.10 and removed in v2.16, and our release workflow floats GoReleaser to ~> v2, so the next release that picked up v2.16+ would fail to parse .goreleaser.yaml. GoReleaser can now only emit binary homebrew_casks — it cannot generate a build-from-source formula at all.

Per maintainer decision, GoReleaser no longer manages Homebrew. The Homebrew formula will be hand-maintained, build-from-source, in the separate kevdoran/homebrew-tap repo. This PR makes this repo consistent with that decision and hands over everything needed for the tap.

What changed in this repo

  • .goreleaser.yaml — removed the Homebrew block entirely (the brews: block this PR previously introduced) and replaced it with a comment explaining why Homebrew is no longer GoReleaser-managed. Builds, archives, notarize, checksum, and changelog are untouched — the release still produces the binaries/archives used by the "Binary download" install method.
  • .github/workflows/release.ymlHOMEBREW_TAP_TOKEN was only ever passed to the (now-removed) GoReleaser Homebrew step, so it is no longer consumed. Removed it from the GoReleaser step's env and left a comment noting the secret is retained in repo settings for any future tap automation. The rest of the workflow is unchanged.
  • docs/install.md — Homebrew section uses the formula form (brew install pj / brew upgrade pj, no --cask); added a note that the formula builds from source with go build (Homebrew pulls in go as a build dependency). The cask→formula migration section is corrected (brew uninstall --cask kevdoran/tap/pj then brew install kevdoran/tap/pj) and notes that a tap_migrations.json in the tap will eventually automate this.
  • README.md / pj-skill.md — already used the formula form; consistent on brew tap kevdoran/tap (which Homebrew expands to kevdoran/homebrew-tap).

go build ./cmd/projector and go vet ./... both pass (packaging/docs change only, no Go code touched).

Follow-up in the tap repo (not editable from here)

Add the build-from-source formula below as Formula/pj.rb in kevdoran/homebrew-tap, plus a tap_migrations.json so existing cask users auto-migrate. Once those land, cask users can simply brew upgrade pj.

Formula/pj.rb (ready to paste)

class Pj < Formula
  desc "Manage parallel projects backed by git worktrees"
  homepage "https://github.com/kevdoran/projector"
  url "https://github.com/kevdoran/projector/archive/refs/tags/v0.5.0.tar.gz"
  sha256 "REPLACE_WITH_SHA256_OF_THE_SOURCE_TARBALL"
  license "Apache-2.0"
  head "https://github.com/kevdoran/projector.git", branch: "main"

  depends_on "go" => :build
  depends_on "git"

  def install
    commit   = Utils.git_short_head(length: 7) rescue "unknown"
    build_date = Time.now.utc.strftime("%Y-%m-%d")
    ldflags = %W[
      -s -w
      -X main.version=#{version}
      -X main.commit=#{commit}
      -X main.buildDate=#{build_date}
    ]
    system "go", "build", *std_go_args(ldflags: ldflags.join(" ")), "./cmd/projector"
  end

  test do
    assert_match version.to_s, shell_output("#{bin}/pj version")
  end
end

Notes:

  • The url / sha256 track the GitHub source tarball for each release tag. Get the checksum with curl -sL <url> | shasum -a 256. (Homebrew's brew bump-formula-pr automates this on subsequent bumps.)
  • std_go_args already sets -o #{bin}/pj and the build mod flags; we only add the version ldflags. The ldflags mirror the repo's Makefile and the (now-removed) .goreleaser.yaml builds block: -X main.version=… -X main.commit=… -X main.buildDate=…, main package ./cmd/projector.
  • The test do block asserts pj version prints the version string.

tap_migrations.json (ready to paste)

{
  "pj": "kevdoran/tap/pj"
}

This maps the old kevdoran/tap/pj cask to the new formula, so Homebrew auto-migrates existing cask installs on the next brew upgrade.

🤖 Generated with Claude Code

kevdoran and others added 2 commits June 22, 2026 20:14
Replace the homebrew_casks block with a GoReleaser v2 brews block so pj
publishes a Homebrew formula (rather than a cask) to kevdoran/homebrew-tap.
The generated formula installs the prebuilt release binary; an explicit
install/test block is included. Docs updated to use the formula install
syntax (brew install pj / brew upgrade pj) and the cask-to-formula
migration steps are activated.

Closes #21

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
GoReleaser removed the `brews` formula key in v2.16 and only
supports binary casks; a build-from-source formula must be
hand-maintained in kevdoran/homebrew-tap. Drop GoReleaser's
Homebrew management and document the formula install + migration.

Closes #21

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@kevdoran kevdoran changed the title Distribute pj as a Homebrew formula instead of a cask Hand off Homebrew to a hand-maintained source-built formula in the tap Jun 23, 2026

@kevdoran kevdoran left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review: LGTM with one merge-sequencing caveat ⚠️ (comment-only — reviewer account is also the PR author, so GitHub disallows a formal approval)

What was verified

  • The rationale is factually correct. Confirmed against goreleaser.com/deprecations: the brews (formula) key was deprecated in v2.10 and removed in v2.16; GoReleaser now only emits binary homebrew_casks and cannot generate a build-from-source formula. Since .github/workflows/release.yml floats on version: "~> v2", any GoReleaser-managed formula approach would break the next tagged release — dropping GoReleaser's Homebrew management entirely is the right call for issue #21's build-from-source intent.
  • .goreleaser.yaml: only the homebrew_casks block removed (with an explanatory comment); builds, archives, notarize, checksum, changelog untouched. Removing a section cannot break v2 parsing. Binary-download installs continue to work from release archives.
  • release.yml: HOMEBREW_TAP_TOKEN was only consumed by the removed GoReleaser Homebrew step; dropping it from env is safe and the comment documents why the repo secret is retained. Workflow otherwise untouched. CI Build + Test are green on this branch.
  • Docs: README + docs/install.md consistently use formula form (brew install pj / brew upgrade pj); the cask→formula migration section is activated and correct (brew uninstall --cask kevdoran/tap/pjbrew install kevdoran/tap/pj); tap shorthand kevdoran/taphomebrew-tap is consistent throughout; "lastest" typo fixed.
  • PR body deliverable: contains a complete ready-to-paste Formula/pj.rb (Apache-2.0 matches the repo LICENSE; depends_on "go" => :build; ldflags mirror the Makefile/goreleaser: -X main.version/commit/buildDate, main pkg ./cmd/projector; test do uses the real pj version subcommand) plus a tap_migrations.json snippet.

⚠️ Merge-sequencing caveat (the one real gotcha)

The docs describe a state that doesn't exist until the tap follow-up lands: today kevdoran/homebrew-tap ships a cask named pj, so a new user following the updated README (brew install pj) will get the old cask or a confusing result. Recommended order:

  1. Add Formula/pj.rb (with a real sha256) and tap_migrations.json to the tap; remove/deprecate the cask.
  2. Then merge this PR (or merge both the same day).

Manual steps before the formula works

  • Fill in the real tarball sha256 per release (curl -sL <url> | shasum -a 256); brew bump-formula-pr automates later bumps.
  • Decide on commit/buildDate for tarball builds: source tarballs have no git metadata, so the formula falls back to "unknown" — either accept that or hardcode per release.
  • Sanity-check in the tap: brew install --build-from-source kevdoran/tap/pj, brew test pj, brew audit --strict pj.

Nothing blocking in this repo's diff itself — ready to merge once the tap sequencing above is planned.

🤖 Generated with Claude Code

Add a homebrew job to the release workflow that computes the new
source tarball's sha256, updates the url and sha256 in
kevdoran/homebrew-tap's Formula/pj.rb using HOMEBREW_TAP_TOKEN, and
pushes the bump. Restores the release automation the GoReleaser cask
block used to provide.
@kevdoran

kevdoran commented Jul 4, 2026

Copy link
Copy Markdown
Owner Author

Follow-up pushed: the release workflow now includes a homebrew job that fully automates formula bumps, restoring the automation the GoReleaser cask block used to provide.

On each tagged release (after the release job succeeds):

  1. Downloads the tag's source tarball and computes its sha256 (fails loudly if the download or hash fails).
  2. Checks out kevdoran/homebrew-tap with HOMEBREW_TAP_TOKEN (the same secret the cask automation used — needs contents: write on the tap).
  3. sed-updates the url tag and sha256 in Formula/pj.rb, then greps to verify both substitutions actually landed (fails loudly if not).
  4. Commits and pushes Brew formula update for projector version vX.Y.Z (skips gracefully if already current, so re-runs are idempotent).

Verified locally: workflow YAML parses, and the exact sed/grep sequence was dry-run against the real Formula/pj.rb from the tap (url and sha both update correctly). The stale "token retained for future automation" comment on the GoReleaser step is updated to point at the new job.

Not verifiable until a real release: the end-to-end run on Actions. Requires kevdoran/homebrew-tap#1 to be merged first (the job edits Formula/pj.rb, which doesn't exist on the tap's main yet).

🤖 Generated with Claude Code

kevdoran added a commit to kevdoran/homebrew-tap that referenced this pull request Jul 4, 2026
The pj formula builds from the release source tarball with go as a
build dependency, replacing the GoReleaser-generated binary cask.
tap_migrations.json migrates existing cask installs automatically.

See kevdoran/projector#21 and kevdoran/projector#26.
@kevdoran
kevdoran merged commit 8977873 into main Jul 4, 2026
2 checks passed
@kevdoran
kevdoran deleted the brew-formula branch July 4, 2026 13:21
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.

Migrate to homebrew formula rather than cask install

1 participant