test: clean up isolated config homes after integration runs#509
Conversation
Addresses Greptile's review note on #506: the per-file XDG_CONFIG_HOME temp dirs were created at module scope and never removed. Bun's test runner never emits process 'exit', so the helper exports an explicit cleanupTestConfigHomes() that each consumer registers via afterAll. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Greptile SummaryThis PR fixes a temp-directory leak introduced in #506 by exporting a
Confidence Score: 5/5Test-only cleanup with no production code changes; the new cleanup function is idempotent and safe to merge. All changes are confined to test helpers and test files. The cleanupTestConfigHomes logic is straightforward — a pop-loop backed by rmSync({force:true}) — and each test file correctly pairs its createTestConfigHome() call with afterAll(cleanupTestConfigHomes). Bun's per-file worker isolation ensures the module-level createdDirs singleton is not shared across files, so there is no cross-file cleanup race. The only rough edge (a spawned daemon recreating a dir after the sweep) is already documented in the PR description and leaves at worst one near-empty directory, which is far better than the previous guaranteed leak. No files require special attention. Important Files Changed
Sequence Diagram%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
participant F as Test File (module scope)
participant H as config-home.ts
participant OS as /tmp
F->>H: createTestConfigHome()
H->>OS: mkdtempSync(join(tmpdir(), prefix))
OS-->>H: dir path
H->>H: createdDirs.push(dir)
H-->>F: dir path
F->>F: afterAll(cleanupTestConfigHomes) registered
Note over F: ... tests run ...
F->>H: cleanupTestConfigHomes() [via afterAll]
loop "while createdDirs.length > 0"
H->>H: "dir = createdDirs.pop()"
H->>OS: "rmSync(dir, { recursive: true, force: true })"
end
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
participant F as Test File (module scope)
participant H as config-home.ts
participant OS as /tmp
F->>H: createTestConfigHome()
H->>OS: mkdtempSync(join(tmpdir(), prefix))
OS-->>H: dir path
H->>H: createdDirs.push(dir)
H-->>F: dir path
F->>F: afterAll(cleanupTestConfigHomes) registered
Note over F: ... tests run ...
F->>H: cleanupTestConfigHomes() [via afterAll]
loop "while createdDirs.length > 0"
H->>H: "dir = createdDirs.pop()"
H->>OS: "rmSync(dir, { recursive: true, force: true })"
end
Reviews (1): Last reviewed commit: "test: clean up isolated config homes aft..." | Re-trigger Greptile |
Addresses the Greptile P2 on #506:
createTestConfigHome()is called at module scope in four test files and the temp dirs were never removed, leaking one directory per file per run.The suggested per-consumer
afterAllis exactly what this does — a central sweep was attempted first but Bun's test runner never emitsprocess.on("exit")(verified with a probe), so the helper now exportscleanupTestConfigHomes()and each consumer registers it withafterAll.Verified:
/tmpis clean afterbun test test/session/andbun run test:tty-smoke(previously each run left 4 dirs). One caveat: a spawned session daemon can in rare cases recreate a dir just after the sweep — a transient race that leaves at most one near-empty dir, versus the previous guaranteed leak.Empty changeset: test-only maintenance.
🤖 Generated with Claude Code