fix(release): verify before publishing instead of recovering from 409s [release-all] #3
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "fix/release-verify-before-publish"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
The bug
Every push to main deleted and re-uploaded all ten package versions.
publish_artifactPUT each zip blind and read the resulting 409 as evidence of a "phantom" version, so it DELETEd the live version and re-PUT. They were never phantoms — the published blobs match a localbuild_dist.pyrebuild byte-for-byte. So each run destroyed and recreated ten healthy artifacts (404-ing anyone installing in that window; losing the version outright had a re-PUT failed after its DELETE), then reported green. The repo-link POST was the same shape: the packages are already linked, so it 400'd ten times a run.The fix — read before writing
publish_artifactcompares the registry's published sha256 (/files) against a local rebuild. Match →verified, zero writes. The destructive DELETE+PUT now fires only on a real phantom (version with no blob) or genuine drift, warns loudly, and is counted in the summary.ensure_releaseGETs/releases/tags/<tag>;link_packagechecksrepository.full_namefirst.Second bug: stale tags from the history rewrite
last_tag()took the highest-numbered tag regardless of ancestry. Tags left behind by this repo's re-init (domain-language-v1.3.0,skillsmith-v1.1.0, the old repo-widev1.x) made<tag>..HEADspan unrelated history and return every commit — computing a bump from a version the tree never had, and re-releasing it every run since the stale tag stays the baseline. Only ancestors of HEAD count now. (Those tags are local-only, never pushed, so CI was never affected.)[release-all]This PR's title carries the
[release-all]token, which patch-releases all ten skills on merge — an estate-wide re-cut on the fixed pipeline. Deliberately not wired intorelease.yml, where it would re-release everything on every push; the token lives in one commit, so the switch expires the moment that commit is no longer HEAD. Also available asapply --all.Expected result on merge:
Each gets a
Maintenance release — estate-wide re-cut; no changes to this skill.changelog entry.Verification
npm run check,npm test, andcheck_plugin_commits.py origin/mainpass. A 9-case harness stubs the registry and asserts exactly which HTTP calls each state produces (healthy → GET only; absent → PUT; phantom/drift → DELETE+PUT; unexpected 409 → non-zero exit; already-linked → no POST; existing release → no POST).apply --allwas dry-run end-to-end in a throwaway clone: ten tags, ten changelog entries, bundle bump, marketplace regenerated, and the resulting tree passes lint/sync/manifest checks.🤖 Generated with Claude Code