fix: isolate orchestrate tests from user's ~/.spawn history (#2398)

The orchestrate test suite called runOrchestration (which internally
calls saveSpawnRecord) without setting SPAWN_HOME to a temp directory.
Every test run wrote ~20 fake records into the user's real history,
eventually filling it with 100 connectionless "testagent" entries
and wiping all real spawn history.

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Ahmed Abushagur 2026-03-09 15:46:19 -07:00 committed by GitHub
parent e182806eee
commit 06796ec95c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 30 additions and 2 deletions

View file

@ -1,6 +1,6 @@
{
"name": "@openrouter/spawn",
"version": "0.15.31",
"version": "0.15.32",
"type": "module",
"bin": {
"spawn": "cli.js"

View file

@ -10,7 +10,10 @@
* bleed into with-retry-result.test.ts which tests the real wrapSshCall.
*/
import { beforeEach, describe, expect, it, mock, spyOn } from "bun:test";
import { afterEach, beforeEach, describe, expect, it, mock, spyOn } from "bun:test";
import { mkdirSync, rmSync } from "node:fs";
import { homedir } from "node:os";
import { join } from "node:path";
import { isNumber } from "../shared/type-guards.js";
// ── Mock oauth + tarball (needed to avoid interactive prompts / network) ──
@ -101,9 +104,18 @@ describe("runOrchestration", () => {
let exitSpy: ReturnType<typeof spyOn>;
let capturedExitCode: number | undefined;
let stderrSpy: ReturnType<typeof spyOn>;
let testDir: string;
let savedSpawnHome: string | undefined;
beforeEach(() => {
capturedExitCode = undefined;
// Isolate history writes to a temp directory so tests never pollute ~/.spawn
testDir = join(homedir(), `.spawn-test-orch-${Date.now()}-${Math.random()}`);
mkdirSync(testDir, {
recursive: true,
});
savedSpawnHome = process.env.SPAWN_HOME;
process.env.SPAWN_HOME = testDir;
// Skip GitHub auth prompts during tests
process.env.SPAWN_SKIP_GITHUB_AUTH = "1";
stderrSpy = spyOn(process.stderr, "write").mockImplementation(() => true);
@ -117,6 +129,22 @@ describe("runOrchestration", () => {
mockTryTarballInstall.mockImplementation(() => Promise.resolve(false));
});
afterEach(() => {
if (savedSpawnHome !== undefined) {
process.env.SPAWN_HOME = savedSpawnHome;
} else {
delete process.env.SPAWN_HOME;
}
try {
rmSync(testDir, {
recursive: true,
force: true,
});
} catch {
// best-effort cleanup
}
});
it("calls all cloud lifecycle methods in correct order", async () => {
const callOrder: string[] = [];
const cloud = createMockCloud({