feat(release): make holodeck installable via Homebrew#825
Open
ArangoGutierrez wants to merge 15 commits into
Open
feat(release): make holodeck installable via Homebrew#825ArangoGutierrez wants to merge 15 commits into
ArangoGutierrez wants to merge 15 commits into
Conversation
Land the design for shipping holodeck via Homebrew using GoReleaser, with the formula hosted in NVIDIA/holodeck main branch. - Same-repo tap (Formula/holodeck.rb), custom-URL brew tap form - GoReleaser cross-builds binaries + auto-generates the formula on each tag - GitHub Action triggered on v* tags drives the release - README install section + Makefile snapshot target for local dry-run - Existing make release target removed (replaced by GoReleaser) See docs/superpowers/specs/2026-05-26-holodeck-brew-installable-design.md. Signed-off-by: Carlos Eduardo Arango Gutierrez <eduardoa@nvidia.com>
11 tasks covering: - Task 1: cmd/cli version variable refactor for ldflag injection - Task 2: .goreleaser.yaml config - Task 3: Makefile snapshot target (replaces dead release: target) - Task 4: release.yaml workflow on v* tags - Task 5: homebrew-validate.yaml workflow - Task 6: README Homebrew install section - Task 7: docs/release.md release process doc - Task 8: PR + review + merge - Task 9: PAT setup (manual, one-time) - Task 10: cut v0.3.5 bootstrap release - Task 11: post-release smoke test Resolves the spec's open questions: - Branch protection: PR mode required (signed-commits + 1-reviewer rule) - Version variable: add 'var version = "dev"' at package level - Action pins: @v6 to match existing workflows Spec: docs/superpowers/specs/2026-05-26-holodeck-brew-installable-design.md Signed-off-by: Carlos Eduardo Arango Gutierrez <eduardoa@nvidia.com>
Replace the hardcoded "0.2.18" version string with a package-level `version` variable so GoReleaser can inject the real tag via -ldflags -X main.version=<tag> at build time. Signed-off-by: Carlos Eduardo Arango Gutierrez <eduardoa@nvidia.com>
Cross-builds holodeck CLI for linux/darwin x amd64/arm64 and the action binary for linux x amd64/arm64. Produces tar.gz archives, sha256 checksums, source tarball, and auto-generates a Homebrew formula at Formula/holodeck.rb via PR mode (required because main has branch protection with required signed commits). The PR mode token is read from $HOMEBREW_TAP_GITHUB_TOKEN at release time — see docs/release.md for setup. Signed-off-by: Carlos Eduardo Arango Gutierrez <eduardoa@nvidia.com>
The previous `make release` target cross-built binaries to bin/ but never published them — dead code now that GoReleaser handles the release flow. `make snapshot` is the new local dry-run: runs GoReleaser in --snapshot mode to validate the build matrix and inspect the generated formula before tagging. Signed-off-by: Carlos Eduardo Arango Gutierrez <eduardoa@nvidia.com>
Triggers on `push: tags: v*`. Runs goreleaser release --clean which publishes binaries to the GitHub Release and opens a PR updating Formula/holodeck.rb. Uses the workflow's default GITHUB_TOKEN to publish the release. The formula-bump PR is opened via a separate PAT (HOMEBREW_TAP_GITHUB_TOKEN) — required because the default token cannot open PRs against a protected branch from within the same repo workflow context. See docs/release.md for PAT setup. Signed-off-by: Carlos Eduardo Arango Gutierrez <eduardoa@nvidia.com>
Runs `brew audit --strict --online` and `brew style` against Formula/holodeck.rb on PRs that touch Formula/** and on pushes to main. Path-filtered so it stays dormant until the first formula lands. Catches formula syntax errors before they reach users. Signed-off-by: Carlos Eduardo Arango Gutierrez <eduardoa@nvidia.com>
Documents the `brew tap nvidia/holodeck <url> && brew install` flow. Retains the existing make-build path as 'Install from source' for contributors. The custom-URL tap form is required because the formula lives in NVIDIA/holodeck rather than a dedicated homebrew-* repo. Signed-off-by: Carlos Eduardo Arango Gutierrez <eduardoa@nvidia.com>
Documents the GoReleaser-driven release flow, PAT setup for HOMEBREW_TAP_GITHUB_TOKEN, dry-run via `make snapshot`, tag-and-push ritual, post-release smoke test, and rollback procedure for bad releases. Signed-off-by: Carlos Eduardo Arango Gutierrez <eduardoa@nvidia.com>
GoReleaser's PR-mode commits are server-signed via the GitHub API (satisfying main's required-signed-commits rule), but the commit message had no `Signed-off-by:` trailer. The DCO bot is an independently required status check on NVIDIA/holodeck:main, so without a trailer the auto-opened formula-bump PR would land in 'cannot merge' purgatory. Add a `Signed-off-by:` trailer to the brews `commit_msg_template` attributing the sign-off to the nvidia-ci identity. Update docs/release.md so its explanation of the PAT-vs-default-token rationale also covers DCO (previously claimed signed-commits satisfied DCO, which is wrong). Caught during pre-push principal-engineer review. Signed-off-by: Carlos Eduardo Arango Gutierrez <eduardoa@nvidia.com>
Two follow-ups from the pre-push principal-engineer review: 1. Pre-flight HOMEBREW_TAP_GITHUB_TOKEN check in release.yaml. If the secret is unset (or revoked/expired between rotations), GoReleaser would publish the release successfully and then silently skip the formula-bump PR — leaving users stuck on the previous formula version. Fail fast with a clear error pointing at docs/release.md instead. 2. Pin release.github.owner/name in .goreleaser.yaml. Without it, GoReleaser autodetects owner/repo from the git remote — fine in NVIDIA/holodeck CI, but a fork-foot-gun if a contributor accidentally runs `goreleaser release` (not --snapshot) from their fork checkout. Explicit pin removes the ambiguity. Verified locally: snapshot now produces URLs against NVIDIA/holodeck regardless of the local origin remote. Signed-off-by: Carlos Eduardo Arango Gutierrez <eduardoa@nvidia.com>
Follow-up after rebasing onto upstream/main: upstream already added `const ProgramVersion = "0.3.2"` in cmd/cli/main.go (PR #?). To keep the established naming, the conflict-resolution in the refactor(cli) commit converted ProgramVersion from `const` to `var` (required for ldflag injection) and removed the now-redundant `var version` declaration. This commit updates .goreleaser.yaml to inject into the renamed variable: -X main.version → -X main.ProgramVersion. Verified: snapshot binary prints `holodeck version 0.3.4-SNAPSHOT-<sha>`. Signed-off-by: Carlos Eduardo Arango Gutierrez <eduardoa@nvidia.com>
4e91947 to
6e5fb10
Compare
After rebasing onto upstream/main, three CI checks failed:
1. Unit test `TestNewApp` (cmd/cli/main_test.go) asserted
`app.Version \!= "0.3.2"` — pinning the binary to a literal
constant. That contract is invalid under the new ldflag
injection model (`go test` builds with no ldflag, falling back
to "dev"; release builds inject the tag). Rewrite the assertion
to non-emptiness so the test doesn't need bumping on every tag.
2. `docs/release.md` triggered MD005, MD007, MD029, MD034 violations
(inconsistent indent, bare URLs, ambiguous list ordering).
Rewrite the doc with mdl-friendly structure: prose paragraphs
where lists weren't load-bearing, code fence for the asset
manifest, wrapped URLs in <>, and single-line ordered items.
Content unchanged.
3. `docs/superpowers/{specs,plans}/*.md` triggered many style
violations. These are internal AI-assisted planning artifacts
(work-in-progress authoring docs), not user-facing documentation.
Exclude `docs/superpowers/` from `scripts/mdlint.sh` with a
commented rationale. The exclusion sits alongside the existing
`docs/vendor/` exclusion.
Verified locally:
- `go test ./cmd/cli/ -run TestNewApp` passes
- `make snapshot` succeeds in 8s
Signed-off-by: Carlos Eduardo Arango Gutierrez <eduardoa@nvidia.com>
Coverage Report for CI Build 26458628453Coverage remained the same at 48.745%Details
Uncovered ChangesNo uncovered changes found. Coverage RegressionsNo coverage regressions found. Coverage Stats
💛 - Coveralls |
Round-two mdlint fix: - MD013 line length: wrap all prose to 80 cols - MD029 ordered list item prefix: use '1.' for every numbered step (mdl's :one style — also accepted by :one_or_ordered) - Convert bare URLs to named reference links for readability Signed-off-by: Carlos Eduardo Arango Gutierrez <eduardoa@nvidia.com>
The previous mdlint exclusion only updated scripts/mdlint.sh, but the docs_check.yaml workflow embeds its own `find` command and doesn't call the script. Apply the same docs/superpowers exclusion inline in the workflow so CI matches the script behaviour. Signed-off-by: Carlos Eduardo Arango Gutierrez <eduardoa@nvidia.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Implements
docs/superpowers/specs/2026-05-26-holodeck-brew-installable-design.md.Summary
v*tagshomebrew-validateworkflow (audit + style onFormula/**changes)cmd/cli/main.goto use aversionpackage variable for ldflag injection (fixes stale hardcoded0.2.18)make release(dead code — built binaries tobin/but never published) withmake snapshotfor local dry-runs; addsdist/to.gitignoredocs/release.mdwith the full release process + PAT setupThe first GoReleaser run (triggered by tagging
v0.3.5after this merges) will createFormula/holodeck.rbvia an auto-opened PR.How users will install after v0.3.5
Testing done
goreleaser check→ passes (one non-fatalbrewsdeprecation warning, tracked as follow-up)make snapshot→ produces 6 binary archives + checksums + source + draft formula indist/in ~11sgo build -ldflags "-X main.version=v0.3.5" ./cmd/cli && ./holodeck --version→ printsholodeck version v0.3.5Pre-push hardening (caught during principal-engineer review)
commit_msg_templatein.goreleaser.yamlnow includes aSigned-off-by:trailer so the auto-opened PR can pass the DCO required check.release.yamlfails fast with a clear error ifHOMEBREW_TAP_GITHUB_TOKENis unset (otherwise the release would publish but the formula PR would silently not open).release.githubowner/name pin —.goreleaser.yamlpinsNVIDIA/holodeckso a contributor runninggoreleaser releasefrom a fork checkout doesn't accidentally publish to the wrong repo.Required before tagging v0.3.5
HOMEBREW_TAP_GITHUB_TOKENrepo secret perdocs/release.md→ "One-time setup". Fine-grained PAT scoped toNVIDIA/holodeckwithContents: read/writeandPull requests: read/write. Without it, the new pre-flight check fails the release workflow immediately.Follow-ups (out of scope for this PR)
brews:→homebrew:block when bumping GoReleaser to v3make build, but the Makefile only hasmake build-cli/make build-action(separate small PR)Spec & plan
docs/superpowers/specs/2026-05-26-holodeck-brew-installable-design.mddocs/superpowers/plans/2026-05-26-holodeck-brew-installable.md