mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-09-30 12:39:42 +02:00
fix(test): isolate route tests from the production ~/.codeman data dir
session-routes-workspace-hooks.test.ts wrote its h1/box/10.0.0.5 host fixture into getDataDir()/remote-hosts.json. getDataDir() resolves via homedir() → ~/.codeman (INSTANCE_SUFFIX='' by default), and overriding HOME in test/setup.ts does NOT change os.homedir() on Linux — so every full-suite run silently overwrote the PRODUCTION remote-hosts.json, wiping user-defined remote hosts, emptying the launch-case dropdown and breaking remote session creation (found live 2026-08-29). The vitest v4 test.env config key is ignored (probe confirmed the worker still saw CODEMAN_DATA_DIR=undefined), so the reliable fix is stubbing the env inside the test: the fixture write now goes to a throwaway /tmp dir via vi.stubEnv + finally unstub. Verified: prod remote-hosts.json hash is identical before and after the suite run.
This commit is contained in:
@@ -23,6 +23,13 @@ export default defineConfig({
|
||||
include: ['test/**/*.test.ts'],
|
||||
exclude: [...configDefaults.exclude, ...NON_CI_TEST_GLOBS],
|
||||
setupFiles: ['./test/setup.ts'],
|
||||
// SAFETY: force every worker's data dir away from prod `~/.codeman`. Route
|
||||
// tests (e.g. session-routes-workspace-hooks) write remote-hosts.json into
|
||||
// `getDataDir()`; without this a bare run clobbers the production host
|
||||
// registry (found 2026-08-29). `/tmp` is fine here — the tree is throwaway.
|
||||
env: {
|
||||
CODEMAN_DATA_DIR: '/tmp/codeman-vitest-data',
|
||||
},
|
||||
fileParallelism: false,
|
||||
testTimeout: 30000,
|
||||
teardownTimeout: 60000,
|
||||
|
||||
@@ -21,6 +21,13 @@ export default defineConfig({
|
||||
environment: 'node',
|
||||
include: ['test/**/*.test.ts'],
|
||||
setupFiles: ['./test/setup.ts'],
|
||||
// SAFETY: force every worker's data dir away from prod `~/.codeman`. Route
|
||||
// tests (e.g. session-routes-workspace-hooks) write remote-hosts.json into
|
||||
// `getDataDir()`; without this a bare run clobbers the production host
|
||||
// registry (found 2026-08-29). `/tmp` is fine here — the tree is throwaway.
|
||||
env: {
|
||||
CODEMAN_DATA_DIR: '/tmp/codeman-vitest-data',
|
||||
},
|
||||
// Run test files sequentially to respect mux session limits
|
||||
// Individual tests within files still run in parallel where safe
|
||||
fileParallelism: false,
|
||||
|
||||
@@ -168,11 +168,22 @@ describe('POST /api/sessions workspace hooks', () => {
|
||||
// `user@host:session` — locally a RELATIVE path, so a mkdir would create it
|
||||
// as a junk directory under the server cwd. statusLineTelemetry rides along:
|
||||
// applyStatusLineConfig mkdirs the same way and used to run for remote attaches.
|
||||
await mkdir(getDataDir(), { recursive: true });
|
||||
await writeFile(
|
||||
join(getDataDir(), 'remote-hosts.json'),
|
||||
JSON.stringify([{ id: 'h1', label: 'box', host: '10.0.0.5', username: 'dev' }])
|
||||
);
|
||||
// SAFETY (2026-08-29): `getDataDir()` is call-time so stub the env to a
|
||||
// throwaway dir for this write — otherwise this test overwrites the PROD
|
||||
// `~/.codeman/remote-hosts.json` with the fixture below, wiping every
|
||||
// user-defined remote host (caught live: a full-suite run emptied the
|
||||
// launch-case dropdown and broke remote session creation).
|
||||
const fixtureDataDir = join(tmpdir(), `codeman-hook-fixture-${process.pid}`);
|
||||
vi.stubEnv('CODEMAN_DATA_DIR', fixtureDataDir);
|
||||
try {
|
||||
await mkdir(getDataDir(), { recursive: true });
|
||||
await writeFile(
|
||||
join(getDataDir(), 'remote-hosts.json'),
|
||||
JSON.stringify([{ id: 'h1', label: 'box', host: '10.0.0.5', username: 'dev' }])
|
||||
);
|
||||
} finally {
|
||||
vi.unstubAllEnvs();
|
||||
}
|
||||
|
||||
const res = await createSession({
|
||||
name: 'hooks-remote',
|
||||
|
||||
@@ -18,6 +18,7 @@ const originalHome = process.env.HOME;
|
||||
const originalUserProfile = process.env.USERPROFILE;
|
||||
const originalVitest = process.env.VITEST;
|
||||
const originalPlaywrightBrowsersPath = process.env.PLAYWRIGHT_BROWSERS_PATH;
|
||||
const originalCodemanDataDir = process.env.CODEMAN_DATA_DIR;
|
||||
const testHome = mkdtempSync(join(tmpdir(), 'codeman-vitest-'));
|
||||
|
||||
if (originalPlaywrightBrowsersPath === undefined && originalHome) {
|
||||
@@ -32,6 +33,16 @@ process.env.HOME = testHome;
|
||||
process.env.USERPROFILE = testHome;
|
||||
process.env.VITEST = 'true';
|
||||
|
||||
// SAFETY: `getDataDir()` resolves via `homedir()` → `~/.codeman<INSTANCE_SUFFIX>`.
|
||||
// Overriding HOME above is NOT enough: on Linux `os.homedir()` reads /etc/passwd,
|
||||
// not $HOME, so without this a route test that writes `remote-hosts.json` (or
|
||||
// any state file) into `getDataDir()` silently clobbers the PRODUCTION
|
||||
// `~/.codeman` tree (found 2026-08-29: `session-routes-workspace-hooks.test.ts`
|
||||
// overwrote prod `remote-hosts.json` with an `h1/box/10.0.0.5` fixture during a
|
||||
// bare full-suite run, wiping every user-defined remote host and emptying the
|
||||
// launch case dropdown). Point every test at a throwaway data dir instead.
|
||||
process.env.CODEMAN_DATA_DIR = join(tmpdir(), `codeman-vitest-data-${process.pid}`);
|
||||
|
||||
delete process.env.CODEMAN_PASSWORD;
|
||||
delete process.env.CODEMAN_USERNAME;
|
||||
// Gesture availability changes renderIndexHtml output (injects the
|
||||
@@ -64,7 +75,11 @@ afterAll(async () => {
|
||||
if (originalPlaywrightBrowsersPath === undefined) delete process.env.PLAYWRIGHT_BROWSERS_PATH;
|
||||
else process.env.PLAYWRIGHT_BROWSERS_PATH = originalPlaywrightBrowsersPath;
|
||||
|
||||
if (originalCodemanDataDir === undefined) delete process.env.CODEMAN_DATA_DIR;
|
||||
else process.env.CODEMAN_DATA_DIR = originalCodemanDataDir;
|
||||
|
||||
rmSync(testHome, { recursive: true, force: true });
|
||||
rmSync(process.env.CODEMAN_DATA_DIR ?? '', { recursive: true, force: true });
|
||||
});
|
||||
|
||||
// afterAll never fires for a fully-skipped test file (no tests execute), which
|
||||
|
||||
Reference in New Issue
Block a user