From f142fafe8ee34c3f6a6f50b10c2422607308d54f Mon Sep 17 00:00:00 2001 From: Lucien <44640337+LucienSong@users.noreply.github.com> Date: Sat, 17 Oct 2026 10:22:23 +0800 Subject: [PATCH] fix(release): tolerate registry visibility delay after publication --- .github/workflows/publish.yml | 23 +++++++++++++++++++++++ scripts/check-release-package.mjs | 19 +++++++++++++++++-- 2 files changed, 40 insertions(+), 2 deletions(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 415a680..af7d4a1 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -2,6 +2,11 @@ name: Publish on: workflow_dispatch: + inputs: + verify_only: + description: Verify the existing registry version without publishing + type: boolean + default: false push: tags: - 'v*' @@ -12,6 +17,7 @@ permissions: jobs: publish: + if: ${{ !inputs.verify_only }} name: Publish to npm runs-on: ubuntu-latest @@ -61,3 +67,20 @@ jobs: run: | version=$(node -p "require('./package.json').version") node scripts/check-release-package.mjs "shell-sdk@$version" + + verify: + name: Verify existing npm package + if: ${{ github.event_name == 'workflow_dispatch' && inputs.verify_only }} + runs-on: ubuntu-latest + permissions: + contents: read + steps: + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 + with: + node-version: '24' + package-manager-cache: false + - name: Verify the published registry package + run: | + version=$(node -p "require('./package.json').version") + node scripts/check-release-package.mjs "shell-sdk@$version" diff --git a/scripts/check-release-package.mjs b/scripts/check-release-package.mjs index dac467a..be2aeff 100644 --- a/scripts/check-release-package.mjs +++ b/scripts/check-release-package.mjs @@ -3,6 +3,7 @@ import { execFileSync, spawnSync } from 'node:child_process'; import { mkdtempSync, readFileSync, rmSync, statSync, writeFileSync } from 'node:fs'; import { tmpdir } from 'node:os'; import path from 'node:path'; +import { setTimeout } from 'node:timers/promises'; const expected = JSON.parse(readFileSync('package.json', 'utf8')); const consumer = mkdtempSync(path.join(tmpdir(), 'shell-sdk-package-')); @@ -16,8 +17,22 @@ function run(command, args) { try { const spec = process.argv[2] ?? path.join(consumer, JSON.parse(execFileSync('npm', ['pack', '--json', '--pack-destination', consumer], { encoding: 'utf8' }))[0].filename); - run('npm', ['install', '--ignore-scripts', '--no-audit', '--no-fund', - '--no-package-lock', spec]); + for (let attempt = 0; ; attempt++) { + try { + run('npm', ['install', '--ignore-scripts', '--no-audit', '--no-fund', + '--no-package-lock', '--prefer-online', spec]); + break; + } catch (error) { + const message = String(error?.message); + const versionNotVisible = spec === `${expected.name}@${expected.version}` && + message.includes('npm error code ETARGET') && + message.includes(`No matching version found for ${spec}.`); + if (!versionNotVisible || attempt >= 2) throw error; + const delay = 5000 * (attempt + 1); + console.error(`Registry has not exposed ${spec}; retrying in ${delay / 1000}s`); + await setTimeout(delay); + } + } const root = path.join(consumer, 'node_modules', expected.name); const installed = JSON.parse(readFileSync(path.join(root, 'package.json'), 'utf8')); assert.equal(installed.version, expected.version, 'Installed version must match the release');