Commit 330c950
feat: [release] harden /release — preflight script, fail-closed tags, publish gates (#1032)
* feat: [release] harden /release from 3-release retro — preflight script, fail-closed tags, publish gates
Retro of the v0.8.10 / v0.9.1 / v0.9.2 release traces (.github/meta/release-retro-2026-07-22.md)
found recurring failure classes; this change closes them:
- `script/release-preflight.ts` (+34 unit tests): deterministic fail-closed gate —
clean tree, HEAD == fresh `origin/main` (stage `pre`) or ancestor (stage `tag`),
local+remote tag-collision check (never auto-delete), version sanity vs npm,
prerelease-line ancestry, `release-blocker` PRs, `PREV_TAG` dry-run, marker guard
with full output in one pass
- `release.yml`: `publish-npm` now gated on the `test` job (npm could previously
publish with tests red); tag format/SHA/CHANGELOG validated BEFORE publish;
pre-publish smoke test asserts the exact tag version (a stale 0.7.3 binary once
passed while releasing 0.9.2)
- `/release` skill: preflight as Step 2 gate; three-step verified commit/tag +
`git push --atomic origin HEAD:main v{V}`; stop-never-improvise on structural
failures; deferred findings require durable issue links; P0-candidates verified
or explicitly downgraded; exit-status integrity rule (no trailing status echoes);
smoke-test the dist binary by path; every step visible in the summary table;
personas deliver via SendMessage before idling
- RELEASING.md: targeted staging instead of `git add -A`, atomic push, honest
AUR-disabled / Docker-best-effort wording
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* fix: [release] codex-review fixes — fail-closed gates, ordering, PREV_TAG upper bound
Codex review of the release-hardening commit found fail-open paths; all fixed:
- skill/RELEASING.md: tag verification now aborts (`|| exit 1`) instead of
echo-and-continue; stage-`tag` preflight moved AFTER the release commit
(it previously ran against a tree dirtied by the CHANGELOG edit and could
never pass); `cd` blocks made subshells so repo-root paths stay valid;
smoke test builds with `OPENCODE_VERSION` injected and asserts equality
- `release-preflight.ts`: npm publish-check only treats E404 as "not
published" (other errors FAIL); `gh` errors FAIL (WARN only when the
binary is missing); malformed `gh` JSON FAILs instead of double-reporting;
`run()` no longer throws on missing binaries; SemVer prerelease compare is
numeric-aware (`beta.10` > `beta.2`); `selectPrevTag` picks the greatest
stable tag strictly LOWER than the target (a merged fork-inherited
`v1.18.3` must not become PREV_TAG for `v0.9.x`) — same fix applied to
`release.yml`'s PREV_TAG loop
- `/release-beta`: wires in the preflight (`--allow-prerelease`) and
fail-closed tag collision checks before pushing the beta tag
- tests: 34 -> 38 (numeric prerelease precedence, prefix ranking,
fork-inherited higher-tag exclusion)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* fix: [release] address PR #1032 review — strict SemVer, fail-closed npm, authoritative tag check
Addresses all 7 chatgpt-codex-connector review comments:
- P1 prerelease ancestry now checks against HEAD, not origin/main — cutting
beta.N+1 from a release branch no longer trips on beta.N being unmerged
- P1 npm unreachable/unparseable is now FAIL, not WARN — an inconclusive
registry query must not defer failure to the irreversible release workflow
- P1 release.yml validates the tag via `git ls-remote origin` (with annotated
`^{}` peel) instead of an unforced fetch that a force-moved tag would defeat
- P1 prerelease targets are also compared against the current `beta` dist-tag
so a stale beta.N cannot move new beta installs backward
- P2 `parseSemver` + the workflow tag regex now enforce semver.org rules:
no leading zeros in numeric identifiers, no empty prerelease identifiers
- P2 ci.yml marker-guard job runs the preflight test suite (root bunfig.toml
pins `bun test` away from the repo root, so it runs from `script/`)
- P2 marker-guard check FAILs when analyze.ts degrades to pattern-only
detection because the upstream remote is missing
tests: 38 -> 41 (leading-zero rejection, empty-identifier rejection,
zero/alphanumeric prerelease acceptance)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* chore: drop internal release-retro notes from the PR
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>1 parent 537d3b7 commit 330c950
7 files changed
Lines changed: 1103 additions & 79 deletions
File tree
- .claude/commands
- .github/workflows
- docs
- script
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
91 | 91 | | |
92 | 92 | | |
93 | 93 | | |
94 | | - | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
95 | 101 | | |
96 | 102 | | |
97 | 103 | | |
| |||
108 | 114 | | |
109 | 115 | | |
110 | 116 | | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
111 | 121 | | |
| 122 | + | |
112 | 123 | | |
113 | 124 | | |
114 | 125 | | |
| |||
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
509 | 509 | | |
510 | 510 | | |
511 | 511 | | |
| 512 | + | |
| 513 | + | |
| 514 | + | |
| 515 | + | |
| 516 | + | |
| 517 | + | |
512 | 518 | | |
513 | 519 | | |
514 | 520 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
181 | 181 | | |
182 | 182 | | |
183 | 183 | | |
184 | | - | |
| 184 | + | |
| 185 | + | |
| 186 | + | |
| 187 | + | |
185 | 188 | | |
186 | 189 | | |
187 | 190 | | |
188 | 191 | | |
189 | 192 | | |
190 | 193 | | |
191 | 194 | | |
| 195 | + | |
| 196 | + | |
| 197 | + | |
| 198 | + | |
| 199 | + | |
| 200 | + | |
| 201 | + | |
| 202 | + | |
| 203 | + | |
| 204 | + | |
| 205 | + | |
| 206 | + | |
| 207 | + | |
| 208 | + | |
| 209 | + | |
| 210 | + | |
| 211 | + | |
| 212 | + | |
| 213 | + | |
| 214 | + | |
| 215 | + | |
| 216 | + | |
| 217 | + | |
| 218 | + | |
| 219 | + | |
| 220 | + | |
| 221 | + | |
| 222 | + | |
| 223 | + | |
| 224 | + | |
| 225 | + | |
| 226 | + | |
| 227 | + | |
| 228 | + | |
| 229 | + | |
| 230 | + | |
| 231 | + | |
| 232 | + | |
| 233 | + | |
| 234 | + | |
| 235 | + | |
192 | 236 | | |
193 | 237 | | |
194 | 238 | | |
| |||
276 | 320 | | |
277 | 321 | | |
278 | 322 | | |
279 | | - | |
280 | | - | |
| 323 | + | |
| 324 | + | |
| 325 | + | |
| 326 | + | |
| 327 | + | |
| 328 | + | |
| 329 | + | |
| 330 | + | |
| 331 | + | |
| 332 | + | |
281 | 333 | | |
| 334 | + | |
| 335 | + | |
282 | 336 | | |
283 | 337 | | |
284 | 338 | | |
| |||
321 | 375 | | |
322 | 376 | | |
323 | 377 | | |
324 | | - | |
325 | | - | |
326 | | - | |
327 | | - | |
328 | | - | |
329 | | - | |
330 | | - | |
331 | | - | |
332 | | - | |
| 378 | + | |
| 379 | + | |
| 380 | + | |
| 381 | + | |
| 382 | + | |
| 383 | + | |
| 384 | + | |
| 385 | + | |
| 386 | + | |
| 387 | + | |
| 388 | + | |
| 389 | + | |
333 | 390 | | |
334 | 391 | | |
335 | 392 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
34 | 34 | | |
35 | 35 | | |
36 | 36 | | |
37 | | - | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
38 | 53 | | |
39 | 54 | | |
40 | 55 | | |
| |||
48 | 63 | | |
49 | 64 | | |
50 | 65 | | |
51 | | - | |
| 66 | + | |
52 | 67 | | |
53 | 68 | | |
54 | 69 | | |
55 | 70 | | |
56 | | - | |
57 | | - | |
| 71 | + | |
58 | 72 | | |
59 | 73 | | |
60 | | - | |
| 74 | + | |
61 | 75 | | |
62 | 76 | | |
63 | 77 | | |
64 | 78 | | |
65 | 79 | | |
66 | 80 | | |
67 | | - | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
68 | 87 | | |
69 | 88 | | |
70 | | - | |
| 89 | + | |
71 | 90 | | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
72 | 96 | | |
73 | | - | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
74 | 102 | | |
75 | 103 | | |
76 | | - | |
| 104 | + | |
77 | 105 | | |
78 | 106 | | |
79 | 107 | | |
80 | | - | |
81 | | - | |
82 | | - | |
83 | | - | |
84 | | - | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
85 | 115 | | |
86 | | - | |
| 116 | + | |
87 | 117 | | |
88 | 118 | | |
89 | 119 | | |
| |||
0 commit comments