diff --git a/package.json b/package.json index 29b999b28e..1d8f7fb078 100644 --- a/package.json +++ b/package.json @@ -61,7 +61,7 @@ "smoke:posthog-live": "node scripts/smoke/posthog-live.mjs", "smoke:pipelines-tutorial": "./scripts/smoke/pipelines-tutorial-smoke.sh", "smoke:terminal-bench-loop-skill": "node scripts/smoke/terminal-bench-loop-skill-smoke.mjs", - "test:release-registry": "node --test scripts/__tests__/canary-startup-playwright.test.mjs scripts/__tests__/cursor-public-install-sandbox.test.mjs scripts/__tests__/grok-public-install-sandbox.test.mjs scripts/__tests__/prefetch-child.test.mjs scripts/__tests__/stage-bundled-packages.test.mjs scripts/__tests__/retain-runner-qualification-packages.test.mjs scripts/verify-release-registry-state.test.mjs scripts/release-package-map.test.mjs scripts/check-release-package-bootstrap.test.mjs scripts/check-no-git-push.test.mjs scripts/release-lib.test.mjs scripts/release-registry-versions.test.mjs scripts/link-plugin-dev-sdk.test.js scripts/acpx-patch-packaging.test.mjs scripts/service-onboard-smoke.test.mjs scripts/docker-onboard-smoke.test.mjs scripts/preview-artifacts.test.mjs scripts/cloud-migrator-artifacts.test.mjs", + "test:release-registry": "node --test scripts/__tests__/canary-startup-playwright.test.mjs scripts/__tests__/cursor-public-install-sandbox.test.mjs scripts/__tests__/grok-public-install-sandbox.test.mjs scripts/__tests__/prefetch-child.test.mjs scripts/__tests__/stage-bundled-packages.test.mjs scripts/__tests__/pack-staged-packages.test.mjs scripts/__tests__/retain-runner-qualification-packages.test.mjs scripts/verify-release-registry-state.test.mjs scripts/release-package-map.test.mjs scripts/check-release-package-bootstrap.test.mjs scripts/check-no-git-push.test.mjs scripts/release-lib.test.mjs scripts/release-registry-versions.test.mjs scripts/link-plugin-dev-sdk.test.js scripts/acpx-patch-packaging.test.mjs scripts/service-onboard-smoke.test.mjs scripts/docker-onboard-smoke.test.mjs scripts/preview-artifacts.test.mjs scripts/cloud-migrator-artifacts.test.mjs", "storybook-visual:baseline": "node scripts/storybook-visual-baseline.mjs", "test:storybook-visual": "node scripts/storybook-visual-baseline.mjs download && node scripts/storybook-visual-baseline.mjs verify && pnpm build-storybook && npx playwright test --config tests/storybook-visual/playwright.config.ts", "test:storybook-visual:update": "node scripts/storybook-visual-baseline.mjs download && pnpm build-storybook && npx playwright test --config tests/storybook-visual/playwright.config.ts --update-snapshots && node scripts/storybook-visual-baseline.mjs pack", diff --git a/scripts/__tests__/grok-public-install-sandbox.test.mjs b/scripts/__tests__/grok-public-install-sandbox.test.mjs index 11fde52433..3cf43712a1 100644 --- a/scripts/__tests__/grok-public-install-sandbox.test.mjs +++ b/scripts/__tests__/grok-public-install-sandbox.test.mjs @@ -120,19 +120,28 @@ test('the bundled-dependency installs run together while the other packages are // Only the bundled packages' sources are staged before the installs start; // the installs are registered for cleanup at once, before anything else can // fail; the other packages are copied while the installs run; the join comes - // before the first pack; and the pack loop walks every package in order. + // before the packs start; and the packs run through the helper covered by + // pack-staged-packages.test.mjs, bundled packages first, each registered for + // cleanup as it starts, with the results put back into dependency order + // before every tarball is checked. const bundledSources = position('for (const entry of entries.filter(entry => entry.bundled)) stageSource(entry)'); const start = position("startBundledInstalls(entries.filter(entry => entry.bundled), { logDir: prefetched, cwd: repo })"); const registered = position('prefetches.push(...installs.map(({ handle }) => handle))'); const otherSources = position('for (const entry of entries.filter(entry => !entry.bundled))'); const join = position("await awaited('bundled', Promise.all(installs.map(({ handle }) => handle.done)))"); - const packLoop = position('for (const { target } of entries)'); - const firstPack = position("run('npm', ['pack', '--ignore-scripts', '--pack-destination', root], target)"); - assert.ok(bundledSources < start && start < registered && registered < otherSources && otherSources < join && join < packLoop && packLoop < firstPack); - assert.equal(source.match(/run\('npm', \['pack'/g).length, 2, 'one package pack loop plus the lifecycle sentinel'); - // The timing line reports the split staging phase and each install. - for (const key of ['stage_sources_ms', 'stage_bundled_ms', 'stage_pack_ms']) assert.ok(source.includes(`timing.${key} =`)); + assert.ok(source.includes("import { packConcurrency, packStagedPackages, packTimings } from './pack-staged-packages.mjs'")); + const packs = position("await packStagedPackages([...entries].sort((a, b) => Number(b.bundled) - Number(a.bundled)), { logDir: prefetched, env, concurrency, register: handle => prefetches.push(handle) })"); + const reordered = position('packs.sort((a, b) => a.index - b.index)'); + const checks = position("for (const tarball of tarballs) assertNoBundledCodexPayloads(run('tar', ['-tzf', tarball])"); + const copied = position('for (const tarball of tarballs) {'); + assert.ok(bundledSources < start && start < registered && registered < otherSources && otherSources < join && join < packs && packs < reordered && reordered < checks && checks < copied); + assert.equal(source.match(/run\('npm', \['pack'/g).length, 1, 'only the lifecycle sentinel is packed in-process'); + assert.ok(source.includes("destination: join(root, `pack-${index}`)"), 'each pack writes into its own directory'); + // The timing line reports the split staging phase, each install, and the + // pack step with what the packs would have cost one after another. + for (const key of ['stage_sources_ms', 'stage_bundled_ms', 'stage_pack_ms', 'stage_pack_check_ms']) assert.ok(source.includes(`timing.${key} =`)); assert.ok(source.includes('...bundledInstallTimings(installs)')); + assert.ok(source.includes('Object.assign(timing, packTimings(packs, concurrency))')); }); test('the installed Codex probe exercises the public export and rejects incomplete or mismatched packages', () => { diff --git a/scripts/__tests__/pack-staged-packages.test.mjs b/scripts/__tests__/pack-staged-packages.test.mjs new file mode 100644 index 0000000000..09c19cf64a --- /dev/null +++ b/scripts/__tests__/pack-staged-packages.test.mjs @@ -0,0 +1,107 @@ +import assert from 'node:assert/strict'; +import { existsSync, mkdirSync, mkdtempSync, readFileSync, readdirSync, rmSync, writeFileSync } from 'node:fs'; +import { tmpdir } from 'node:os'; +import { join } from 'node:path'; +import test from 'node:test'; +import { stopPrefetches } from '../prefetch-child.mjs'; +import { PACK_ARGS, packConcurrency, packStagedPackages, packTimings } from '../pack-staged-packages.mjs'; + +// A small local script stands in for npm; no test here needs npm or a network. +// It is run as `node