* fix(#623): make release Verify-publish tolerant of npm propagation lag The rc and latest Verify-publish steps used a single `sleep 10` + one `npm view`, which false-failed the whole release job when npm's registry read lagged the publish write — observed on the v1.3.0-rc.1 RC run, where publish/tag/GitHub-release all succeeded but verification reported NOT_FOUND. Extract the check into scripts/verify-npm-publish.cjs: a testable module with a bounded retry/poll loop, a frozen REASON enum, and a --json mode (mirrors verify-reapply-patches.cjs). Both workflow steps now call it. dist-tag reporting stays informational and never fails the step, matching prior behavior. Adds tests/verify-npm-publish.test.cjs covering retry, exhaustion, and dist-tag reporting via injected lookups (no network). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * chore(#623): allowlist verify-npm-publish.test.cjs in the verify cluster The test-file-count linter groups test files by production-module prefix. scripts/verify-npm-publish.cjs lives under scripts/ (not a scanned prod dir), so its test collapses into the existing `verify` module via the startsWith(prefix + '-') rule — same as scripts/verify-reapply-patches.cjs, whose tests are already allowlisted under `verify`. Add the new test to that cluster's allowlisted set to satisfy the identity ratchet. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
148
tests/verify-npm-publish.test.cjs
Normal file
148
tests/verify-npm-publish.test.cjs
Normal file
@@ -0,0 +1,148 @@
|
||||
'use strict';
|
||||
|
||||
const { test, describe } = require('node:test');
|
||||
const assert = require('node:assert/strict');
|
||||
const path = require('node:path');
|
||||
|
||||
const SCRIPT = path.join(__dirname, '..', 'scripts', 'verify-npm-publish.cjs');
|
||||
const { verifyPublish, REASON } = require(SCRIPT);
|
||||
|
||||
// ---- Helpers -----------------------------------------------------------------
|
||||
|
||||
function makeFetchVersion(sequence) {
|
||||
let i = 0;
|
||||
return () => sequence[Math.min(i++, sequence.length - 1)];
|
||||
}
|
||||
|
||||
function makeSleepSpy() {
|
||||
let sleeps = 0;
|
||||
const sleep = async () => { sleeps++; };
|
||||
const count = () => sleeps;
|
||||
return { sleep, count };
|
||||
}
|
||||
|
||||
// ---- Tests -------------------------------------------------------------------
|
||||
|
||||
describe('verifyPublish', () => {
|
||||
test('returns OK on first attempt when version is already live', async () => {
|
||||
const { sleep, count } = makeSleepSpy();
|
||||
const fetchVersion = makeFetchVersion(['1.3.0-rc.1']);
|
||||
const fetchDistTag = makeFetchVersion([null]);
|
||||
|
||||
const result = await verifyPublish({
|
||||
pkg: '@opengsd/gsd-core',
|
||||
version: '1.3.0-rc.1',
|
||||
fetchVersion,
|
||||
fetchDistTag,
|
||||
sleep,
|
||||
intervalMs: 0,
|
||||
});
|
||||
|
||||
assert.equal(result.ok, true);
|
||||
assert.equal(result.reason, REASON.OK_VERSION_LIVE);
|
||||
assert.equal(result.attempts, 1);
|
||||
assert.equal(count(), 0);
|
||||
});
|
||||
|
||||
test('retries through propagation lag and succeeds once the version appears', async () => {
|
||||
const { sleep, count } = makeSleepSpy();
|
||||
const fetchVersion = makeFetchVersion([null, null, '1.3.0-rc.1']);
|
||||
const fetchDistTag = makeFetchVersion([null]);
|
||||
|
||||
const result = await verifyPublish({
|
||||
pkg: '@opengsd/gsd-core',
|
||||
version: '1.3.0-rc.1',
|
||||
fetchVersion,
|
||||
fetchDistTag,
|
||||
sleep,
|
||||
intervalMs: 0,
|
||||
});
|
||||
|
||||
assert.equal(result.ok, true);
|
||||
assert.equal(result.attempts, 3);
|
||||
assert.equal(count(), 2);
|
||||
});
|
||||
|
||||
test('fails after exhausting maxAttempts when version never appears', async () => {
|
||||
const { sleep, count } = makeSleepSpy();
|
||||
const fetchVersion = makeFetchVersion([null]);
|
||||
const fetchDistTag = makeFetchVersion([null]);
|
||||
|
||||
const result = await verifyPublish({
|
||||
pkg: '@opengsd/gsd-core',
|
||||
version: '1.3.0-rc.1',
|
||||
maxAttempts: 4,
|
||||
fetchVersion,
|
||||
fetchDistTag,
|
||||
sleep,
|
||||
intervalMs: 0,
|
||||
});
|
||||
|
||||
assert.equal(result.ok, false);
|
||||
assert.equal(result.reason, REASON.FAIL_VERSION_NOT_FOUND);
|
||||
assert.equal(result.attempts, 4);
|
||||
assert.equal(count(), 3);
|
||||
});
|
||||
|
||||
test('reports dist-tag pointer informationally without affecting ok', async () => {
|
||||
const { sleep, count } = makeSleepSpy();
|
||||
const fetchVersion = makeFetchVersion(['1.3.0-rc.1']);
|
||||
const fetchDistTag = makeFetchVersion(['1.3.0-rc.1']);
|
||||
|
||||
const result = await verifyPublish({
|
||||
pkg: '@opengsd/gsd-core',
|
||||
version: '1.3.0-rc.1',
|
||||
distTag: 'next',
|
||||
fetchVersion,
|
||||
fetchDistTag,
|
||||
sleep,
|
||||
intervalMs: 0,
|
||||
});
|
||||
|
||||
assert.equal(result.ok, true);
|
||||
assert.deepEqual(result.distTag, {
|
||||
name: 'next',
|
||||
points_to: '1.3.0-rc.1',
|
||||
matches: true,
|
||||
});
|
||||
void count;
|
||||
});
|
||||
|
||||
test('dist-tag mismatch is a warning, not a failure', async () => {
|
||||
const { sleep } = makeSleepSpy();
|
||||
const fetchVersion = makeFetchVersion(['1.3.0-rc.1']);
|
||||
const fetchDistTag = makeFetchVersion(['1.2.0']);
|
||||
|
||||
const result = await verifyPublish({
|
||||
pkg: '@opengsd/gsd-core',
|
||||
version: '1.3.0-rc.1',
|
||||
distTag: 'latest',
|
||||
fetchVersion,
|
||||
fetchDistTag,
|
||||
sleep,
|
||||
intervalMs: 0,
|
||||
});
|
||||
|
||||
assert.equal(result.ok, true);
|
||||
assert.equal(result.distTag.matches, false);
|
||||
assert.equal(result.distTag.points_to, '1.2.0');
|
||||
});
|
||||
|
||||
test('no dist-tag requested yields null distTag', async () => {
|
||||
const { sleep } = makeSleepSpy();
|
||||
const fetchVersion = makeFetchVersion(['1.3.0-rc.1']);
|
||||
const fetchDistTag = makeFetchVersion([null]);
|
||||
|
||||
const result = await verifyPublish({
|
||||
pkg: '@opengsd/gsd-core',
|
||||
version: '1.3.0-rc.1',
|
||||
fetchVersion,
|
||||
fetchDistTag,
|
||||
sleep,
|
||||
intervalMs: 0,
|
||||
});
|
||||
|
||||
assert.equal(result.ok, true);
|
||||
assert.equal(result.distTag, null);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user