Skip to content

feat(release): Homebrew formula automation and manual-dispatch binary builds - #1

Open
trumpyla wants to merge 6 commits into
mainfrom
feat/homebrew-formula-automation
Open

feat(release): Homebrew formula automation and manual-dispatch binary builds#1
trumpyla wants to merge 6 commits into
mainfrom
feat/homebrew-formula-automation

Conversation

@trumpyla

Copy link
Copy Markdown
Member

Summary

  • New scripts/sea/generate-formula.mjs renders Formula/acpx.rb as the single writer of both install paths: platforms with a published single-executable asset pin the immutable release tarball; every other platform installs the npm package with Homebrew's node (std_npm_args).
  • New formula job in release-binaries.yml regenerates the formula after publish — from the release's SHA256SUMS and the npm registry tarball — and opens a PR, replacing the paste-by-hand checksum step. Requires the "Allow GitHub Actions to create and approve pull requests" Actions setting.
  • release-binaries.yml now triggers on workflow_dispatch only: the darwin matrix legs run on premium-billed GitHub-hosted macOS runners, so binaries build when a human dispatches the workflow for a tag. The npm release in release.yml stays automatic on Linux.
  • Fixes the darwin-x64 leg: macos-13 is a retired runner label (the next tag build would have failed); now macos-15-intel.

Validation

  • actionlint clean on the workflow.
  • brew style and brew audit --formula pass on the generated formula (validated in a scratch tap).
  • Generator exercised for both the current 1-asset release and a synthetic 4-platform manifest.
  • Multi-provider adversarial review (CAO: codex/kimi) in flight; findings will be applied on this branch.

🤖 Generated with Claude Code

trumpyla and others added 2 commits July 26, 2026 14:51
…n npm fallback

The formula is now rendered by scripts/sea/generate-formula.mjs, the single
writer of both install paths: platforms with a published single-executable
asset pin its immutable release tarball, and every other platform installs
the npm package with Homebrew's node. A new formula job in
release-binaries.yml regenerates the file after publish — from the release's
SHA256SUMS and the npm registry tarball — and opens a PR, replacing the
paste-by-hand checksum step.

Also fixes the darwin-x64 matrix leg: macos-13 is a retired runner label,
so the next tag would have failed that build; macos-15-intel is the
supported Intel image.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The darwin matrix legs run on GitHub-hosted macOS runners, which bill at a
premium, so the tag-push trigger is removed: binaries are built when a human
dispatches the workflow for a validated tag. The npm release in release.yml
stays automatic on its Linux runner.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings July 26, 2026 21:10

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Adds release automation to keep the Homebrew formula in sync with published release artifacts, and shifts binary builds to an explicit manual dispatch to control macOS runner cost.

Changes:

  • Introduces scripts/sea/generate-formula.mjs to regenerate Formula/acpx.rb from release SHA256SUMS plus the npm tarball checksum.
  • Updates release-binaries.yml to be workflow_dispatch-only, fixes the retired Intel macOS runner label, and adds a formula job that opens a PR with the regenerated formula.
  • Refreshes Formula/acpx.rb to support per-platform binary installs with npm+Homebrew-node fallback elsewhere.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.

File Description
scripts/sea/generate-formula.mjs New generator script that renders the Homebrew formula from release checksums and npm tarball checksum.
Formula/acpx.rb Updated formula content to support binary installs where available and npm fallback where not.
.github/workflows/release-binaries.yml Makes binary builds manual-dispatch only, updates macOS runner label, hardens checksum generation, and adds formula PR automation.
Comments suppressed due to low confidence (1)

scripts/sea/generate-formula.mjs:82

  • releaseBase is hard-coded to github.com/artagon/acpx, but this repo’s release workflow and metadata expect openclaw/acpx (e.g. .github/workflows/release.yml validates package.json against https://github.com/openclaw/acpx). This will generate Homebrew URLs that 404 or point at a different repo than the checksums were downloaded from.
const releaseBase = `https://github.com/artagon/acpx/releases/download/v${version}`;

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +118 to +121
"class Acpx < Formula",
' desc "Headless CLI client for the Agent Client Protocol (ACP)"',
' homepage "https://github.com/artagon/acpx"',
"",
Comment on lines +39 to +56
const version = args.version ?? "";
const npmSha = args["npm-sha256"] ?? "";
const sumsPath = args.sums ?? "";
const outPath = args.out ?? path.join(repoRoot, "Formula", "acpx.rb");

if (!/^\d+\.\d+\.\d+$/.test(version)) {
throw new Error(`--version must be X.Y.Z; received "${version}".`);
}
if (!/^[0-9a-f]{64}$/.test(npmSha)) {
throw new Error(`--npm-sha256 must be 64 hex characters; received "${npmSha}".`);
}

// The four slots Homebrew can address with on_macos/on_linux × on_arm/on_intel.
// A manifest naming any other target fails the run: silently skipping it would
// publish a formula that pretends the platform does not exist.
const SLOTS = ["darwin-arm64", "darwin-x64", "linux-arm64", "linux-x64"];

const shaByTarget = new Map();
Comment thread Formula/acpx.rb
Comment on lines 29 to 33
on_macos do
on_arm do
url "https://github.com/artagon/acpx/releases/download/v0.12.0/acpx-0.12.0-darwin-arm64.tar.gz"
sha256 "823fea276f249b73c9305f0b36299f0af8f8936966208e5b52ef73f6f97e2c58"
end
trumpyla and others added 4 commits July 26, 2026 17:55
…rmula job's invariants

Two findings from the adversarial review of this branch:

- The job-list invariant in test/release-workflow.test.ts did not know about
  the formula job, so the Test job was red on this branch. The test now pins
  the five-job list and asserts the formula job's trust model: no OIDC, no
  dependency installs, checksums only from the immutable release manifest.
- The npm checksum was trust-on-first-use: whatever bytes the registry served
  were pinned into the formula. The formula job now runs gh attestation
  verify against the tarball — the provenance release.yml attests over the
  exact packed tarball before publish — before recording its sha256.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Adversarial-review finding: the formula job held a contents-write token with
a persisted credential while checking out movable main and executing repo
scripts — the exact co-residency the rest of this workflow is built to avoid.

The job is now split on the same line as build/attest: `formula` renders
from the immutable validated tag with read-only permissions and no persisted
credential, syntax-checks the result (bot PRs from GITHUB_TOKEN get no CI),
and uploads it; `formula-pr` holds the write credential but executes no
repository code — it commits only the artifact bytes. The gate now reads
package.json from the tagged commit rather than the dispatch-branch checkout,
the generator refuses duplicate targets in a manifest, and the invariant
tests cover both new jobs.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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.

2 participants