fix(release): make the v0.23.1 tag pass its own publish gates - #3354
fix(release): make the v0.23.1 tag pass its own publish gates#3354kovtcharov wants to merge 2 commits into
Conversation
Tagging v0.23.1 today fails publish.yml twice before it builds anything. The docs navbar still advertised v0.23.0 with Lemonade 11.5.0 while version.py declared 0.23.1/11.8.1, and publish.yml hard-fails a tag whose label does not name it. The release notes were missing the "What's New" section validate_release_notes.py requires, so that step exited 1 too. The notes also handed users two commands that do not exist in any GAIA binary: `gaia install gaia` is the Lemonade installer and rejects an agent id, and `gaia list` is not a subcommand at all. The working pair is `gaia hub install gaia --trust` / `gaia hub list`, which is what the TUI already tells users to run. Both validators only ever ran against a pushed tag, which is why a release PR could merge untaggable. tests/unit/test_docs_json_release.py now checks docs.json against version.py at PR time, and docs.yml runs the release-note validator for the declared version.
Verdict: Approve with suggestionsThis makes the v0.23.1 tag pass the gates that would otherwise fail it mid-release, and fixes release notes that handed users two commands no GAIA binary accepts. Both corrections check out: the version/navbar/notes now agree, and the replacement commands match what the CLI actually parses and what the README already tells people to run. One gap worth closing before merge, and it's small: the new docs.json guard is a unit test, and the unit-test workflow doesn't run on documentation-only changes. So the exact drift this PR is guarding against — someone editing the navbar label in a docs-only pull request — still slips through to the tag, which is the moment this PR is trying to stop being the moment of discovery. Adding the two documentation paths to the unit-test workflow's trigger list closes it; that file already does this for one other doc. Two smaller things: the new "What's New" entry is a prose block where every other entry in the file is a single bullet, and it repeats the same fact the opening paragraph and the bug-fix entry already state — which also pushes the notes past the release process's own word budget for a patch release. And both new gates now fail loudly whenever the declared version has no notes file yet, which is intended for a release pull request but will also redden unrelated documentation changes if a version bump ever lands ahead of its notes. Real-world evidenceNo evidence bundle was produced for this run ( publish.yml's inline docs.json check, reproduced against this tree: navbar label Not run here: 🔍 Technical details🟡 The new docs.json guard can't fire on the PR shape it most needs to catch
Practical effect: a release PR is covered (it bumps # tests/unit/test_doc_examples_runnable.py execs this guide's own code
# blocks, so a docs-only change can still break the guard.
- 'docs/guides/custom-agent.mdx'
# tests/unit/test_docs_json_release.py pins docs.json + the release notes
# to src/gaia/version.py, so a docs-only change can break it too.
- 'docs/docs.json'
- 'docs/releases/**'(needs adding to both the 🟢
|
The guard added in the previous commit could not fire on the PR shape it exists to catch. test_unit.yml's paths filter covers src/** and tests/**, so a docs-only PR that edits or drops the navbar label never runs the test that pins it to version.py — which is exactly how v0.23.1 became untaggable. Add docs/docs.json and docs/releases/** to both trigger blocks, following the docs/guides/custom-agent.mdx precedent already in that file. The v0.23.1 "What's New" entry becomes a single bullet like every other entry in the file, dropping a third telling of what the opening paragraph and the bug-fix entry already say (narrative section: 358 -> 333 words, against the release skill's 350-word patch cap). Both new gates resolve the notes path from the declared __version__, so a bump that lands ahead of its notes now reddens every docs and unit run. The release skill gains a hard rule that the two must land together, rather than the gate being loosened to tolerate the gap.
|
All three addressed in The guard now covers docs-only PRs.
On the version-bump question, I kept the gates strict and wrote the constraint down instead of loosening them. A bump with no notes is not a benign intermediate state — it is the untaggable state this PR exists to make loud, and CLAUDE.md's fail-loudly rule cuts against adding a tolerance to the check that catches it. The release skill's Phase 2 already commits What I consciously did not do: make 🔍 Technical detailsVerified on The 9 Pylint errors are unchanged from the base: Windows-only
|
Summary
v0.23.1cannot be tagged frommaintoday —publish.yml'svalidatejob rejects it twice before anything is built. This makes the tag pass, and adds the PR-time checks whose absence let the release PR merge untaggable.Why
The release PR bumped
version.pyto0.23.1/ Lemonade11.8.1but left the docs navbar readingv0.23.0 · Lemonade 11.5.0, and shipped release notes with no## What's Newsection. Both are hard gates inpublish.yml, and neither runs on a PR — they only fire against a pushed tag, so the first time anyone finds out is mid-release.The notes also hand new users two commands that do not exist in any GAIA binary:
gaia listis not a subcommand, andgaia installis the Lemonade installer, which rejects a trailing agent id. A user following the v0.23.1 notes to install the flagship agent gets an argparse error. The working commands aregaia hub install gaia --trust/gaia hub list— the same pair the TUI already tells users to run.Linked issue
Closes #3353
Refs #1128
Changes
publish.ymlunchanged.tests/unit/test_docs_json_release.pychecksdocs.jsonagainstversion.pyat PR time;docs.ymlruns the release-note validator for the declared version. These are the two gates that previously existed only behind a tag.Test plan
python util/validate_release_notes.py docs/releases/v0.23.1.mdx --tag v0.23.1→ exits 0 (was 1)python -m pytest tests/unit/test_docs_json_release.py -q→ 5 passed; revertingdocs.jsonalone fails 3 of thempublish.yml's inlinedocs.jsoncheck executed verbatim withTAG_NAME=v0.23.1→ exits 0docs.ymlstep extracted from the workflow and run against a simulated bump to0.24.0→ exits 1python util/lint.py --all→ Black / isort / Flake8 pass; the 9 Pylint errors are pre-existing Windows-onlyos.killpg/os.geteuidfalse positives in files this PR does not touch (identical count on the unmodified base)Evidence
CLI — the commands the notes told users to run (
.venv\Scripts\python.exe -m gaia.cli):Release-notes gate, before → after:
publish.yml's docs.json gate, run verbatim withTAG_NAME=v0.23.1:New PR-time gates:
Not in this PR
update-release-branch.ymlandrelease_components.ymlstill fire on the same tag independently of validation and approval —update-release-branch.ymlforce-pushesreleaseand exits 1 on pre-release tags;release_components.ymlredeploys the production Cloudflare Worker before any approval. Chaining those aftergithub-releaseis a separate PR.approve-publishhard-requiresemail-eval, which is currently failing on Anthropic billing (credit balance is too low). Even with these validators fixed the tag stalls before approval until that is cleared — an ops action, not a code change (eval: route remaining direct-Anthropic-API eval paths through Claude Code (subscription auth) #1344).Checklist