fix(qa): pin gateway child control ui root

This commit is contained in:
Vincent Koc
2026-04-07 11:11:24 +01:00
committed by Peter Steinberger
parent f9f38a48e6
commit 82535771cd
3 changed files with 65 additions and 2 deletions

View File

@@ -1,5 +1,16 @@
import { describe, expect, it } from "vitest";
import { buildQaRuntimeEnv } from "./gateway-child.js";
import { mkdir, mkdtemp, rm, writeFile } from "node:fs/promises";
import os from "node:os";
import path from "node:path";
import { afterEach, describe, expect, it } from "vitest";
import { buildQaRuntimeEnv, resolveQaControlUiRoot } from "./gateway-child.js";
const cleanups: Array<() => Promise<void>> = [];
afterEach(async () => {
while (cleanups.length > 0) {
await cleanups.pop()?.();
}
});
function createParams(baseEnv?: NodeJS.ProcessEnv) {
return {
@@ -83,3 +94,27 @@ describe("buildQaRuntimeEnv", () => {
expect(env.OPENCLAW_LIVE_GEMINI_KEY).toBeUndefined();
});
});
describe("resolveQaControlUiRoot", () => {
it("returns the built control ui root when repo assets exist", async () => {
const repoRoot = await mkdtemp(path.join(os.tmpdir(), "qa-control-ui-root-"));
cleanups.push(async () => {
await rm(repoRoot, { recursive: true, force: true });
});
const controlUiRoot = path.join(repoRoot, "dist", "control-ui");
await mkdir(controlUiRoot, { recursive: true });
await writeFile(path.join(controlUiRoot, "index.html"), "<html></html>", "utf8");
expect(resolveQaControlUiRoot({ repoRoot })).toBe(controlUiRoot);
});
it("returns undefined when control ui is disabled or not built", async () => {
const repoRoot = await mkdtemp(path.join(os.tmpdir(), "qa-control-ui-root-missing-"));
cleanups.push(async () => {
await rm(repoRoot, { recursive: true, force: true });
});
expect(resolveQaControlUiRoot({ repoRoot })).toBeUndefined();
expect(resolveQaControlUiRoot({ repoRoot, controlUiEnabled: false })).toBeUndefined();
});
});

View File

@@ -1,5 +1,6 @@
import { spawn } from "node:child_process";
import { randomUUID } from "node:crypto";
import { existsSync } from "node:fs";
import fs from "node:fs/promises";
import net from "node:net";
import os from "node:os";
@@ -184,6 +185,15 @@ async function runCliJson(params: { cwd: string; env: NodeJS.ProcessEnv; args: s
return text ? (JSON.parse(text) as unknown) : {};
}
export function resolveQaControlUiRoot(params: { repoRoot: string; controlUiEnabled?: boolean }) {
if (params.controlUiEnabled === false) {
return undefined;
}
const controlUiRoot = path.join(params.repoRoot, "dist", "control-ui");
const indexPath = path.join(controlUiRoot, "index.html");
return existsSync(indexPath) ? controlUiRoot : undefined;
}
export async function startQaGatewayChild(params: {
repoRoot: string;
providerBaseUrl?: string;
@@ -224,6 +234,10 @@ export async function startQaGatewayChild(params: {
providerBaseUrl: params.providerBaseUrl,
qaBusBaseUrl: params.qaBusBaseUrl,
workspaceDir,
controlUiRoot: resolveQaControlUiRoot({
repoRoot: params.repoRoot,
controlUiEnabled: params.controlUiEnabled,
}),
providerMode: params.providerMode,
primaryModel: params.primaryModel,
alternateModel: params.alternateModel,

View File

@@ -87,4 +87,18 @@ describe("buildQaGatewayConfig", () => {
expect(cfg.gateway?.controlUi).not.toHaveProperty("allowInsecureAuth");
expect(cfg.gateway?.controlUi).not.toHaveProperty("allowedOrigins");
});
it("pins control ui to a provided built root when available", () => {
const cfg = buildQaGatewayConfig({
bind: "loopback",
gatewayPort: 18789,
gatewayToken: "token",
qaBusBaseUrl: "http://127.0.0.1:43124",
workspaceDir: "/tmp/qa-workspace",
controlUiRoot: "/tmp/openclaw/dist/control-ui",
});
expect(cfg.gateway?.controlUi?.enabled).toBe(true);
expect(cfg.gateway?.controlUi?.root).toBe("/tmp/openclaw/dist/control-ui");
});
});