From 38f446bb6ff651ace06ce93da572fe9ad3f66b4b Mon Sep 17 00:00:00 2001 From: Lloyd Date: Thu, 23 Jul 2026 13:24:40 -0700 Subject: [PATCH] fix(test): isolate $HOME in mechanical.test.ts so E2E suite stops clobbering user config (#434) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit mechanical.test.ts shells out to `gbrain init --non-interactive`, `gbrain import`, and similar commands via Bun.spawnSync. The four `cliEnv()` helpers in this file forward `process.env` unchanged, so `gbrain init` ends up calling saveConfig() against the developer's real $HOME/.gbrain/config.json, overwriting their production database_url with the test container's URL on every `bun run test:e2e` invocation. Sibling test/e2e/migration-flow.test.ts already solved this with a module-level temp HOME and an afterAll restore. Mirror that pattern in mechanical.test.ts. Verified by md5'ing ~/.gbrain/config.json before and after running the Setup Journey, Init Edge Cases, Schema Idempotency, RLS Verification, Doctor Command, and Parallel Import describe blocks — config hash is identical pre and post (26 passing tests, 0 failures, 0 mutations to the user's real config). Co-authored-by: Seth Armbrust Co-authored-by: Claude Opus 4.7 (1M context) --- test/e2e/mechanical.test.ts | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/test/e2e/mechanical.test.ts b/test/e2e/mechanical.test.ts index 3b21e1e92..edd3477d7 100644 --- a/test/e2e/mechanical.test.ts +++ b/test/e2e/mechanical.test.ts @@ -24,6 +24,29 @@ import { importFromContent } from '../../src/core/import-file.ts'; const skip = !hasDatabase(); const describeE2E = skip ? describe.skip : describe; +// HOME isolation. Several tests in this file shell out to `gbrain init` and +// `gbrain import` via Bun.spawnSync. `gbrain init` calls saveConfig() which +// writes to $HOME/.gbrain/config.json, and `gbrain import` writes a sync +// bookmark to the same directory. Without isolating $HOME, these tests +// clobber the user's real production gbrain config every time `bun run +// test:e2e` is executed. Sibling test/e2e/migration-flow.test.ts solved +// this with a module-level temp HOME; mirror that pattern here so the +// E2E suite stops mutating user state. +let _origHome: string | undefined; +let _tmpHome: string | undefined; +if (!skip) { + _origHome = process.env.HOME; + _tmpHome = mkdtempSync(join(tmpdir(), 'gbrain-e2e-mechanical-home-')); + process.env.HOME = _tmpHome; +} + +afterAll(() => { + if (skip) return; + if (_origHome === undefined) delete process.env.HOME; + else process.env.HOME = _origHome; + try { if (_tmpHome) rmSync(_tmpHome, { recursive: true, force: true }); } catch { /* best-effort */ } +}); + function makeCtx(opts: { remote?: boolean } = {}): OperationContext { return { engine: getEngine(),