From e26be2795055c84a395fa64af4329c55a96c96c1 Mon Sep 17 00:00:00 2001 From: omermorad Date: Sat, 31 Oct 2026 19:22:32 +0200 Subject: [PATCH 1/3] fix: wait for npm publication visibility before verification --- .github/workflows/publish-packages.yml | 47 ++++++++++++++++++++++---- RELEASING.md | 2 +- 2 files changed, 42 insertions(+), 7 deletions(-) diff --git a/.github/workflows/publish-packages.yml b/.github/workflows/publish-packages.yml index fec2ade..88b2806 100644 --- a/.github/workflows/publish-packages.yml +++ b/.github/workflows/publish-packages.yml @@ -134,19 +134,54 @@ jobs: if: steps.publication.outputs.pending != '0' run: pnpm exec lerna publish from-package --yes --dist-tag beta --git-head "$APPROVED_COMMIT" --no-git-reset - name: Verify each package against its publication plan + env: + NPM_CONFIG_FETCH_RETRIES: '0' + NPM_CONFIG_FETCH_TIMEOUT: '10000' run: | + verification_deadline=$((SECONDS + 300)) while IFS= read -r entry; do package_name="$(jq -r '.name' <<< "$entry")" version="$(jq -r '.version' <<< "$entry")" expected_commit="$(jq -r '.gitHead' <<< "$entry")" expected_beta="$(jq -c '.beta' <<< "$entry")" disposition="$(jq -r '.disposition' <<< "$entry")" - npm view "$package_name@$version" --json | - jq -e --arg name "$package_name" --arg version "$version" --arg sha "$expected_commit" \ - '.name == $name and .version == $version and .gitHead == $sha' > /dev/null - npm view "$package_name" dist-tags --json | - jq -e --argjson beta "$expected_beta" \ - 'type == "object" and (has("error") | not) and (.beta // null) == $beta' > /dev/null + while true; do + if npm view "$package_name@$version" --json --prefer-online > "$RUNNER_TEMP/published-package.json"; then + # A visible version with unexpected ownership is never a visibility retry. + if ! jq -e --arg name "$package_name" --arg version "$version" --arg sha "$expected_commit" \ + '.name == $name and .version == $version and .gitHead == $sha' \ + "$RUNNER_TEMP/published-package.json" > /dev/null; then + echo "::error::$package_name@$version has unexpected package identity or gitHead." + exit 1 + fi + if npm view "$package_name" dist-tags --json --prefer-online > "$RUNNER_TEMP/published-dist-tags.json"; then + jq -e 'type == "object" and (has("error") | not) and all(.[]; type == "string")' \ + "$RUNNER_TEMP/published-dist-tags.json" > /dev/null + if jq -e --argjson beta "$expected_beta" '(.beta // null) == $beta' \ + "$RUNNER_TEMP/published-dist-tags.json" > /dev/null; then + break + fi + if [[ "$disposition" != publish ]]; then + echo "::error::The beta tag changed for preserved package $package_name." + exit 1 + fi + else + test "$disposition" = publish + jq -e '.error.code == "E404"' "$RUNNER_TEMP/published-dist-tags.json" > /dev/null + fi + else + # New uploads can return E404 briefly before npm exposes the version. + # Authentication, server errors, and missing preserved versions still fail. + test "$disposition" = publish + jq -e '.error.code == "E404"' "$RUNNER_TEMP/published-package.json" > /dev/null + fi + if (( SECONDS >= verification_deadline )); then + echo "::error::Timed out waiting for npm visibility of $package_name@$version and its beta tag. Check the registry before retrying publication." + exit 1 + fi + echo "$package_name@$version: waiting for npm registry visibility; retrying read-only verification in 10 seconds." + sleep 10 + done printf '\n- `%s@%s`: %s, verified at `%s`\n' \ "$package_name" "$version" "$disposition" "$expected_commit" >> "$GITHUB_STEP_SUMMARY" done < "$RUNNER_TEMP/package-publication.jsonl" diff --git a/RELEASING.md b/RELEASING.md index 0bae3f9..6d861d6 100644 --- a/RELEASING.md +++ b/RELEASING.md @@ -37,7 +37,7 @@ The publish preflight checks each package separately: - A missing npm version is published from the approved commit under `beta`. Its npm `gitHead` records that publishing commit, which can be newer than an unchanged package's original Git tag. - Changed contents under an existing version, unrelated source history, missing source metadata, and registry failures stop publication. Only an explicit registry `E404` permits a new publication. -The workflow records these decisions before publishing and verifies each package against its own expected commit and distribution tag afterward. A retry skips versions already published successfully; when all versions exist, the publish step is skipped entirely. No version bumps, tag moves, or distribution-tag repairs happen implicitly. +The workflow records these decisions before publishing and verifies each package against its own expected commit and distribution tag afterward. New uploads may take time to become visible on npm. Verification refreshes registry metadata and retries missing new versions or a delayed new `beta` tag for up to five minutes across the batch. It never retries uploads. Wrong source commits, changes to preserved versions, and registry errors other than `E404` still fail immediately. A retry skips versions already published successfully; when all versions exist, the publish step is skipped entirely. No version bumps, tag moves, or distribution-tag repairs happen implicitly. ### Configure signing once From e1788f5cdcc3781ab9a41e7d8c83b18e41976aaf Mon Sep 17 00:00:00 2001 From: omermorad Date: Sat, 31 Oct 2026 19:24:06 +0200 Subject: [PATCH 2/3] fix: allow ten minutes for npm registry visibility --- .github/workflows/publish-packages.yml | 2 +- RELEASING.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/publish-packages.yml b/.github/workflows/publish-packages.yml index 88b2806..c3eb7f1 100644 --- a/.github/workflows/publish-packages.yml +++ b/.github/workflows/publish-packages.yml @@ -138,7 +138,7 @@ jobs: NPM_CONFIG_FETCH_RETRIES: '0' NPM_CONFIG_FETCH_TIMEOUT: '10000' run: | - verification_deadline=$((SECONDS + 300)) + verification_deadline=$((SECONDS + 600)) while IFS= read -r entry; do package_name="$(jq -r '.name' <<< "$entry")" version="$(jq -r '.version' <<< "$entry")" diff --git a/RELEASING.md b/RELEASING.md index 6d861d6..8cb055e 100644 --- a/RELEASING.md +++ b/RELEASING.md @@ -37,7 +37,7 @@ The publish preflight checks each package separately: - A missing npm version is published from the approved commit under `beta`. Its npm `gitHead` records that publishing commit, which can be newer than an unchanged package's original Git tag. - Changed contents under an existing version, unrelated source history, missing source metadata, and registry failures stop publication. Only an explicit registry `E404` permits a new publication. -The workflow records these decisions before publishing and verifies each package against its own expected commit and distribution tag afterward. New uploads may take time to become visible on npm. Verification refreshes registry metadata and retries missing new versions or a delayed new `beta` tag for up to five minutes across the batch. It never retries uploads. Wrong source commits, changes to preserved versions, and registry errors other than `E404` still fail immediately. A retry skips versions already published successfully; when all versions exist, the publish step is skipped entirely. No version bumps, tag moves, or distribution-tag repairs happen implicitly. +The workflow records these decisions before publishing and verifies each package against its own expected commit and distribution tag afterward. New uploads may take time to become visible on npm. Verification refreshes registry metadata and retries missing new versions or a delayed new `beta` tag for up to ten minutes across the batch. It never retries uploads. Wrong source commits, changes to preserved versions, and registry errors other than `E404` still fail immediately. A retry skips versions already published successfully; when all versions exist, the publish step is skipped entirely. No version bumps, tag moves, or distribution-tag repairs happen implicitly. ### Configure signing once From 5606baa1e4d59f265f3c0af9ded2901fb366acd5 Mon Sep 17 00:00:00 2001 From: omermorad Date: Sat, 31 Oct 2026 19:24:59 +0200 Subject: [PATCH 3/3] fix: verify published package tarballs are downloadable --- .github/workflows/publish-packages.yml | 12 ++++++++---- RELEASING.md | 2 +- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/.github/workflows/publish-packages.yml b/.github/workflows/publish-packages.yml index c3eb7f1..7a1f08e 100644 --- a/.github/workflows/publish-packages.yml +++ b/.github/workflows/publish-packages.yml @@ -159,9 +159,13 @@ jobs: "$RUNNER_TEMP/published-dist-tags.json" > /dev/null if jq -e --argjson beta "$expected_beta" '(.beta // null) == $beta' \ "$RUNNER_TEMP/published-dist-tags.json" > /dev/null; then - break - fi - if [[ "$disposition" != publish ]]; then + if npm pack "$package_name@$version" --ignore-scripts --json --prefer-online \ + --pack-destination "$RUNNER_TEMP" > "$RUNNER_TEMP/published-tarball.json"; then + break + fi + test "$disposition" = publish + jq -e '.error.code == "E404"' "$RUNNER_TEMP/published-tarball.json" > /dev/null + elif [[ "$disposition" != publish ]]; then echo "::error::The beta tag changed for preserved package $package_name." exit 1 fi @@ -176,7 +180,7 @@ jobs: jq -e '.error.code == "E404"' "$RUNNER_TEMP/published-package.json" > /dev/null fi if (( SECONDS >= verification_deadline )); then - echo "::error::Timed out waiting for npm visibility of $package_name@$version and its beta tag. Check the registry before retrying publication." + echo "::error::Timed out waiting for npm visibility of $package_name@$version, its beta tag, and its tarball. Check the registry before retrying publication." exit 1 fi echo "$package_name@$version: waiting for npm registry visibility; retrying read-only verification in 10 seconds." diff --git a/RELEASING.md b/RELEASING.md index 8cb055e..46d8aa1 100644 --- a/RELEASING.md +++ b/RELEASING.md @@ -37,7 +37,7 @@ The publish preflight checks each package separately: - A missing npm version is published from the approved commit under `beta`. Its npm `gitHead` records that publishing commit, which can be newer than an unchanged package's original Git tag. - Changed contents under an existing version, unrelated source history, missing source metadata, and registry failures stop publication. Only an explicit registry `E404` permits a new publication. -The workflow records these decisions before publishing and verifies each package against its own expected commit and distribution tag afterward. New uploads may take time to become visible on npm. Verification refreshes registry metadata and retries missing new versions or a delayed new `beta` tag for up to ten minutes across the batch. It never retries uploads. Wrong source commits, changes to preserved versions, and registry errors other than `E404` still fail immediately. A retry skips versions already published successfully; when all versions exist, the publish step is skipped entirely. No version bumps, tag moves, or distribution-tag repairs happen implicitly. +The workflow records these decisions before publishing and verifies each package against its own expected commit and distribution tag afterward. New uploads may take time to become visible on npm. Verification refreshes registry metadata and retries missing new versions, delayed new `beta` tags, or unavailable new tarballs for up to ten minutes across the batch. It never retries uploads. Wrong source commits, changes to preserved versions, and registry errors other than `E404` still fail immediately. A retry skips versions already published successfully; when all versions exist, the publish step is skipped entirely. No version bumps, tag moves, or distribution-tag repairs happen implicitly. ### Configure signing once