From c6affc008467314a97518d91b13c871a0904e386 Mon Sep 17 00:00:00 2001 From: wit_qq Date: Sun, 6 Sep 2026 00:40:22 +0300 Subject: [PATCH] fix: publish verified local tarballs Reuse the already-downloaded and hash-verified Release asset because npm 12 rejects remote publish URLs. --- .github/workflows/publish-npm.yml | 3 ++- scripts/check-workflows.mjs | 6 ++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/.github/workflows/publish-npm.yml b/.github/workflows/publish-npm.yml index 3d796e4..77ee3c4 100644 --- a/.github/workflows/publish-npm.yml +++ b/.github/workflows/publish-npm.yml @@ -162,7 +162,8 @@ jobs: if npm view "${package_name}@${version}" version --json >/dev/null 2>&1; then echo "${package_name}@${version} already contains the accepted bytes; skipping" else - npm publish --access public "${asset_url}" + tarball="${RUNNER_TEMP}/${asset_name}" + npm publish --access public "${tarball}" fi done < "${package_rows}" diff --git a/scripts/check-workflows.mjs b/scripts/check-workflows.mjs index ae4f0d8..dbc79fd 100644 --- a/scripts/check-workflows.mjs +++ b/scripts/check-workflows.mjs @@ -48,14 +48,16 @@ for (const required of [ 'asset.digest !== `sha256:${item.sha256}`', 'registry-preflight-${index}.tgz', 'already contains the accepted bytes; skipping', - 'npm publish --access public "${asset_url}"', + 'tarball="${RUNNER_TEMP}/${asset_name}"', + 'npm publish --access public "${tarball}"', 'registry-final-${index}.tgz', ]) assert.ok(runs.includes(required), `publication must enforce ${required}`); const preflight = runs.indexOf('registry-preflight-${index}.tgz'); -const firstPublish = runs.indexOf('npm publish --access public "${asset_url}"'); +const firstPublish = runs.indexOf('npm publish --access public "${tarball}"'); assert.ok(preflight >= 0 && preflight < firstPublish, 'all existing registry versions are checked before publication'); assert.ok(runs.includes('if existing_url="$(npm view'), 'registry absence must be decided by npm view exit status'); assert.ok(!runs.includes('dist.tarball --json 2>/dev/null || true'), 'registry lookup errors must not become JSON values'); +assert.ok(!runs.includes('npm publish --access public "${asset_url}"'), 'npm 12 must not publish a remote URL'); for (const forbidden of ['actions/checkout@', 'NPM_TOKEN', 'NODE_AUTH_TOKEN', 'npm ci', 'npm run build', 'npm test', 'npm pack']) { assert.ok(!publishSource.includes(forbidden), `publication must exclude ${forbidden}`); }