Files
OmniRoute/tests/unit/sync-env.test.ts
Diego Rodrigues de Sa e Souza 3d4f3e4960 test(infra): retry recursive temp-dir removal instead of failing a shard on ENOTEMPTY (#11966) (#11968)
* test(infra): retry recursive temp-dir removal instead of failing a shard on ENOTEMPTY (#11966)

Two shards on release/v3.8.51 went red in one day with the same signature —
"ENOTEMPTY, Directory not empty: /tmp/omniroute-<test>-XXXXXX" — from
combo-same-provider-cascade (Unit Tests fast-path 4/4, on a PR that touches only
.github/) and auth-policy-embeddings-webfetch-7785 (the 20k-test TIA step). Both pass
alone and on re-run: the cleanup races something still writing into the directory
(SQLite WAL/-shm checkpoint, a worker, the backup) and under a loaded hosted runner
the window opens. 1154 test files do their own cleanup with
fs.rmSync(dir, { recursive: true, force: true }); 57 already asked for retries.

One-shot codemod (scripts/ad-hoc/codemod-rm-maxretries.mjs, kept for the record):
every rm / rmSync / rmdirSync option object with `recursive: true` and no
`maxRetries` gains `maxRetries: 5, retryDelay: 100` — Node itself then retries
ENOTEMPTY/EBUSY/EPERM for up to ~0.5 s before giving up. 2243 call sites in 1292
files under tests/, the shared tests/_setup/isolateDataDir.ts exit hook included.
Only the option object changes: no call site, assertion or import is touched.

Validation: prettier and ESLint (with the frozen suppressions) clean on all 1292
files; a random 20-file sample runs green (quota-redis-store hangs identically on
the untouched tree — it needs a Redis on localhost, an environment matter). The
four unit shards on this PR are the full run.

* fix(quality): let check-forgotten-sibling-tests read a 1,000-file diff

The gate shells out to `git diff` through execFileSync with Node's default 1 MB
maxBuffer; the 1,292-file codemod in this PR is the first diff large enough to
overflow it, and the gate died with `spawnSync git ENOBUFS` before comparing
anything. 64 MB is far above any real PR and costs nothing when unused.
2026-08-29 01:17:40 -03:00

193 lines
7.4 KiB
TypeScript

import test from "node:test";
import assert from "node:assert/strict";
import fs from "node:fs";
import os from "node:os";
import path from "node:path";
const { syncEnv } = (await import("../../scripts/dev/sync-env.mjs")) as {
syncEnv: (opts?: { rootDir?: string; quiet?: boolean; scope?: string }) => {
created: boolean;
added: number;
};
};
function createTempRoot(): string {
return fs.mkdtempSync(path.join(os.tmpdir(), "omniroute-sync-env-"));
}
function writeEnvExample(rootDir: string) {
fs.writeFileSync(
path.join(rootDir, ".env.example"),
[
"JWT_SECRET=",
"API_KEY_SECRET=",
"STORAGE_ENCRYPTION_KEY=",
"MACHINE_ID_SALT=",
"CLAUDE_OAUTH_CLIENT_ID=claude-default",
"CODEX_OAUTH_CLIENT_ID=codex-default",
'CLAUDE_USER_AGENT="claude-cli/2.1.219 (external, cli)"',
"# COMMENTED_KEY=skip-me",
"",
].join("\n"),
"utf8"
);
}
function writeOauthEnvExample(rootDir: string) {
fs.writeFileSync(
path.join(rootDir, ".env.example"),
[
"# ═══════════════════════════════════════════════════",
"# OAUTH PROVIDER CREDENTIALS",
"# ═══════════════════════════════════════════════════",
"CLAUDE_OAUTH_CLIENT_ID=claude-default",
"CODEX_OAUTH_CLIENT_ID=codex-default",
"# ─────────────────────────────────────────────────────────────────────────────",
"# Provider User-Agent Overrides (optional — customize per-provider UA headers)",
"# ─────────────────────────────────────────────────────────────────────────────",
"JWT_SECRET=should-not-be-copied",
"",
].join("\n"),
"utf8"
);
}
test("syncEnv creates .env from .env.example and leaves runtime-owned secrets blank", () => {
const rootDir = createTempRoot();
// Temporarily override DATA_DIR so the encrypted-credentials guard doesn't
// find the user's real DB at ~/.omniroute/ during tests
const origDataDir = process.env.DATA_DIR;
try {
writeEnvExample(rootDir);
process.env.DATA_DIR = rootDir;
const result = syncEnv({ rootDir, quiet: true });
const envContent = fs.readFileSync(path.join(rootDir, ".env"), "utf8");
assert.deepEqual(result, { created: true, added: 7 });
// The three secrets the server provisions itself stay blank here. Filling
// them in the package directory hides ensureSecrets() (instrumentation-node),
// which restores them from the durable store or generates and persists them
// there — so a pre-filled value is silently replaced by a new one on every
// reinstall. STORAGE_ENCRYPTION_KEY was pulled out for that reason (#1622).
assert.match(envContent, /^JWT_SECRET=$/m);
assert.match(envContent, /^API_KEY_SECRET=$/m);
assert.match(envContent, /^STORAGE_ENCRYPTION_KEY=$/m);
assert.match(envContent, /^MACHINE_ID_SALT=omniroute-/m);
assert.match(envContent, /^CLAUDE_OAUTH_CLIENT_ID=claude-default$/m);
assert.match(envContent, /^CODEX_OAUTH_CLIENT_ID=codex-default$/m);
assert.match(envContent, /^CLAUDE_USER_AGENT="claude-cli\/2\.1\.219 \(external, cli\)"$/m);
assert.doesNotMatch(envContent, /^COMMENTED_KEY=/m);
} finally {
process.env.DATA_DIR = origDataDir;
fs.rmSync(rootDir, { recursive: true, force: true, maxRetries: 5, retryDelay: 100 });
}
});
test("syncEnv appends only missing keys and preserves existing values", () => {
const rootDir = createTempRoot();
const origDataDir = process.env.DATA_DIR;
try {
writeEnvExample(rootDir);
fs.writeFileSync(
path.join(rootDir, ".env"),
[
"JWT_SECRET=my-custom-secret-that-should-stay",
"CLAUDE_OAUTH_CLIENT_ID=custom-claude",
"",
].join("\n"),
"utf8"
);
process.env.DATA_DIR = rootDir;
const result = syncEnv({ rootDir, quiet: true });
const envContent = fs.readFileSync(path.join(rootDir, ".env"), "utf8");
assert.deepEqual(result, { created: false, added: 5 });
assert.match(envContent, /^JWT_SECRET=my-custom-secret-that-should-stay$/m);
assert.match(envContent, /^CLAUDE_OAUTH_CLIENT_ID=custom-claude$/m);
assert.match(envContent, /^API_KEY_SECRET=$/m);
assert.match(envContent, /^STORAGE_ENCRYPTION_KEY=$/m);
assert.match(envContent, /^MACHINE_ID_SALT=omniroute-/m);
assert.match(envContent, /^CODEX_OAUTH_CLIENT_ID=codex-default$/m);
assert.match(envContent, /^CLAUDE_USER_AGENT=claude-cli\/2\.1\.219 \(external, cli\)$/m);
assert.match(envContent, /Auto-added by sync-env/);
} finally {
process.env.DATA_DIR = origDataDir;
fs.rmSync(rootDir, { recursive: true, force: true, maxRetries: 5, retryDelay: 100 });
}
});
test("syncEnv treats quoted and unquoted values as equivalent", () => {
const rootDir = createTempRoot();
const origDataDir = process.env.DATA_DIR;
try {
writeEnvExample(rootDir);
fs.writeFileSync(
path.join(rootDir, ".env"),
[
"JWT_SECRET=jwt-secret",
"API_KEY_SECRET=api-secret",
"STORAGE_ENCRYPTION_KEY=storage-secret",
"MACHINE_ID_SALT=machine-salt",
"CLAUDE_OAUTH_CLIENT_ID=claude-default",
"CODEX_OAUTH_CLIENT_ID=codex-default",
'CLAUDE_USER_AGENT="claude-cli/2.1.219 (external, cli)"',
"",
].join("\n"),
"utf8"
);
process.env.DATA_DIR = rootDir;
const result = syncEnv({ rootDir, quiet: true });
assert.deepEqual(result, { created: false, added: 0 });
} finally {
process.env.DATA_DIR = origDataDir;
fs.rmSync(rootDir, { recursive: true, force: true, maxRetries: 5, retryDelay: 100 });
}
});
test("syncEnv is idempotent when .env is already complete", () => {
const rootDir = createTempRoot();
const origDataDir = process.env.DATA_DIR;
try {
writeEnvExample(rootDir);
process.env.DATA_DIR = rootDir;
syncEnv({ rootDir, quiet: true });
const before = fs.readFileSync(path.join(rootDir, ".env"), "utf8");
const result = syncEnv({ rootDir, quiet: true });
const after = fs.readFileSync(path.join(rootDir, ".env"), "utf8");
assert.deepEqual(result, { created: false, added: 0 });
assert.equal(after, before);
} finally {
process.env.DATA_DIR = origDataDir;
fs.rmSync(rootDir, { recursive: true, force: true, maxRetries: 5, retryDelay: 100 });
}
});
test("syncEnv oauth scope only copies oauth defaults", () => {
const rootDir = createTempRoot();
try {
writeOauthEnvExample(rootDir);
const result = syncEnv({ rootDir, quiet: true, scope: "oauth" });
const envContent = fs.readFileSync(path.join(rootDir, ".env"), "utf8");
assert.deepEqual(result, { created: true, added: 2 });
assert.match(envContent, /^CLAUDE_OAUTH_CLIENT_ID=claude-default$/m);
assert.match(envContent, /^CODEX_OAUTH_CLIENT_ID=codex-default$/m);
assert.doesNotMatch(envContent, /^JWT_SECRET=/m);
assert.doesNotMatch(envContent, /^Provider User-Agent Overrides/m);
} finally {
fs.rmSync(rootDir, { recursive: true, force: true, maxRetries: 5, retryDelay: 100 });
}
});