Skip to content

Add release CI and publish cross-compiled binaries - #17

Merged
arcaputo3 merged 3 commits into
mainfrom
release-ci-v0.1.0
Aug 5, 2026
Merged

Add release CI and publish cross-compiled binaries#17
arcaputo3 merged 3 commits into
mainfrom
release-ci-v0.1.0

Conversation

@arcaputo3

Copy link
Copy Markdown
Contributor

Sets up release automation so v* tags publish binaries, and corrects skill-doc drift found while verifying the CLI surface.

Release automation

Pushing a tag is the whole process:

git tag -a v0.1.0 -m "v0.1.0" && git push origin v0.1.0

release.yml then tests, runs make dist, asserts the binary reports the version its tag implies, and publishes with --generate-notes.

  • make dist is the single build recipe. The workflow calls it instead of reimplementing the matrix in YAML, so local and published artifacts come from the same code path.
  • ci.yml gains a dist job so a broken cross-compile fails on the PR that caused it, rather than after a tag is already pushed and immutable.
  • 5 targets: darwin/linux × amd64/arm64, plus windows/amd64. Archives bundle README + LICENSE and ship with SHA256SUMS.
  • Hyphenated tags (v0.2.0-rc1) publish as prereleases.

Version plumbing

The version was stated twice and injectable neither time — const Version = "0.1.0" in cli plus a separate hardcoded UserAgent = "quartr-cli/0.1.0" in quartr. A const can't be set by -ldflags -X, so release builds had no way to stamp themselves, and the two copies could drift so --version and the wire disagreed.

Resolution now lives in internal/quartr/version.go (below cli, so both readers share one value) and prefers, in order: the injected string → debug.ReadBuildInfo (module version for go install pkg@v0.1.0, VCS revision for a checkout) → dev.

Module rename

go.mod declared a bare module quartr-cli, so go install github.com/TJC-LP/quartr-cli/cmd/quartr@latest could not resolve. Renaming is free right now — no tags, no releases, no importers — and becomes a breaking change the moment v0.1.0 exists. The GitHub repo, clone URL, and binary name are unchanged.

Skill doc corrections

Three drift points, each verified against the built binary with --debug rather than by reading the resource map:

Claim Reality
--type-ids works on audio /audio has no typeIds; silently dropped, so callers get unfiltered rows
--transcript-version works on transcripts get / audio get Both allow only expand; it reaches the API on live / live-transcripts only
live transcripts has list, get, stream Also has download via downloadField

--expand is split into two rows, since the API-side event expansion and the client-side company join cover different resources — --expand company does work on events, which the combined row left ambiguous.

CLAUDE.md also called the repo private; it is public.

Verification

  • go test ./..., golangci-lint run (0 issues), pre-commit clean
  • make dist builds all 5 targets; archives and checksums verified
  • Release binary confirmed sending User-Agent: quartr-cli/0.1.0 against a local server
  • Version fallback confirmed in a real clone: clean → pseudo-version, dirty → +dirty suffix

🤖 Generated with Claude Code

arcaputo3 and others added 3 commits August 5, 2026 15:20
The module was declared as a bare `quartr-cli`, so `go install
github.com/TJC-LP/quartr-cli/cmd/quartr@latest` could not resolve it —
Go fetches the URL in the module path. Renaming is free right now: there
are no tags, no releases, and no importers. After v0.1.0 it would be a
breaking change for anyone who had imported the package.

The version was also stated twice and injectable neither time: a `const
Version = "0.1.0"` in cli, and a separate hardcoded `UserAgent =
"quartr-cli/0.1.0"` in quartr. A const cannot be set by `-ldflags -X`, so
a release build had no way to stamp itself, and the two copies could
drift so that `--version` and the wire disagreed.

Version resolution now lives in internal/quartr/version.go, below cli, so
both readers share one value. It prefers the linker-injected string, then
falls back to what the go tool already stamps into every binary: the
module version for `go install pkg@v0.1.0`, or the VCS revision for a
build from a checkout. "dev" only when none is available. That means an
install straight from the module path reports its real version without
the Makefile being involved at all.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Pushing a v* tag now runs the tests, cross-compiles for darwin, linux and
windows on amd64 and arm64, and publishes the archives with generated
notes. Tags carry the `v`; the reported version does not, so v0.1.0 ships
`quartr 0.1.0`. A hyphenated tag (v0.2.0-rc1) publishes as a prerelease.

`make dist` is the only build recipe — the workflow calls it rather than
reimplementing the matrix in YAML, so what a maintainer builds locally and
what gets uploaded cannot diverge. For the same reason ci.yml gains a dist
job: a broken cross-compile should fail on the PR that caused it, not
after a tag is already pushed and immutable.

The workflow asserts the built binary reports the version its tag implies
before it publishes anything. A release that ships a mislabeled binary is
worse than one that fails to ship.

Archives bundle README.md and LICENSE with the binary and are published
alongside a SHA256SUMS file.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
README gains an Install section: release archives with checksum
verification and the Gatekeeper note, `go install ...@latest`, and the
make targets. The old text claimed a plain `go build` reports "dev",
which is no longer the whole story now that build info is consulted.

The skill's command reference had drifted from resources.go in three
places, each verified against the binary with --debug rather than by
reading the map:

- `--type-ids` was listed as working on audio. /audio has no typeIds
  param, so the CLI drops it and the caller silently gets unfiltered
  rows — the exact failure mode the --sort-by rejection exists to
  prevent.
- `--transcript-version` was listed for `transcripts get` and `audio
  get`. Both take only `expand`; it is dropped there. It reaches the API
  on live and live-transcripts only.
- `live transcripts` was missing its `download` operation, which the
  resource map has had via downloadField all along.

`--expand` is now split into its two rows, because the API-side `event`
expansion and the client-side `company` join apply to different
resources — notably `--expand company` does work on events, which the
single combined row left ambiguous.

CLAUDE.md documents the release process and records that the module path
must keep matching the repo URL. It also called the repo private; it is
public.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@arcaputo3
arcaputo3 merged commit 6371dd4 into main Aug 5, 2026
2 checks passed
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