mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-09-16 03:42:21 +03:00
* test(infra): retry recursive temp-dir removal on main (main twin of #11968)
`main` has been red since b342c1a361 on the vitest and integration gates:
✖ tests/unit/autoCombo/provider-family-combos.test.ts > auto/<family>
✖ chat pipeline applies Codex OAuth fingerprint and priority tier inside combos
Both call resetStorage() from beforeEach, which does an fs.rmSync(TEST_DATA_DIR,
{recursive: true, force: true}) with no retry, and intermittently loses the race
with a not-yet-released SQLite handle (ENOTEMPTY).
release/v3.8.51 fixed this in #11968 with a mechanical codemod adding
maxRetries/retryDelay to every recursive rm/rmSync/rmdirSync under tests/, but
that PR landed only on the release branch. Because main only receives work at
the release squash, it stayed broken for the whole cycle — and repo-wide gates
then turn every open PR into main red on checks unrelated to their diff.
This is the --base main twin: re-runs the same codemod that already shipped on
the release branch (scripts/ad-hoc/codemod-rm-maxretries.mjs), so the two
branches converge on identical test-teardown semantics. Test-only; no product
logic is touched.
The remaining three failures reported on #12133 (unit full suite exceeding its
4800s ceiling, package-artifact exceeding 1200s, and the boot-smoke that is
skipped as a consequence) are runner-contention timeouts, not code defects —
validate-release-green.mjs runs those heavy gates concurrently on one shared
hosted runner. There is no fix to port for those.
* chore(scripts): carry the rm-maxretries codemod onto main alongside its output
The codemod that generated the previous commit lives in the repo on
release/v3.8.51 (added by #11968) but was never on main. Bringing it over keeps
the tool next to the change it produced, so the transformation stays
reproducible and auditable from either branch.
165 lines
6.0 KiB
TypeScript
165 lines
6.0 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";
|
|
import { pathToFileURL } from "node:url";
|
|
|
|
/**
|
|
* POST /api/cli-tools/apply writes host CLI config files. Inside a container
|
|
* with no bind mount that write is thrown away with the container, so the route
|
|
* must refuse with a structured 422 instead of reporting success.
|
|
*/
|
|
|
|
const routePath = path.join(process.cwd(), "src/app/api/cli-tools/apply/route.ts");
|
|
const originalEnv = { ...process.env };
|
|
const tempDirs = new Set<string>();
|
|
|
|
async function importRoute(label: string) {
|
|
return import(`${pathToFileURL(routePath).href}?case=${label}-${Date.now()}-${Math.random()}`);
|
|
}
|
|
|
|
function restoreEnv() {
|
|
for (const key of Object.keys(process.env)) {
|
|
if (!(key in originalEnv)) delete process.env[key];
|
|
}
|
|
Object.assign(process.env, originalEnv);
|
|
}
|
|
|
|
test.afterEach(restoreEnv);
|
|
|
|
// The auth guard reads settings, which opens the SQLite singleton. Releasing it
|
|
// before the temp dirs go away keeps the node:test runner from hanging on an
|
|
// open handle (see AGENTS.md → "Database Handles in Tests").
|
|
test.after(async () => {
|
|
try {
|
|
const { resetDbInstance } = await import("../../src/lib/db/core.ts");
|
|
resetDbInstance();
|
|
} catch {
|
|
// the DB was never opened
|
|
}
|
|
for (const dir of tempDirs) fs.rmSync(dir, { recursive: true, force: true, maxRetries: 5, retryDelay: 100 });
|
|
});
|
|
|
|
function applyRequest(body: Record<string, unknown>) {
|
|
return new Request("http://localhost:20128/api/cli-tools/apply", {
|
|
method: "POST",
|
|
headers: { "content-type": "application/json" },
|
|
body: JSON.stringify({ toolId: "codex", apiKey: "sk-test", ...body }),
|
|
});
|
|
}
|
|
|
|
test("refuses with 422 and does not write when the target is container-ephemeral", async () => {
|
|
// OMNIROUTE_CONTAINER forces detection; the fake HOME has no bind mount, so
|
|
// the target classifies as ephemeral.
|
|
const fakeHome = fs.mkdtempSync(path.join(os.tmpdir(), "or-apply-ephemeral-"));
|
|
tempDirs.add(fakeHome);
|
|
process.env.OMNIROUTE_CONTAINER = "1";
|
|
process.env.HOME = fakeHome;
|
|
process.env.USERPROFILE = fakeHome;
|
|
delete process.env.OMNIROUTE_ALLOW_CONTAINER_CONFIG_WRITE;
|
|
|
|
const { POST } = await importRoute("ephemeral");
|
|
const response = await POST(applyRequest({}));
|
|
|
|
assert.equal(response.status, 422);
|
|
const body = await response.json();
|
|
assert.equal(body.containerEphemeralTarget, true);
|
|
assert.equal(body.hostSetupCommand, "omniroute setup-codex");
|
|
assert.match(body.error, /Refusing to write/);
|
|
assert.match(body.error, /omniroute connect/);
|
|
// Nothing may hit disk.
|
|
assert.equal(fs.existsSync(path.join(fakeHome, ".codex")), false);
|
|
});
|
|
|
|
test("the 422 body carries no stack trace", async () => {
|
|
const fakeHome = fs.mkdtempSync(path.join(os.tmpdir(), "or-apply-stack-"));
|
|
tempDirs.add(fakeHome);
|
|
process.env.OMNIROUTE_CONTAINER = "1";
|
|
process.env.HOME = fakeHome;
|
|
process.env.USERPROFILE = fakeHome;
|
|
|
|
const { POST } = await importRoute("nostack");
|
|
const body = await (await POST(applyRequest({}))).json();
|
|
|
|
assert.ok(!body.error.includes("at /"), "error must not leak a stack trace");
|
|
assert.ok(!body.error.includes(".ts:"), "error must not leak source locations");
|
|
});
|
|
|
|
test("dry-run still previews the config inside a container", async () => {
|
|
const fakeHome = fs.mkdtempSync(path.join(os.tmpdir(), "or-apply-dry-"));
|
|
tempDirs.add(fakeHome);
|
|
process.env.OMNIROUTE_CONTAINER = "1";
|
|
process.env.HOME = fakeHome;
|
|
process.env.USERPROFILE = fakeHome;
|
|
|
|
const { POST } = await importRoute("dryrun");
|
|
const response = await POST(applyRequest({ dryRun: true }));
|
|
|
|
assert.equal(response.status, 200);
|
|
const body = await response.json();
|
|
assert.equal(body.dryRun, true);
|
|
});
|
|
|
|
test("OMNIROUTE_ALLOW_CONTAINER_CONFIG_WRITE lets the write through", async () => {
|
|
const fakeHome = fs.mkdtempSync(path.join(os.tmpdir(), "or-apply-override-"));
|
|
tempDirs.add(fakeHome);
|
|
process.env.OMNIROUTE_CONTAINER = "1";
|
|
process.env.OMNIROUTE_ALLOW_CONTAINER_CONFIG_WRITE = "true";
|
|
process.env.HOME = fakeHome;
|
|
process.env.USERPROFILE = fakeHome;
|
|
|
|
const { POST } = await importRoute("override");
|
|
const response = await POST(applyRequest({}));
|
|
|
|
assert.equal(response.status, 200);
|
|
const body = await response.json();
|
|
assert.equal(body.success, true);
|
|
assert.ok(fs.existsSync(body.configPath), `expected ${body.configPath} to be written`);
|
|
});
|
|
|
|
test("the dashboard's guide-settings writer refuses the same way", async () => {
|
|
const fakeHome = fs.mkdtempSync(path.join(os.tmpdir(), "or-guide-ephemeral-"));
|
|
tempDirs.add(fakeHome);
|
|
process.env.OMNIROUTE_CONTAINER = "1";
|
|
process.env.HOME = fakeHome;
|
|
process.env.USERPROFILE = fakeHome;
|
|
delete process.env.OMNIROUTE_ALLOW_CONTAINER_CONFIG_WRITE;
|
|
|
|
const guideRoute = path.join(
|
|
process.cwd(),
|
|
"src/app/api/cli-tools/guide-settings/[toolId]/route.ts"
|
|
);
|
|
const { POST } = await import(`${pathToFileURL(guideRoute).href}?case=guide-${Date.now()}`);
|
|
|
|
const response = await POST(
|
|
new Request("http://localhost:20128/api/cli-tools/guide-settings/continue", {
|
|
method: "POST",
|
|
headers: { "content-type": "application/json" },
|
|
body: JSON.stringify({ baseUrl: "http://localhost:20128/v1", model: "glm/glm-5.2" }),
|
|
}),
|
|
{ params: Promise.resolve({ toolId: "continue" }) }
|
|
);
|
|
|
|
assert.equal(response.status, 422);
|
|
const body = await response.json();
|
|
assert.equal(body.containerEphemeralTarget, true);
|
|
assert.equal(body.hostSetupCommand, "omniroute setup-continue");
|
|
assert.equal(fs.existsSync(path.join(fakeHome, ".continue")), false);
|
|
});
|
|
|
|
test("a host environment applies the config normally", async () => {
|
|
const fakeHome = fs.mkdtempSync(path.join(os.tmpdir(), "or-apply-host-"));
|
|
tempDirs.add(fakeHome);
|
|
process.env.OMNIROUTE_CONTAINER = "0";
|
|
process.env.HOME = fakeHome;
|
|
process.env.USERPROFILE = fakeHome;
|
|
|
|
const { POST } = await importRoute("host");
|
|
const response = await POST(applyRequest({}));
|
|
|
|
assert.equal(response.status, 200);
|
|
const body = await response.json();
|
|
assert.equal(body.success, true);
|
|
});
|