diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 6a80e4b77..db63724f8 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -206,7 +206,11 @@ jobs: needs: cache-check if: needs.cache-check.outputs.hit != 'true' runs-on: ubuntu-latest - timeout-minutes: 15 + # 22, not 15: under parallel PR load the PGLite WASM cold-starts stretch a + # shard past 15 min while every test is still passing — the timeout then + # cancels the job and the test-status gate reads it as a failure. 13 runs + # died this way on 2026-07-21/22 alone. + timeout-minutes: 22 strategy: fail-fast: false matrix: diff --git a/test/progress.test.ts b/test/progress.test.ts index 0e70e0d6f..7f266d770 100644 --- a/test/progress.test.ts +++ b/test/progress.test.ts @@ -218,15 +218,21 @@ describe('progress reporter', () => { test('only one process-level signal handler installed across many reporters', () => { // Baseline: one handler already installed by prior tests in this file. const installedBefore = __signalHandlerInstalledForTest(); + // liveReporters is module-global, so a reporter left running by ANOTHER + // test file in the same shard shows up here. Assert the DELTA (these 50 + // lifecycles leak nothing) instead of an absolute zero — the absolute + // form flaked whenever shard composition changed and an unrelated file + // held a live reporter across this test. + const liveBefore = __liveReporterCountForTest(); const { stream } = sink(false); for (let i = 0; i < 50; i++) { const p = createProgress({ mode: 'json', stream, minIntervalMs: 0, minItems: 1 }); p.start(`phase_${i}`, 1); p.finish(); } - // After 50 reporter lifecycles, still exactly one handler and zero leaked live entries. + // After 50 reporter lifecycles, still exactly one handler and no new live entries. expect(__signalHandlerInstalledForTest()).toBe(installedBefore || true); - expect(__liveReporterCountForTest()).toBe(0); + expect(__liveReporterCountForTest()).toBe(liveBefore); }); test('startHeartbeat() fires heartbeats and stop() clears', async () => {