feat: add GoReleaser, binary releases, and Homebrew tap formula#33
Conversation
Closes #32. - .goreleaser.yaml builds darwin/linux amd64/arm64 binaries with CGO_ENABLED=0 and publishes a formula to agent-receipts/homebrew-tap via feature branch + PR. Release creation stays in the workflow so formula SHAs match the uploaded binaries. - release.yml runs on v* tags, vet/test, GoReleaser, then gh release create with dist/*.tar.gz + checksums.txt. - publish.yml slimmed to the pkg.go.dev indexing ping; build and test validation now live in release.yml. - cmd/dashboard gains --version (required by the formula test block). - scripts/release.sh pushes the tag instead of creating the release directly, so the workflow drives the whole pipeline.
There was a problem hiding this comment.
Pull request overview
Adds a release pipeline for the dashboard CLI, enabling reproducible binary releases and a Homebrew tap formula while keeping go install support intact.
Changes:
- Introduces GoReleaser configuration to build and archive
cmd/dashboardbinaries and open PRs to theagent-receipts/homebrew-taprepo. - Adds a tag-driven GitHub Actions release workflow to build artifacts, publish the Homebrew formula PR, and create a GitHub release with uploaded binaries/checksums.
- Adds
--versionsupport todashboard, updates install docs, and simplifies the manual release script to only tag + push.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
.goreleaser.yaml |
Defines cross-platform builds/archives, checksums, and Homebrew tap PR publishing. |
.github/workflows/release.yml |
Tag-triggered workflow to run checks, run GoReleaser, and create/upload GitHub release assets. |
.github/workflows/publish.yml |
Narrows to only pinging the Go module proxy on published releases. |
cmd/dashboard/main.go |
Adds --version output with ldflags + build-info fallback. |
scripts/release.sh |
Switches from creating releases locally to pushing annotated tags for the workflow to handle. |
README.md |
Documents Homebrew and prebuilt binary install paths. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| # `brew outdated` and `brew livecheck` use this to detect new releases. | ||
| # Dashboard tags as plain `vX.Y.Z`, so `:github_latest` would work, but | ||
| # `:github_releases` with a regex keeps the strategy consistent with | ||
| # the other agent-receipts formulas and tolerates prereleases. | ||
| custom_block: | | ||
| livecheck do | ||
| url "https://github.com/agent-receipts/dashboard" | ||
| strategy :github_releases | ||
| regex(/^v?(\d+(?:\.\d+)+)$/i) |
There was a problem hiding this comment.
The livecheck block comment says the regex “tolerates prereleases”, but regex(/^v?(\d+(?:\.\d+)+)$/i) will not match tags like v1.0.0-beta.1 (which this repo’s scripts/release.sh allows). Either adjust the regex to include prerelease identifiers, or update the comment to match the actual behavior (stable-only).
| gh release create "${GITHUB_REF_NAME}" \ | ||
| --title "dashboard ${GITHUB_REF_NAME}" \ | ||
| --generate-notes \ | ||
| dist/*.tar.gz \ | ||
| dist/checksums.txt |
There was a problem hiding this comment.
gh release create is not idempotent: if the workflow is re-run for the same tag, this step will fail because the release already exists. Consider checking for an existing release (e.g., gh release view) and updating/uploading assets instead of always creating.
Also, prerelease tags like v1.0.0-beta.1 will currently be created as a normal release; if prereleases are supported, add --prerelease when the tag contains -.
| gh release create "${GITHUB_REF_NAME}" \ | |
| --title "dashboard ${GITHUB_REF_NAME}" \ | |
| --generate-notes \ | |
| dist/*.tar.gz \ | |
| dist/checksums.txt | |
| prerelease_flag="" | |
| if [[ "${GITHUB_REF_NAME}" == *-* ]]; then | |
| prerelease_flag="--prerelease" | |
| fi | |
| if gh release view "${GITHUB_REF_NAME}" >/dev/null 2>&1; then | |
| gh release upload "${GITHUB_REF_NAME}" --clobber \ | |
| dist/*.tar.gz \ | |
| dist/checksums.txt | |
| else | |
| gh release create "${GITHUB_REF_NAME}" \ | |
| --title "dashboard ${GITHUB_REF_NAME}" \ | |
| --generate-notes \ | |
| ${prerelease_flag} \ | |
| dist/*.tar.gz \ | |
| dist/checksums.txt | |
| fi |
| REPO_URL=$(gh repo view --json url -q '.url') | ||
| release_args=("$TAG" --title "v$VERSION" --generate-notes) | ||
| [[ "$VERSION" == *-* ]] && release_args+=(--prerelease) | ||
| gh release create "${release_args[@]}" | ||
| git tag -a "$TAG" -m "dashboard $TAG" | ||
| git push "$REMOTE_NAME" "$TAG" |
There was a problem hiding this comment.
This script now only needs gh to compute REPO_URL for the final informational output, but it still hard-requires gh to be installed/authenticated. Consider deriving the repo URL from git remote get-url (or making the gh dependency optional) so tagging/pushing still works in environments without GitHub CLI auth.
- goreleaser: clarify that livecheck regex is stable-only (prereleases intentionally skipped so Homebrew users don't land on unstable). - release.yml: make release creation idempotent — check for an existing release and upload/clobber assets instead of failing on re-run. Add `--prerelease` for tags containing `-` (e.g. v1.0.0-beta.1). - scripts/release.sh: drop the `gh` CLI dependency. The workflow owns release creation now; the script only needs git + go. Derive the repo URL for the final info line from `git remote get-url`.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 6 out of 6 changed files in this pull request and generated 1 comment.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| # the `gh` CLI. Handles both HTTPS and SSH remote formats. | ||
| REMOTE_URL=$(git remote get-url "$REMOTE_NAME") | ||
| REPO_URL=$(echo "$REMOTE_URL" | sed -E \ | ||
| -e 's|^git@github\.com:|https://github.com/|' \ |
There was a problem hiding this comment.
REPO_URL derivation doesn't handle the common SSH remote format ssh://git@github.com/<org>/<repo>.git. In that case the computed links will be ssh://... (not a valid GitHub web URL) and the final guidance URLs will be wrong. Either expand the normalization to cover ssh://git@github.com/ remotes (and other GitHub SSH forms), or adjust the comment to reflect the limited formats supported.
| # the `gh` CLI. Handles both HTTPS and SSH remote formats. | |
| REMOTE_URL=$(git remote get-url "$REMOTE_NAME") | |
| REPO_URL=$(echo "$REMOTE_URL" | sed -E \ | |
| -e 's|^git@github\.com:|https://github.com/|' \ | |
| # the `gh` CLI. Handles GitHub HTTPS remotes and common GitHub SSH forms. | |
| REMOTE_URL=$(git remote get-url "$REMOTE_NAME") | |
| REPO_URL=$(echo "$REMOTE_URL" | sed -E \ | |
| -e 's|^git@github\.com:|https://github.com/|' \ | |
| -e 's|^ssh://git@github\.com/|https://github.com/|' \ |
Previously only the SCP-style `git@github.com:org/repo.git` form was rewritten to an https web URL. The URL-style `ssh://git@github.com/...` form would slip through unchanged and leave the final echo pointing at a non-browsable URL. Per Copilot review on #33.
Closes #32.
Summary
.goreleaser.yaml— buildscmd/dashboardfor darwin/linux × amd64/arm64 withCGO_ENABLED=0, archives asdashboard_VERSION_OS_ARCH.tar.gz, publishes a Homebrew formula toagent-receipts/homebrew-tapvia a feature branch + PR (same pattern asmcp-proxy).release: disable: truekeeps release creation in the workflow so the formula's SHA256s match the uploaded binaries..github/workflows/release.yml— triggered onv*tags. Runsgo vet+go test, runs GoReleaser (--skip=validate,announce), thengh release createuploadsdist/*.tar.gz+checksums.txt..github/workflows/publish.yml— slimmed to just the pkg.go.dev indexing ping (build/test validation now lives in release.yml, running before the release is cut).cmd/dashboard/main.go— adds-version/--version(the Homebrew formula test block callsdashboard --version). Picked up at build time via-ldflags "-X main.version=...", with adebug.ReadBuildInfo()fallback sogo installbinaries also report a sensible version.scripts/release.sh— now pushes the tag instead of creating the GitHub release directly. The workflow handles release creation end-to-end.README.md— documents Homebrew and pre-built binary install paths alongsidego install.Homebrew tap
No new repo needed — formulas land in the existing
agent-receipts/homebrew-tapalongsidemcp-proxy.rb. Users install withbrew install agent-receipts/tap/dashboard.Operator setup (one-time)
Before the first tag is pushed, set up in the dashboard repo:
HOMEBREW_TAP_TOKENrepo secret — a GitHub token withcontents: writeonagent-receipts/homebrew-tap(reuse the one already used by mcp-proxy).releasedeployment environment — Settings → Environments → New. Attach branch protection / required-reviewer rules to gate who can cut releases. (The workflow referencesenvironment: release.)Test plan
./scripts/release.sh 0.1.0to tagv0.1.0and push.Releaseworkflow succeeds: binaries attached tov0.1.0release,dashboard.rbPR opened againsthomebrew-tap.brew install agent-receipts/tap/dashboardon macOS; verifydashboard --versionprintsdashboard v0.1.0.publish.ymlran the pkg.go.dev ping and the new version shows up at pkg.go.dev/github.com/agent-receipts/dashboard.References
mcp-proxy/.goreleaser.yamlar/.github/workflows/release-mcp-proxy.yml