fix(e2e): bound bundled runtime smoke ports

This commit is contained in:
Vincent Koc
2026-06-18 19:51:39 +02:00
parent 8151a547c5
commit 3125cdacb5
2 changed files with 28 additions and 6 deletions

View File

@@ -8,6 +8,8 @@ import { setTimeout as delay } from "node:timers/promises";
import { fileURLToPath } from "node:url";
const TOKEN = "bundled-plugin-runtime-smoke-token";
const RUNTIME_PORT_BASE_ENV = "OPENCLAW_BUNDLED_PLUGIN_RUNTIME_PORT_BASE";
const TCP_PORT_MAX = 65535;
const OUTPUT_CAPTURE_CHARS = readPositiveIntEnv(
"OPENCLAW_BUNDLED_PLUGIN_RUNTIME_OUTPUT_CHARS",
1024 * 1024,
@@ -87,6 +89,17 @@ function readNonNegativeInt(raw, fallback, name) {
return parsed;
}
export function resolveRuntimeSmokePort(pluginIndex, offset = 0, env = process.env) {
const base = readPositiveInt(env[RUNTIME_PORT_BASE_ENV], 19000, RUNTIME_PORT_BASE_ENV);
const port = base + pluginIndex * 3 + offset;
if (!Number.isSafeInteger(port) || port > TCP_PORT_MAX) {
throw new Error(
`${RUNTIME_PORT_BASE_ENV} with bundled plugin runtime index ${pluginIndex} and offset ${offset} must resolve to a TCP port from 1 to 65535. Got: ${port}`,
);
}
return port;
}
function readJson(file) {
return JSON.parse(fs.readFileSync(file, "utf8"));
}
@@ -966,8 +979,7 @@ async function smokePlugin(pluginId, pluginDir, requiresConfig, pluginIndex, plu
}
const manifest = loadManifest(pluginDir, pluginRoot);
const plan = buildPluginPlan(manifest);
const port =
readPositiveIntEnv("OPENCLAW_BUNDLED_PLUGIN_RUNTIME_PORT_BASE", 19000) + pluginIndex * 3;
const port = resolveRuntimeSmokePort(pluginIndex);
const config = ensureGatewayConfig(
activateSmokePlugin(readConfig(), pluginId, plan.channels),
port,
@@ -1299,8 +1311,7 @@ async function smokeTtsGlobalDisable(pluginId, pluginDir, provider, pluginIndex,
console.log(`Global-disable TTS smoke skipped for ${pluginId}: no speech provider contract`);
return;
}
const port =
readPositiveIntEnv("OPENCLAW_BUNDLED_PLUGIN_RUNTIME_PORT_BASE", 19000) + pluginIndex * 3 + 1;
const port = resolveRuntimeSmokePort(pluginIndex, 1);
const env = createIsolatedStateEnv(`tts-disabled-${pluginId}`);
writeConfig(
ensureGatewayConfig(
@@ -1352,8 +1363,7 @@ async function smokeOpenAiTts(pluginIndex) {
console.log("OpenAI key-backed TTS smoke skipped: OPENAI_API_KEY is not set");
return;
}
const port =
readPositiveIntEnv("OPENCLAW_BUNDLED_PLUGIN_RUNTIME_PORT_BASE", 19000) + pluginIndex * 3 + 2;
const port = resolveRuntimeSmokePort(pluginIndex, 2);
const env = createIsolatedStateEnv("tts-openai-live");
writeConfig(
ensureGatewayConfig(

View File

@@ -266,6 +266,18 @@ describe("bundled plugin install/uninstall probe", () => {
expect(result.stderr).toContain("invalid bundled plugin runtime index: 1e3");
});
it("rejects bundled plugin runtime ports outside the TCP range", async () => {
const runtimeSmoke = await import(pathToFileURL(runtimeSmokePath).href);
const env = {
OPENCLAW_BUNDLED_PLUGIN_RUNTIME_PORT_BASE: "65533",
};
expect(runtimeSmoke.resolveRuntimeSmokePort(0, 2, env)).toBe(65535);
expect(() => runtimeSmoke.resolveRuntimeSmokePort(1, 0, env)).toThrow(
"OPENCLAW_BUNDLED_PLUGIN_RUNTIME_PORT_BASE with bundled plugin runtime index 1 and offset 0 must resolve to a TCP port from 1 to 65535. Got: 65536",
);
});
it("caps noisy runtime gateway logs", async () => {
const runtimeSmoke = await importRuntimeSmokeWithEnv({
OPENCLAW_BUNDLED_PLUGIN_RUNTIME_GATEWAY_LOG_BYTES: "64",