You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Same shape as the arxiv-cli v0.2.0 release, which worked.
goreleaser dockers_v2, ghcr.io/tamnd/goodread tagged 0.3.0 without the v and :latest, handwritten notes with the generated changelog below them.
The image gets pulled and run before this closes.
On arxiv-cli that step is what caught the tag being 0.2.0 and not v0.2.0.
homebrew and scoop stay blocked until HOMEBREW_TAP_GITHUB_TOKEN and SCOOP_BUCKET_GITHUB_TOKEN are set as repo secrets.
Checklist
README rewritten, one sentence per line
everything under docs/ rewritten the same way
goreleaser dockers_v2 publishing ghcr.io/tamnd/goodread, tagged 0.3.0 and :latest
the container image actually pulled and run before the issue closes
govulncheck against the tag, not only against the branch
handwritten release notes with the generated changelog below them
Two PRs in, five of seven boxes ticked. #28 for the docs, #29 for the release config.
The docs were worse than stale. They documented --cookies, --workers, a singular quote command, crawl --parse, search --html and a five row exit code table that has not been right since M4, and they said nothing about works, editions, the graph, the crawler or the MCP server. Rewritten, one sentence per line, no newline inside a sentence.
The guides are renamed to the job rather than the commands that happened to exist in v0.1.0: books-and-works, store-and-graph, robots-and-limits, crawling, and a new mcp. v0-1-0.md keeps its facts and gains a note at the top saying they are v0.1.0's, so somebody landing on it from a search does not follow it into --cookies.
Every command, flag and default in the reference was read off --help from a build of the branch rather than remembered. Which is how I found that --fields names the JSON keys and --template walks the Go struct, so --fields isbn13 and {{.Book.ISBN13}} are the same field by different routes and {{.title}} silently is not. That is now written down.
dockers_v2 was already right.{{ .Version }} is the tag without the v, so v0.3.0 gives 0.3.0, and latest is alongside it. Nothing to change, so the box is ticked on inspection rather than on a commit.
The release header was two releases stale. It still claimed goodread "routes around the Goodreads WAF through open endpoints so search and shelves keep working", which is now flatly untrue since both are disallowed. Replaced with handwritten v0.3.0 notes and a breaking-changes section naming every flag and command that moved. The header is rewritten per release rather than kept generic, which sounds like a chore until you notice this one went two releases without anybody reading it.
govulncheck at the tag found six. Which is the argument for adding it. ci.yml covered main and PRs; a tag can be cut from a commit that was green a week ago and the database has moved since.
Five were the standard library in go1.26.5, fixed in go1.26.6: GO-2026-6218 net/url, GO-2026-6090 crypto/tls, GO-2026-6088 encoding/xml, GO-2026-5972 encoding/asn1, GO-2026-5026 net/http reached from Client.doGet. The release job's setup-go had no check-latest, so the runner's cached toolchain could be a patch behind and ship every standard library CVE fixed in between. Set now.
The sixth, GO-2026-5970 in golang.org/x/text v0.38.0, comes in through fang. Bumped to v0.39.0.
What is left is the outward-facing half. Tagging v0.3.0 publishes a container image, a GitHub release and, once the tokens exist, a cask and a scoop manifest. That is not something to do on my own initiative, so it waits for a go-ahead. Pulling and running the image follows the tag, since there is nothing to pull until then.
Tagged at 456828f rather than at main, because main had already moved on to the search work that the notes call v0.3.1, and a tag whose contents do not match its notes is worse than a tag cut a few commits back. v0.3.1 followed straight after.
The run is green. 35 assets: archives for Linux, macOS, Windows and FreeBSD, deb, rpm and apk, checksums with a keyless cosign signature and a certificate, and an SBOM per archive. The multi-arch image is on GHCR for linux/amd64 and linux/arm64, and 0.3.0, 0.3.1 and latest all answer.
Homebrew and Scoop are still unpublished, and that did not fail anything. Both blocks self-disable when their token is unset, so the run wrote the cask and the manifest into dist and skipped the upload, saying "brew.skip_upload is set" and "scoop.skip_upload is true". Adding HOMEBREW_TAP_GITHUB_TOKEN and SCOOP_BUCKET_GITHUB_TOKEN as repo secrets and re-running the release is all either needs.
One thing this shook out: the lint job ran golangci-lint at latest with no config, so a linter release had turned main red on a commit nobody touched. The rules are written down in .golangci.yml now and the version is pinned, and three real findings were fixed rather than excluded (#35).
Activity
tamnd commentedon Aug 15, 2026
Two PRs in, five of seven boxes ticked. #28 for the docs, #29 for the release config.
The docs were worse than stale. They documented
--cookies,--workers, a singularquotecommand,crawl --parse,search --htmland a five row exit code table that has not been right since M4, and they said nothing about works, editions, the graph, the crawler or the MCP server. Rewritten, one sentence per line, no newline inside a sentence.The guides are renamed to the job rather than the commands that happened to exist in v0.1.0:
books-and-works,store-and-graph,robots-and-limits,crawling, and a newmcp.v0-1-0.mdkeeps its facts and gains a note at the top saying they are v0.1.0's, so somebody landing on it from a search does not follow it into--cookies.Every command, flag and default in the reference was read off
--helpfrom a build of the branch rather than remembered. Which is how I found that--fieldsnames the JSON keys and--templatewalks the Go struct, so--fields isbn13and{{.Book.ISBN13}}are the same field by different routes and{{.title}}silently is not. That is now written down.dockers_v2was already right.{{ .Version }}is the tag without thev, sov0.3.0gives0.3.0, andlatestis alongside it. Nothing to change, so the box is ticked on inspection rather than on a commit.The release header was two releases stale. It still claimed goodread "routes around the Goodreads WAF through open endpoints so search and shelves keep working", which is now flatly untrue since both are disallowed. Replaced with handwritten v0.3.0 notes and a breaking-changes section naming every flag and command that moved. The header is rewritten per release rather than kept generic, which sounds like a chore until you notice this one went two releases without anybody reading it.
govulncheck at the tag found six. Which is the argument for adding it.
ci.ymlcovered main and PRs; a tag can be cut from a commit that was green a week ago and the database has moved since.Five were the standard library in go1.26.5, fixed in go1.26.6: GO-2026-6218
net/url, GO-2026-6090crypto/tls, GO-2026-6088encoding/xml, GO-2026-5972encoding/asn1, GO-2026-5026net/httpreached fromClient.doGet. The release job'ssetup-gohad nocheck-latest, so the runner's cached toolchain could be a patch behind and ship every standard library CVE fixed in between. Set now.The sixth, GO-2026-5970 in
golang.org/x/textv0.38.0, comes in throughfang. Bumped to v0.39.0.What is left is the outward-facing half. Tagging
v0.3.0publishes a container image, a GitHub release and, once the tokens exist, a cask and a scoop manifest. That is not something to do on my own initiative, so it waits for a go-ahead. Pulling and running the image follows the tag, since there is nothing to pull until then.tamnd commentedon Aug 17, 2026
v0.3.0 is tagged and released: https://github.com/tamnd/goodread-cli/releases/tag/v0.3.0
Tagged at 456828f rather than at main, because main had already moved on to the search work that the notes call v0.3.1, and a tag whose contents do not match its notes is worse than a tag cut a few commits back. v0.3.1 followed straight after.
The run is green. 35 assets: archives for Linux, macOS, Windows and FreeBSD, deb, rpm and apk, checksums with a keyless cosign signature and a certificate, and an SBOM per archive. The multi-arch image is on GHCR for linux/amd64 and linux/arm64, and
0.3.0,0.3.1andlatestall answer.Homebrew and Scoop are still unpublished, and that did not fail anything. Both blocks self-disable when their token is unset, so the run wrote the cask and the manifest into dist and skipped the upload, saying "brew.skip_upload is set" and "scoop.skip_upload is true". Adding HOMEBREW_TAP_GITHUB_TOKEN and SCOOP_BUCKET_GITHUB_TOKEN as repo secrets and re-running the release is all either needs.
One thing this shook out: the lint job ran golangci-lint at
latestwith no config, so a linter release had turned main red on a commit nobody touched. The rules are written down in .golangci.yml now and the version is pinned, and three real findings were fixed rather than excluded (#35).