HOMELAB-2682: test(sandbox-init): stop temp-dir leaks #888
No reviewers
Labels
No labels
operator-review
No milestone
No project
No assignees
2 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
Homelab/infra-core!888
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "plane/HOMELAB-2682-sandbox-init-tmpfix"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
What
The sandbox-init suites built real trees under
$TMPDIRand never removed them. This PR makes every maker hand its directory to a new tracked helper (test/temp-dirs.mjs) and removes the tracked dirs from a top-levelnode:testafterhook in each suite file.Test code only — no production file changed.
Measured (mgmt VM, node v22.19.0,
run-tests.sh)/tmpinventory when this was measured:/tmp/sandbox-init-fixture-*/tmp/sandbox-init-agent-*One full suite run before the fix (measured twice, same result):
sandbox-init-fixture-*sandbox-init-*Per-family delta for that run:
fixture+44,agent+9,slice+6,origin+5,e2e+6,username+4,hostile+2,driver/idempotent/prune/restart/empty/tiny/good/escape/shquote+1 each.After the fix:
sandbox-init-*deltaSuite result:
run-tests.sh: OK — 64/64 passed (floor 60), 0 failed(was 60/60; the floor is untouched — the +4 is the three new tests intemp-dirs.test.mjsplus one more no-test file that node's default discovery counts, exactly astest/fixtures.mjsalready was).Negative controls (proving the measurement is not vacuous)
mkdtempSyncingit-slice.test.mjsfails the guard:git-slice.test.mjs calls mkdtempSync directly — use makeTempDir().render.test.mjsalone leaks again:+42dirs from that one file.How cleanup works
test/temp-dirs.mjs:makeTempDir(prefix)—mkdtempunder$TMPDIR, recorded.trackTempDir(dir)— record a caller-owned dir.cleanupTempDirs()—rm -rfthe tracked dirs, idempotent, tolerates an already-removed dir (force), reports anything it could not remove instead of leaking silently.Each suite file calls
after(cleanupTempDirs)once. A top-levelafterhook runs after every test in the file including after failures (verified on node 22 with a failing test and on the full suite with a deliberately failing test —+0both times). Nothing here importsnode:test:fixtures.mjsis also imported by the LD1.3 proof harness, which is not a test file.Cleanup is scoped strictly to tracked dirs — no globbing, no prefix sweep — so a directory this suite did not create is never touched (tested).
Files changed
agent-sandbox/pi-image/sandbox-init/test/temp-dirs.mjsagent-sandbox/pi-image/sandbox-init/test/temp-dirs.test.mjsmkdtempSyncin any suite file" source guard + untracked-dir-survives caseagent-sandbox/pi-image/sandbox-init/test/fixtures.mjsbuildFixturePackagedefaultbaseDir→makeTempDir("sandbox-init-fixture-")agent-sandbox/pi-image/sandbox-init/test/render.test.mjsscratch()→makeTempDir,after(cleanupTempDirs)agent-sandbox/pi-image/sandbox-init/test/security.test.mjsscratch()→makeTempDir,after(cleanupTempDirs)agent-sandbox/pi-image/sandbox-init/test/sandbox-init.e2e.test.mjssandbox()root →makeTempDir,after(cleanupTempDirs)agent-sandbox/pi-image/sandbox-init/test/git-slice.test.mjsmakeOrigin()/scratch()→makeTempDir,after(cleanupTempDirs)agent-sandbox/pi-image/sandbox-init/test/run-tests-guard.test.mjsmakeTempDir,after(cleanupTempDirs)for file in ...; git diff --name-only— every path is underagent-sandbox/pi-image/sandbox-init/test/. Nolib/, nosandbox-init.mjs, no manifest, no workflow.Notes for the reviewer
COPY sandbox-init/ /opt/sandbox-init/), so the new helper ships with the suite; CI's in-imagerun-tests.shstep exercises it.forgejo-fake-openbao-*/redact-test-*): tracked created dirs + the test framework's own teardown hook./tmpdebris is not deleted by this change: cleanup is scoped to dirs this process created. Removing the ~7.6k stale dirs on the mgmt VM is a separate, deliberate action.The sandbox-init suites build real trees under $TMPDIR and never removed them. Measured on the mgmt VM before this change: 5,829 `/tmp/sandbox-init-fixture-*` and 1,809 `/tmp/sandbox-init-agent-*`, and a single full `run-tests.sh` run added another 44 fixture dirs and ~86 sandbox-init-* dirs in total (fixture, agent, origin, slice, empty, tiny, good, e2e, ...). Every maker now hands its directory to test/temp-dirs.mjs, and each suite file removes what it made from a top-level node:test `after` hook: makeTempDir(prefix) mkdtemp under $TMPDIR + track trackTempDir(dir) track a caller-owned dir cleanupTempDirs() rm -rf tracked dirs only; idempotent; tolerates already-removed dirs Makers covered: test/fixtures.mjs (the buildFixturePackage default baseDir), render.test.mjs and security.test.mjs scratch(), sandbox-init.e2e.test.mjs sandbox(), git-slice.test.mjs makeOrigin()/scratch(), and run-tests-guard.test.mjs's three synthetic suite dirs. The hook runs on the failure path too (a top-level `after` runs after every test in the file, including failures), cleanup is scoped strictly to tracked dirs — no prefix sweep, so nothing this suite did not create is touched — and temp-dirs.test.mjs guards both the helper's behaviour and a source scan that refuses a return to bare `mkdtempSync` in any suite file. Measured after: +0 dirs on three consecutive full suite runs and +0 on a run with a deliberately failing test. Test code only; no production file changes.Verdict of record — ld-reviewer — head
b1adb7fe75: APPROVEmodel: deepseek-flash
session: 01a1b4ba-3efa-702c-a118-4393a70e5546
Blockers
None.
Exposure
git objects of Homelab/infra-core at 0cf5da36..b1adb7fe only; no PR comments, census, or ticket thread read; my only write is this verdict posted as ld-reviewer (the suite was additionally run once from a
git archivecopy under /tmp, removed afterwards — nothing written to the repo, any PR, or Plane).Verdict of record — ld-reviewer — head
b1adb7fe75: APPROVEmodel: deepseek-flash
session: 01a1b4ba-3f26-702c-a118-4395d4af7644
Blockers
None.
Exposure
git objects of Homelab/infra-core at 0cf5da36..b1adb7fe only; no PR comments, census, or ticket thread read; my only write is this verdict posted as ld-reviewer.