Skip to content

Release rdsh with tagpr and GoReleaser, and report the version from --version - #66

Merged
178inaba merged 7 commits into
mainfrom
feature/64-add-release-pipeline
Aug 30, 2026
Merged

Release rdsh with tagpr and GoReleaser, and report the version from --version#66
178inaba merged 7 commits into
mainfrom
feature/64-add-release-pipeline

Conversation

@178inaba

@178inaba 178inaba commented Aug 30, 2026

Copy link
Copy Markdown
Owner

Why

rdsh installs only with go install, which needs a Go toolchain on the machine. The users and the AI coding agents rdsh is built for do not always have one, so there is nothing to install on a bare macOS or a CI container.

This is the first half of #63: the pipeline that publishes prebuilt binaries. After it, a push to main keeps a tagpr release PR up to date, merging that PR cuts the tag, and the same job then builds six archives into a GitHub Release and writes a cask into 178inaba/homebrew-tap. rdsh --version reports which build you have — a version that means something only once releases exist.

Merging this PR alone publishes nothing: no tag is cut until the release PR is merged.

What

  • rdsh --versioninternal/cmd gets a version var that GoReleaser fills through -ldflags -X. resolveVersion prefers it, falls back to the version the toolchain recorded (go install …@vX.Y.Z's module version, or a VCS-stamped pseudo-version from go build), and reports unknown when there is no build information. cobra prints rdsh version X.Y.Z.
  • .tagprreleaseBranch = main, versionFile = - (no version constant in the repository), vPrefix = true, release = false so GoReleaser owns the GitHub Release. changelog is left at its default, which gives the release PR a CHANGELOG.md diff.
  • .goreleaser.yamlCGO_ENABLED=0, darwin/linux/windows × amd64/arm64, zip on Windows, checksums.txt, and a Homebrew cask pushed to the shared tap.
  • .github/workflows/release.yml — tagpr and GoReleaser in one job, the latter gated on steps.tagpr.outputs.tag != ''.
  • .github/workflows/ci.yml — a goreleaser check step in the lint job.
  • README.md — the Install section now lists Homebrew, the Releases archive and go install, in that order.
  • CLAUDE.md.goreleaser.yaml joins the synced surfaces for the one-line description.

skills/rdsh/SKILL.md needs no change: it states no install route and lists no flags, which is what its router-style rule asks for.

Closes #64
Part of #63

Before merging

The Before #64 is merged items under #63's Manual release steps have to be done first — this workflow runs on every push to main and fails at the token step without them:

  1. 178inaba/homebrew-tap exists and has a main branch.
  2. The Daemon Bot App is installed on 178inaba/rdsh and 178inaba/homebrew-tap. Alongside the read & write on contents and pull requests that Distribute prebuilt rdsh binaries through GitHub Releases and Homebrew #63 lists, tagpr's own docs ask for read on issues — worth checking while installing.
  3. APP_ID (repository variable) and APP_PRIVATE_KEY (repository secret) are set on 178inaba/rdsh.

Decisions worth a second look

persist-credentials: false on the checkout step, beyond the fetch-depth: 0 the issue asks for. tagpr skips installing its own token when checkout has already left an http.https://<host>/.extraheader in the git config, so without this its pushes are made with the default GITHUB_TOKEN — and a release PR whose branch GITHUB_TOKEN pushed gets no CI until a maintainer approves it in the merge box, which is exactly what the App is there to avoid. It is also what tagpr's own docs recommend.

Newer action majors than the issue implies: actions/create-github-app-token@v3 and goreleaser/goreleaser-action@v7, following "pin action major versions like ci.yml does". v3 takes client-id and treats app-id as a deprecated alias, so the release log will carry a Use 'client-id' instead. notice on every run. Moving to client-id would mean registering the App's Client ID as a second repository variable, against #63's plan of reusing the existing App and variables, so app-id stays.

-v comes along with --version: cobra registers the shorthand when nothing else claims v, and nothing here does. One more flag on the agent-facing surface, mentioned because that surface is a contract.

setup-go is gated on the tag too. It exists only for the GoReleaser step below it, and most pushes to main merely refresh the release PR.

The release job does not wait for CI on the merge commit. That commit was already tested on the release PR itself; the workflow says so in a comment.

Values a sibling CLI would have to change are kept to a minimum, per #63's rule that cflio and slio copy this configuration. release.yml reads its owner and repository from the workflow context, and .goreleaser.yaml templates {{ .ProjectName }} and {{ .ModulePath }}, so the only rdsh-specific values left there are the project name, the cask homepage and the description.

How this was checked

Locally, with GoReleaser v2.18.0 (go run github.com/goreleaser/goreleaser/v2@latest):

go test -race ./...                  # passes, including the version fallback table
docker compose run --rm lint         # 0 issues
goreleaser check                     # 1 configuration file(s) validated
goreleaser release --snapshot --clean

The snapshot produces exactly six archives (darwin/linux .tar.gz, windows .zip, each amd64 and arm64) plus checksums.txt, and no 386 artifact. dist/rdsh_darwin_arm64_v8.0/rdsh --version prints rdsh version 0.0.0-SNAPSHOT-<sha>, which is what confirms the templated -X path still resolves; the generated Casks/rdsh.rb carries the right name, desc and quarantine hook. A plain go build binary prints its VCS pseudo-version and rdsh --help lists -v, --version.

What only the merge can show: that the workflow runs on an ordinary push with the GoReleaser step skipped, that the release PR gets CI without approval, and that merging it produces the tag, the Release and Casks/rdsh.rb. The first release PR will also add .github/release.yml, which tagpr generates on its first run.

GoReleaser embeds it with -ldflags -X; a go install or go build binary
falls back to the version the toolchain recorded.
A push to main keeps a release PR up to date; merging it cuts the tag,
and the same job then builds the six archives, the GitHub Release and
the Homebrew cask. CI gains a goreleaser check so a broken config fails
on the PR rather than once the tag is pushed.
go install needs a Go toolchain, which the users and agents rdsh is for
do not always have.
The cask name, the quarantine hook's binary path and the ldflags symbol
each spelled rdsh again; templating them leaves .goreleaser.yaml with
only the values a sibling CLI has to change. release.yml reads its owner
and repository from the workflow context for the same reason, and its Go
setup is now gated like the release step it exists for.

resolveVersion takes the recorded module version rather than the function
that reads it, which makes it a pure function of two strings.
@178inaba 178inaba self-assigned this Aug 30, 2026
@178inaba
178inaba marked this pull request as ready for review August 30, 2026 18:01
@178inaba
178inaba merged commit 12bc41c into main Aug 30, 2026
3 checks passed
@178inaba
178inaba deleted the feature/64-add-release-pipeline branch August 30, 2026 18:42
@daemon-bot daemon-bot Bot mentioned this pull request Aug 30, 2026
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.

Release rdsh with tagpr and GoReleaser: prebuilt binaries, a Homebrew cask, and --version

1 participant