diff --git a/.github/workflows/npm-publish.yml b/.github/workflows/npm-publish.yml index 7fa6882a88..f58acff65b 100644 --- a/.github/workflows/npm-publish.yml +++ b/.github/workflows/npm-publish.yml @@ -287,7 +287,12 @@ jobs: # a staged package that is never approved simply expires, with no `npm deprecate` needed. - name: Prove clean-install AND upgrade-over-previous both boot if: steps.resolve.outputs.skip != 'true' - timeout-minutes: 30 + # 60, not 30. This gate was added in #8953 and the 2026-08-27 v3.8.50 publish + # was the FIRST run to ever reach it — every earlier attempt died upstream, so + # its budget had never been measured against a real run. It then blew the limit + # on its debut: `npm pack` alone took 24m37s, leaving 5 minutes for two installs + # and two boots. 30 was a guess; 60 is sized to the one measurement we have. + timeout-minutes: 60 run: npm run check:install-upgrade # WS1.3 (D2, v3.8.49 plan): STAGED publishing by default — `npm stage publish` diff --git a/scripts/check/check-install-upgrade.mjs b/scripts/check/check-install-upgrade.mjs index 87253c611d..04cb0b4437 100644 --- a/scripts/check/check-install-upgrade.mjs +++ b/scripts/check/check-install-upgrade.mjs @@ -223,6 +223,11 @@ async function main() { const warnings = []; try { + // Timed, because this turned out to be the expensive part: on the 2026-08-27 + // v3.8.50 publish `npm pack` alone took 24m37s, leaving 5 of the step's 30-minute + // budget for two installs and two boots. Without a duration here the log showed + // only "packing…" then a timeout, which reads like a hang and is not. + const packStarted = Date.now(); log(`packing v${version}…`); const packOut = execFileSync("npm", ["pack", "--json", "--pack-destination", tmp], { cwd: ROOT, @@ -230,6 +235,8 @@ async function main() { maxBuffer: 128 * 1024 * 1024, }); const tarball = path.join(tmp, pickTarball(packOut)); + const packMb = (fs.statSync(tarball).size / 1024 / 1024).toFixed(1); + log(`packed in ${Math.round((Date.now() - packStarted) / 1000)}s (${packMb} MB)`); // ---- Phase A: clean install ------------------------------------------------- log("PHASE A — clean install of the packed tarball");