From cc1b13056b045d5ec6675011e3c45d0f9714f58b Mon Sep 17 00:00:00 2001 From: Colby McHenry Date: Thu, 21 May 2026 16:05:05 -0500 Subject: [PATCH] fix(release): make publish idempotent + verify packages landed on the registry MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The first 0.9.0 run published 6/7 npm packages: npm printed `+ @colbymchenry/codegraph-linux-x64@0.9.0` but the registry never persisted it (a known npm flake), so the job went green while linux-x64 npm installs were broken. Now: - the GitHub Release step is idempotent (create, else upload --clobber); - the publish loop skips packages already on the registry, so a re-run only fills gaps; - a new verify step queries the registry (with retries) and fails the job if any package@version is missing — green now means actually shipped. Co-Authored-By: Claude Opus 4.7 (1M context) --- .github/workflows/release.yml | 40 +++++++++++++++++++++++++++++------ 1 file changed, 33 insertions(+), 7 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 88dd0c5..dcb2061 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -55,18 +55,44 @@ jobs: env: GH_TOKEN: ${{ github.token }} run: | - gh release create "v${{ steps.ver.outputs.version }}" \ - release/codegraph-* \ - --title "v${{ steps.ver.outputs.version }}" \ - --notes-file notes.md + TAG="v${{ steps.ver.outputs.version }}" + # Idempotent: create the release once, otherwise (re-run) refresh assets. + if gh release view "$TAG" >/dev/null 2>&1; then + gh release upload "$TAG" release/codegraph-* --clobber + else + gh release create "$TAG" release/codegraph-* --title "$TAG" --notes-file notes.md + fi - name: Publish to npm env: NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} run: | - bash scripts/pack-npm.sh "${{ steps.ver.outputs.version }}" + V="${{ steps.ver.outputs.version }}" + bash scripts/pack-npm.sh "$V" # Platform packages first, then the main shim (which depends on them). + # Skip any already on the registry so a re-run only fills in gaps. for dir in release/npm/codegraph-* release/npm/main; do - echo "publishing $dir" - ( cd "$dir" && npm publish --access public ) + name=$(node -p "require('./$dir/package.json').name") + if npm view "$name@$V" version >/dev/null 2>&1; then + echo "skip $name@$V (already published)" + else + echo "publishing $name@$V" + ( cd "$dir" && npm publish --access public ) + fi + done + + - name: Verify every package is actually on the registry + run: | + V="${{ steps.ver.outputs.version }}" + # npm publish can print success without persisting; confirm against the + # registry (with retries for propagation) so green means really shipped. + for dir in release/npm/codegraph-* release/npm/main; do + name=$(node -p "require('./$dir/package.json').name") + ok= + for i in 1 2 3 4 5 6; do + if npm view "$name@$V" version >/dev/null 2>&1; then ok=1; break; fi + echo "waiting for $name@$V to appear ($i)…"; sleep 10 + done + [ -n "$ok" ] || { echo "::error::$name@$V never appeared on the registry"; exit 1; } + echo "verified $name@$V" done