From e226d755658942fd3cc279b07a15677125232e02 Mon Sep 17 00:00:00 2001 From: Mikola Lysenko Date: Tue, 13 Oct 2026 14:55:23 -0400 Subject: [PATCH] ci(release): skip npm packages an earlier attempt already staged A retry of 5.0.1's npm publish (run 38449949240) failed on the first platform package with `409 Cannot stage previously published version`: the 14 platform packages were already staged by the release run. The fallback that should have skipped them runs `npm stage list`, which can't authenticate in CI because OIDC is exchanged only on publish, so the job never reached the main package. Treat that 409 message as "already staged" in both stage steps, through one inline stage() helper. It stays inline because the job checks out the release tag, which predates any new script. Co-Authored-By: Claude Opus 5.5 (1M context) --- .github/workflows/release.yml | 65 +++++++++++++++++++++-------------- 1 file changed, 39 insertions(+), 26 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 3efcc2ce8..0248757cc 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -440,26 +440,34 @@ jobs: - name: Stage-publish platform packages id: stage-platform run: | - : > "${RUNNER_TEMP}/staged-packages.txt" - for pkg_dir in npm/socket-patch-*/; do - pkg_name="@socketsecurity/$(basename "$pkg_dir")" - echo "Staging ${pkg_name}..." - if npm stage publish "./${pkg_dir}" --access public; then + # Stage one package, tolerating a version an earlier attempt already + # staged or published, so "Re-run failed jobs" and npm-retry-version + # retries can finish a partial publish. The registry answers a + # repeat stage of a staged-but-unapproved version with `409 Cannot + # stage previously published version`, and staged versions are + # invisible to `npm view`; `npm stage list` would show them but + # can't authenticate here (OIDC is exchanged only on publish), so + # the 409 message is the signal. Inline, not a script: this job + # checks out the release tag, which may predate any new script. + stage() { + local pkg_dir="$1" pkg_name="$2" out rc=0 + echo "Staging ${pkg_name}@${VERSION}..." + out=$(npm stage publish "$pkg_dir" --access public 2>&1) || rc=$? + printf '%s\n' "$out" + if [ "$rc" -eq 0 ]; then echo "$pkg_name" >> "${RUNNER_TEMP}/staged-packages.txt" elif npm view "${pkg_name}@${VERSION}" version >/dev/null 2>&1; then - # Already fully published (approved) — a clean re-run. echo "Already published, skipping." - elif npm stage list 2>/dev/null | grep -qF "${pkg_name}@${VERSION}"; then - # Staged but not yet 2FA-approved: `npm view` can't see staged - # versions, so without this check a re-run after a mid-job - # failure could never succeed. Best-effort match on the stage - # listing (format unverified against a live staged state — if it - # misses we still fail loudly below). + elif printf '%s' "$out" | grep -qF 'Cannot stage previously published version'; then echo "Already staged awaiting approval, skipping." echo "$pkg_name" >> "${RUNNER_TEMP}/staged-packages.txt" else - exit 1 + return "$rc" fi + } + : > "${RUNNER_TEMP}/staged-packages.txt" + for pkg_dir in npm/socket-patch-*/; do + stage "./${pkg_dir}" "@socketsecurity/$(basename "$pkg_dir")" done - name: Copy README for npm package @@ -483,19 +491,24 @@ jobs: - name: Stage-publish main package run: | - pkg_name="@socketsecurity/socket-patch" - if npm stage publish ./npm/socket-patch --access public; then - echo "$pkg_name" >> "${RUNNER_TEMP}/staged-packages.txt" - elif npm view "${pkg_name}@${VERSION}" version >/dev/null 2>&1; then - echo "Already published, skipping." - elif npm stage list 2>/dev/null | grep -qF "${pkg_name}@${VERSION}"; then - # See the platform-package step: staged-not-approved versions are - # invisible to `npm view`; tolerate them so re-runs can succeed. - echo "Already staged awaiting approval, skipping." - echo "$pkg_name" >> "${RUNNER_TEMP}/staged-packages.txt" - else - exit 1 - fi + # Same as the platform-package step's stage() (see there). + stage() { + local pkg_dir="$1" pkg_name="$2" out rc=0 + echo "Staging ${pkg_name}@${VERSION}..." + out=$(npm stage publish "$pkg_dir" --access public 2>&1) || rc=$? + printf '%s\n' "$out" + if [ "$rc" -eq 0 ]; then + echo "$pkg_name" >> "${RUNNER_TEMP}/staged-packages.txt" + elif npm view "${pkg_name}@${VERSION}" version >/dev/null 2>&1; then + echo "Already published, skipping." + elif printf '%s' "$out" | grep -qF 'Cannot stage previously published version'; then + echo "Already staged awaiting approval, skipping." + echo "$pkg_name" >> "${RUNNER_TEMP}/staged-packages.txt" + else + return "$rc" + fi + } + stage ./npm/socket-patch "@socketsecurity/socket-patch" - name: Summarize staged versions awaiting approval if: always()