fix(#4020): bound the test run's temp footprint with a swept run-scoped root (#4207)

* test(#4020): the runner must bound and sweep a run-scoped temp root

* fix(#4020): bound the run's temp footprint with a swept run-scoped root

* test(#4020): isolate the env-mutating rows in child processes

* fix(#4020): gate root removal on ownership so nested runners spare the outer root

* test(#4020): pass the probe file via --files, the runner's explicit-file flag

* test(#4020): resolve the probe by basename, as --files matching requires

* test(#4020): assert root survival, not content survival, in the nested-row

* chore(#4020): changeset for the run-scoped temp root

* chore(#4020): backfill changeset pr number

* fix(#4020): the sweep spares ancestors of the runner's own selected files

* fix(#4020): TMPDIR precedence — an operator redirect beats inherited TEMP/TMP

* fix(#4020): only the root's owner sweeps — a nested runner spares live sibling fixtures

---------

Co-authored-by: sim <sim@local>
This commit is contained in:
Tom Boucher
2026-09-02 20:47:34 -04:00
committed by GitHub
parent 858bb89769
commit 7d6d788b51
6 changed files with 389 additions and 6 deletions

View File

@@ -15,7 +15,16 @@
'use strict';
process.env.GSD_TEST_MODE = '1';
const { test, describe } = require('node:test');
const { test, describe, after } = require('node:test');
const { cleanup } = require('./helpers.cjs'); // #4020: fixture-tree removal
// #4020: remove every writeTmp tree once the suite ends (writeTmp callers hold
// file paths, not dirs, so this is the only owner that can).
after(() => {
for (const dir of SPEC_SECTION_TMP_DIRS.splice(0)) {
try { cleanup(dir); } catch { /* best-effort */ }
}
});
const assert = require('node:assert/strict');
const path = require('node:path');
const fs = require('node:fs');
@@ -27,8 +36,12 @@ const { PROBE_TIMEOUT_MS } = require('./helpers/timeouts.cjs');
const BUILT_SCRIPT = path.join(__dirname, '..', 'gsd-core', 'bin', 'lib', 'spec-section.cjs');
const ss = require(BUILT_SCRIPT);
// #4020: every writeTmp tree is tracked and removed after the suite — writeTmp
// returns a FILE path, so callers had no dir handle to clean up themselves.
const SPEC_SECTION_TMP_DIRS = [];
function writeTmp(name, content) {
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'spec-section-'));
SPEC_SECTION_TMP_DIRS.push(dir);
const p = path.join(dir, name);
fs.writeFileSync(p, content);
return p;