Skip to content

feat(release): goreleaser + tag-driven release workflow + install.sh (CLI-MCP-13R2)#18

Merged
mastermanas805 merged 2 commits into
masterfrom
feat/release-workflow-goreleaser
May 29, 2026
Merged

feat(release): goreleaser + tag-driven release workflow + install.sh (CLI-MCP-13R2)#18
mastermanas805 merged 2 commits into
masterfrom
feat/release-workflow-goreleaser

Conversation

@mastermanas805
Copy link
Copy Markdown
Member

Closes CLI-MCP-13R2 (BugBash QA round 2 strategic gap).

Why

Until this PR, the CLI had no release pipeline. `go install` was the only documented install path — it requires a Go toolchain and pins users to whatever HEAD happens to be. Meanwhile every other backend service in instanode.dev auto-builds on push (CLAUDE.md rule 15). The CLI was the odd one out.

What changes

Three coordinated pieces:

`.goreleaser.yml`

  • Cross-compiles darwin / linux × amd64 / arm64 + windows amd64.
  • Binaries are ldflag-stamped with the tag version, short commit SHA, and UTC build time — matches the Makefile's `make build` so `instant --version` keeps the CLAUDE.md rule 14 build-SHA gate workable on release binaries.
  • SBOM (CycloneDX via syft) ships alongside each archive.
  • `checksums.txt` is signed by sigstore cosign via keyless OIDC.

`.github/workflows/release.yml`

  • Fires on `v*..` tag push.
  • Third-party actions are SHA-pinned per CSO supply-chain policy:
    • `goreleaser/goreleaser-action@e435ccd…` (v6.4.0)
    • `sigstore/cosign-installer@398d4b0…` (v3.7.0)
    • `anchore/sbom-action/download-syft@e22c389…` (v0.20.0)
  • First-party `actions/checkout` and `actions/setup-go` use `@v6` to match the rest of the repo (matches `ci.yml`, `coverage.yml`, etc.).
  • `GITHUB_TOKEN` is the per-job repo-scoped token — no long-lived PAT.
  • `id-token: write` granted only at the goreleaser job for sigstore keyless signing.

`install.sh`

  • POSIX `sh` (not bash) so curl-pipe-sh works on Debian/Ubuntu (dash), macOS (bash), Alpine (busybox).
  • Detects OS / arch via `uname`, resolves the latest release via the GitHub API (or honors `INSTANT_VERSION=v0.2.0`).
  • Downloads the matching `.tar.gz`, verifies SHA-256 against the release's signed `checksums.txt`.
  • Installs to `/usr/local/bin` (override via `INSTANT_INSTALL_DIR`). Sudo is requested explicitly only when the target dir isn't writable.
  • Windows users are pointed at the release page `.zip`.
  • shellcheck-clean.

README updated: `curl -sSfL https://instanode.dev/install.sh | sh` is the primary path; `go install` is the fallback.

Verification

  • `goreleaser check` — config valid against GoReleaser v2.16.
  • `goreleaser release --snapshot --skip=sign,sbom,publish` — all 5 archives build clean (darwin amd64/arm64, linux amd64/arm64, windows amd64).
  • `bin/instant --version` on the snapshot binary prints `0.0.1-next (4cd4678, …)` — ldflag stamping works end-to-end.
  • `sh -n install.sh` — POSIX syntax OK.
  • `shellcheck install.sh` — zero warnings.
  • `make ci` — green.

Follow-up (not in this PR)

  • Cut `v0.2.0` tag after merge to fire the first release.
  • Wire `https://instanode.dev/install.sh\` to redirect to the raw GitHub script (tracked separately so this PR doesn't block on instanode-web push perms).
  • Homebrew / Scoop / apt taps — when there's signal that one-liner install isn't enough.

🤖 Generated with Claude Code

mastermanas805 and others added 2 commits May 29, 2026 14:12
Closes CLI-MCP-13R2 (BugBash QA round 2 strategic gap): the CLI had no
release pipeline. `go install` was the only documented install path,
which pins users to whatever HEAD happens to be and requires a Go
toolchain. Every other backend service in instanode.dev auto-builds on
push (CLAUDE.md rule 15) — the CLI was the odd one out.

This PR closes the gap with three coordinated pieces:

* `.goreleaser.yml` — cross-compiles darwin/linux × amd64/arm64 + windows
  amd64. Binaries are ldflag-stamped with the tag version, short commit
  SHA, and UTC build time (matches Makefile's `make build` so
  `instant --version` keeps the rule-14 build-SHA gate workable on
  release binaries). SBOM (CycloneDX via syft) ships alongside each
  archive; checksums.txt is signed by sigstore cosign via keyless OIDC.

* `.github/workflows/release.yml` — fires on `v*.*.*` tag push, runs
  goreleaser, signs, publishes to the GitHub Release page. Third-party
  actions are SHA-pinned per CSO supply-chain policy
  (goreleaser-action / cosign-installer / sbom-action); first-party
  `actions/checkout` and `actions/setup-go` use `@v6` to match the
  rest of the repo. `GITHUB_TOKEN` is the per-job repo-scoped token —
  no long-lived PAT.

* `install.sh` — POSIX sh (not bash) so curl-pipe-sh runs on
  Debian/Ubuntu (dash), macOS (bash), Alpine (busybox) without
  surprises. Detects OS/arch via uname, resolves latest release via
  GitHub API (or honors `INSTANT_VERSION=v0.2.0`), downloads the
  matching tar.gz, verifies SHA-256 against the release's
  `checksums.txt`, and installs to `/usr/local/bin` (override via
  `INSTANT_INSTALL_DIR`). Sudo is requested explicitly only when the
  target dir isn't writable. Windows users are pointed at the release
  page `.zip`. shellcheck-clean.

README updated: `curl -sSfL https://instanode.dev/install.sh | sh` is
the primary path; `go install` is the fallback.

Verification (local):

  goreleaser check         — config valid against GoReleaser v2.16
  goreleaser release --snapshot --skip=sign,sbom,publish
                           — all 5 archives build clean
  sh -n install.sh         — POSIX syntax OK
  shellcheck install.sh    — zero warnings
  make ci                  — green
  bin/instant --version    — `0.0.1-next (4cd4678, …)`
                             confirms ldflag stamping works end-to-end

Follow-up (not in this PR):

* Cut `v0.2.0` tag after merge to fire the first release.
* Wire `https://instanode.dev/install.sh` to redirect to the raw
  GitHub script. Tracked separately so this PR doesn't block on
  instanode-web push permissions.
* Homebrew / Scoop / apt taps — when there's signal that one-liner
  install isn't enough.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@mastermanas805 mastermanas805 merged commit 6b73802 into master May 29, 2026
10 checks passed
@mastermanas805 mastermanas805 deleted the feat/release-workflow-goreleaser branch May 29, 2026 08:46
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