Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# Changelog

## 0.4.2 - Unreleased

### Fixed
- Source-install documentation now requires Go 1.25+, matching `go.mod`.

## 0.4.1 - 2026-07-01

### Fixed
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ Go toolchain:
```bash
go install github.com/steipete/sag/cmd/sag@latest
```
Requires Go 1.24+.
Requires Go 1.25+.

Debian/Ubuntu source build prerequisites:
```bash
Expand Down
26 changes: 11 additions & 15 deletions docs/RELEASING.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,27 +7,23 @@ summary: 'Release checklist for sag (GitHub release + Homebrew tap)'
Follow these steps for each release. Title GitHub releases as `sag <version>`.

## Checklist
- Start from a clean, synchronized `main` checkout and confirm the target version follows the changelog/project SemVer convention.
- Update CLI version in `cmd/root.go` (`Version` field).
- Update `package.json` to the same version.
- Update `CHANGELOG.md` with a section for the new version.
- Run the gates: `pnpm format && pnpm lint && pnpm test && pnpm build`.
- Tag the release: `git tag -a v<version> -m "Release <version>"` after commits; push tags with `git push origin main --tags`.
- GitHub Actions attaches binaries (macOS universal, Linux amd64, Windows amd64) to the GitHub release automatically (workflow: `Release Binaries`).
- Update Homebrew tap formula (`../homebrew-tap/Formula/sag.rb`):
1. Set `version "<version>"`.
2. Set `url "https://github.com/steipete/sag/archive/refs/tags/v<version>.tar.gz"`.
3. Update `sha256` from the same GitHub tag tarball:
- `curl -L -o /tmp/sag-<version>.tar.gz https://github.com/steipete/sag/archive/refs/tags/v<version>.tar.gz`
- `shasum -a 256 /tmp/sag-<version>.tar.gz`
4. Verify formula checksum matches the downloaded tarball.
5. Ensure build step uses `system "go", "build", *std_go_args(ldflags: "-s -w"), "./cmd/sag"`.
6. Commit and push in tap repo: `git commit -am "sag v<version>" && git push origin main`.
- Commit the release changes, then create an annotated tag: `git tag -a v<version> -m "Release <version>"`.
- Push `main` and the tag. The `Release Binaries` workflow builds macOS arm64/amd64/universal, Linux arm64/amd64, and Windows amd64 archives, verifies their checksums, attaches them to the GitHub release, dispatches the Homebrew tap update, and waits for that workflow.
- Watch the exact tag workflow through completion. Repair or rerun failures before continuing.
- Verify the GitHub release:
- title is `sag <version>`
- body contains the complete changelog section plus links to the release commit, exact-head CI, live/behavior proof, and checksum manifest
Comment on lines +18 to +20

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Add a step to populate release notes

When cutting a new tag without pre-creating the GitHub release, this checklist now relies on the workflow-created release but never tells the maintainer how the required title/body get populated. I checked .github/workflows/release-binaries.yml and the upload step only passes tag_name and files to softprops/action-gh-release (no name, body, or generated-notes option), so the very next verification can fail unless someone knows to edit the release out-of-band. Please either add an explicit create/edit step here or wire the workflow to set the release metadata.

Useful? React with 👍 / 👎.

- all expected archives, per-archive checksums, and the combined checksum manifest are attached
- Verify `steipete/homebrew-tap` updated `Formula/sag.rb` to the new release URLs and matching checksums. The release workflow owns this update; use the [Homebrew playbook](releasing-homebrew.md) for recovery.
- Verify Homebrew install from tap:
- `brew update && brew reinstall steipete/tap/sag`
- `brew test steipete/tap/sag`
- `sag --version`
- Create GitHub release for `v<version>`:
- Title: `sag <version>`
- Body: bullets from `CHANGELOG.md` for that version
- Assets: optional source tarball `/tmp/sag-<version>.tar.gz` (mention SHA256 in body)
- Smoke-test CLI locally: `sag --help`, `sag voices --limit 3`, `sag -v Roger "hello"`.
- Add the next patch `Unreleased` section to `CHANGELOG.md`, commit, and push the closeout.
- Announce: optional note with `brew update && brew upgrade steipete/tap/sag`.
2 changes: 1 addition & 1 deletion docs/install.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ sudo install -m 0755 /tmp/sag /usr/local/bin/sag
go install github.com/steipete/sag/cmd/sag@latest
```

Requires the Go version declared in `go.mod` (1.24+). Source builds bake the Git description into the version string.
Requires the Go version declared in `go.mod` (1.25+). Source builds bake the Git description into the version string.

## From source

Expand Down
68 changes: 15 additions & 53 deletions docs/releasing-homebrew.md
Original file line number Diff line number Diff line change
@@ -1,66 +1,28 @@
# sag Homebrew Release Playbook

Lightweight flow to ship sag via the `steipete/tap` Homebrew tap (source build).
The `Release Binaries` workflow updates `steipete/homebrew-tap` after it uploads and verifies release assets. Do not edit the tap formula as a normal release step.

## 0) Prereqs
- macOS with Homebrew installed.
- Clean git tree on `main`.
- Go toolchain installed (Go version from `go.mod`).
- Access to tap repo sibling at `../homebrew-tap`.
## Normal flow

## 1) Verify build is green
```sh
pnpm format
pnpm lint
pnpm test
pnpm build
```

## 2) Bump the version in code
- Update `Version` in `cmd/root.go`.
- Update `CHANGELOG.md` entry to match.
1. Push the annotated `vX.Y.Z` tag after the release commit is on `main`.
2. Watch `Release Binaries` through its `update-homebrew-tap` job.
3. Confirm the dispatched `Update Formula` run succeeds in `steipete/homebrew-tap`.
4. Inspect `Formula/sag.rb`: its versioned artifact URLs and SHA-256 values must match the GitHub release assets and checksum manifest.
5. Sanity-check install from tap:

## 3) Tag & push
```sh
git commit -am "release: vX.Y.Z"
git tag vX.Y.Z
git push origin main --tags
brew update
brew reinstall steipete/tap/sag
brew test steipete/tap/sag
sag --version
```

## 4) Update the Homebrew tap formula
In `../homebrew-tap/Formula/sag.rb`:
## Recovery

1. Set `version "X.Y.Z"`.
2. Set `url` to the tag source tarball:
```
url "https://github.com/steipete/sag/archive/refs/tags/vX.Y.Z.tar.gz"
```
3. Update `sha256` for that tarball:
```sh
curl -L -o /tmp/sag.tar.gz https://github.com/steipete/sag/archive/refs/tags/vX.Y.Z.tar.gz
shasum -a 256 /tmp/sag.tar.gz
```
4. Ensure build step uses:
```ruby
system "go", "build", *std_go_args(ldflags: "-s -w"), "./cmd/sag"
```
If the release assets exist but the tap update failed, fix the release workflow or tap workflow and rerun `Release Binaries` for the existing tag:

Commit/push in tap repo:
```sh
git commit -am "sag vX.Y.Z"
git push origin main
```

## 5) Sanity-check install from tap
```sh
brew uninstall sag || true
brew untap steipete/tap || true
brew tap steipete/tap
brew install steipete/tap/sag
brew test steipete/tap/sag
sag --version
gh workflow run release-binaries.yml --repo steipete/sag -f tag=vX.Y.Z
```

## Notes
- Formula builds from source; no binary assets required.
- Keep formula minimal: version, url, sha256, license, `go` build dep, `std_go_args`.
The workflow redispatches `update-formula.yml` with the repository, tag, artifact template, and a unique request ID, then waits for the matching tap run. Verify the rerun and formula before installing. Manual formula edits are a last-resort repair and still require checksums from the exact published assets.
2 changes: 1 addition & 1 deletion docs/spec.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
CLI that mirrors macOS `say` but uses ElevenLabs or 60db for synthesis. ElevenLabs defaults to streaming directly to speakers; 60db buffers and validates WAV output before playback.

## Runtime & deps
- Go 1.24+
- Go 1.25+
- Playback uses built-in Go audio (MP3/WAV + oto) and should work on macOS/Linux/Windows with a default output device.
- Auth via exactly one configured provider: ElevenLabs (`ELEVENLABS_API_KEY`, `SAG_API_KEY`, `--api-key`) or 60db (`SIXTYDB_API_KEY`).

Expand Down
Loading