Skip to content

build: release with goreleaser, a Homebrew tap, and a Nix flake - #3

Merged
Arnonrgo merged 2 commits into
masterfrom
feat/goreleaser-homebrew-nix
Sep 8, 2026
Merged

build: release with goreleaser, a Homebrew tap, and a Nix flake#3
Arnonrgo merged 2 commits into
masterfrom
feat/goreleaser-homebrew-nix

Conversation

@Arnonrgo

@Arnonrgo Arnonrgo commented Sep 8, 2026

Copy link
Copy Markdown
Collaborator

Why

v0.8.0 tagged but never shipped anything installable:

  • The release matrix needed a macOS runner for the darwin targets, which never got scheduled, so those assets were never published.
  • The checksums that were published recorded dist/-prefixed paths. Where the assets actually get downloaded, sha256sum -c checksums.txt printed three No such file or directory lines — and exited 0. A verification step that always passes is worse than none.
  • There was no brew or nix install path at all.

What changed

goreleaser replaces the hand-rolled matrix (.goreleaser.yaml, release.yml). Everything cross-compiles from one ubuntu-latest runner.

This also restores the Intel macOS build that da665a3 dropped. That commit's stated reason — "darwin builds require CGO (macOS Keychain), so they can't be cross-compiled" — is not the case: zalando/go-keyring's darwin backend shells out to /usr/bin/security via os/exec and contains no cgo. Verified empirically, not by reading: a CGO_ENABLED=0 binary did a real keychain set/get/delete round-trip, and otool -L on it lists only libSystem and libresolv.

A Homebrew cask goes to mondaycom/homebrew-tap (repo created, README in place, Casks/ populated by the first release).

  • homebrew-core is out of reach for now — it requires notability the repo doesn't have (~75 stars / 30 forks; we're at 1 / 0). A custom tap costs users one extra path segment and nothing else.
  • Cask rather than formula: goreleaser deprecated brews in favour of homebrew_casks, on the grounds that what it generated for pre-compiled binaries were "hackyish" formulas.
  • The cask strips com.apple.quarantine in a postflight hook. These binaries are neither signed nor notarized, and Homebrew quarantines cask downloads, so without it macOS reports "mcli is damaged and cannot be opened" on first run. The real fix is an Apple Developer signing identity plus notarization — worth doing later, out of scope here.

A Nix flake (flake.nix) gives nix profile install github:mondaycom/mcli plus a pinned dev shell, without waiting on nixpkgs' review cadence. mcli is unclaimed there and remains an option later.

Tarballs are new. The bare mcli-<os>-<arch> assets keep the names v0.8.0 used, so existing curl -LO instructions still resolve.

CI gains two jobs. packaging runs goreleaser check and a full snapshot build, so a deprecated property fails a PR instead of a tag push. nix builds the flake to guard vendorHash — it goes stale whenever go.mod/go.sum changes, and nothing else would catch it, since the Go build is unaffected and the flake would stay broken until a user ran nix run. Action versions bumped to current majors along the way.

Verification

Run locally, not assumed:

  • goreleaser check clean; goreleaser build --snapshot produced all 4 targets and 8 assets.
  • shasum -a 256 dist/mcli_darwin_arm64_v8.0/mcli matches its checksums.txt entry. Flat names verify with exit 0; a tampered file gives FAILED and exit 1 — the bug this PR fixes.
  • Generated cask carries the on_macos/on_linux × on_arm/on_intel blocks and the postflight hook.
  • nix build / nix run / nix develop all work; the sandbox ran all 9 test packages green.
  • make build, go vet, golangci-lint (0 issues), make test all pass.

Before the next tag

HOMEBREW_TAP_TOKEN has to exist as an Actions secret — a PAT with contents: write on mondaycom/homebrew-tap. The per-run GITHUB_TOKEN is scoped to this repository and can't push to another one. Without it the release step fails at the cask stage. (This is a GitHub PAT, not a monday API token.)

Homebrew casks are macOS-only in practice; Linux users get Nix, go install, or the tarballs.

🤖 Generated with Claude Code

Arnonrgo and others added 2 commits September 8, 2026 20:32
The v0.8.0 release never produced usable artifacts. Its matrix needed a
macOS runner for the darwin targets, which queued indefinitely, and the
checksums it did publish recorded `dist/`-prefixed paths that matched
nothing where the assets are actually downloaded -- `sha256sum -c` printed
three "No such file or directory" lines and still exited 0.

Replace the hand-rolled matrix with goreleaser on a single Linux runner.
Nothing in the build needs cgo: the darwin keychain backend shells out to
/usr/bin/security via os/exec, verified with a set/get/delete round-trip
from a CGO_ENABLED=0 binary whose `otool -L` lists only libSystem and
libresolv. So every target cross-compiles from one runner, which also
restores the Intel macOS build that da665a3 dropped on the mistaken
grounds that darwin requires cgo.

Publish a Homebrew cask to mondaycom/homebrew-tap. homebrew-core is not an
option yet -- it requires notability the repo does not have -- and
goreleaser deprecated `brews` in favour of `homebrew_casks`, since what it
generated for pre-compiled binaries were "hackyish" formulas. The cask
carries a postflight hook that strips com.apple.quarantine; without it
macOS reports "mcli is damaged and cannot be opened", because these
binaries are neither signed nor notarized.

Tarballs are new; the bare `mcli-<os>-<arch>` binaries keep the names
v0.8.0 used so existing download instructions still resolve.

CI now runs `goreleaser check` and a full snapshot build on every PR, so a
deprecated property fails a pull request instead of a tag push.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Gives Nix and NixOS users a first-class install (`nix profile install
github:mondaycom/mcli`) and contributors a pinned dev shell, without
waiting on a nixpkgs submission -- `mcli` is unclaimed there, but the
package would live outside this repo and land on nixpkgs' review cadence.

`nix build` runs the full test suite in the Nix sandbox, which has no
network. That passes today: no test reaches the API, and the one test that
touches a real keychain is behind the `keychain_real` build tag.

CI builds the flake on every PR to guard vendorHash. It goes stale
whenever go.mod or go.sum changes, and nothing else would catch it -- the
Go build is unaffected, so the flake would stay broken until a user ran
`nix run`.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@Arnonrgo
Arnonrgo merged commit 6ce58bf into master Sep 8, 2026
3 checks passed
@Arnonrgo
Arnonrgo deleted the feat/goreleaser-homebrew-nix branch September 8, 2026 17:37
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