mirror of
https://github.com/openclaw/openclaw.git
synced 2026-06-03 10:04:07 +00:00
fix(e2e): reject loose upgrade probe limits
This commit is contained in:
@@ -17,11 +17,37 @@ function option(name, fallback) {
|
||||
return value;
|
||||
}
|
||||
|
||||
function optionValue(name, envName, fallback) {
|
||||
const index = args.indexOf(name);
|
||||
if (index !== -1) {
|
||||
return {
|
||||
label: name,
|
||||
value: option(name),
|
||||
};
|
||||
}
|
||||
return {
|
||||
label: envName,
|
||||
value: process.env[envName] ?? fallback,
|
||||
};
|
||||
}
|
||||
|
||||
function writeJson(file, value) {
|
||||
fs.mkdirSync(path.dirname(file), { recursive: true });
|
||||
fs.writeFileSync(file, `${JSON.stringify(value, null, 2)}\n`);
|
||||
}
|
||||
|
||||
function readStrictInteger({ allowZero = false, label, value }) {
|
||||
const text = String(value ?? "").trim();
|
||||
if (!/^\d+$/u.test(text)) {
|
||||
throw new Error(`invalid ${label}: ${text}`);
|
||||
}
|
||||
const parsed = Number(text);
|
||||
if (!Number.isSafeInteger(parsed) || (allowZero ? parsed < 0 : parsed <= 0)) {
|
||||
throw new Error(`invalid ${label}: ${text}`);
|
||||
}
|
||||
return parsed;
|
||||
}
|
||||
|
||||
const baseUrl = option("--base-url");
|
||||
const probePath = option("--path");
|
||||
const expectKind = option("--expect");
|
||||
@@ -32,35 +58,25 @@ const allowFailing = new Set(
|
||||
.map((entry) => entry.trim())
|
||||
.filter(Boolean),
|
||||
);
|
||||
const timeoutMs = Number.parseInt(
|
||||
option("--timeout-ms", process.env.OPENCLAW_UPGRADE_SURVIVOR_PROBE_TIMEOUT_MS || "60000"),
|
||||
10,
|
||||
const timeoutOption = optionValue(
|
||||
"--timeout-ms",
|
||||
"OPENCLAW_UPGRADE_SURVIVOR_PROBE_TIMEOUT_MS",
|
||||
"60000",
|
||||
);
|
||||
const attemptTimeoutMs = Number.parseInt(
|
||||
option(
|
||||
"--attempt-timeout-ms",
|
||||
process.env.OPENCLAW_UPGRADE_SURVIVOR_PROBE_ATTEMPT_TIMEOUT_MS || "5000",
|
||||
),
|
||||
10,
|
||||
const attemptTimeoutOption = optionValue(
|
||||
"--attempt-timeout-ms",
|
||||
"OPENCLAW_UPGRADE_SURVIVOR_PROBE_ATTEMPT_TIMEOUT_MS",
|
||||
"5000",
|
||||
);
|
||||
const maxBodyBytes = Number.parseInt(
|
||||
option(
|
||||
"--max-body-bytes",
|
||||
process.env.OPENCLAW_UPGRADE_SURVIVOR_PROBE_MAX_BODY_BYTES || "1048576",
|
||||
),
|
||||
10,
|
||||
const maxBodyOption = optionValue(
|
||||
"--max-body-bytes",
|
||||
"OPENCLAW_UPGRADE_SURVIVOR_PROBE_MAX_BODY_BYTES",
|
||||
"1048576",
|
||||
);
|
||||
const timeoutMs = readStrictInteger({ ...timeoutOption, allowZero: true });
|
||||
const attemptTimeoutMs = readStrictInteger(attemptTimeoutOption);
|
||||
const maxBodyBytes = readStrictInteger(maxBodyOption);
|
||||
const url = new URL(probePath, baseUrl).toString();
|
||||
|
||||
if (!Number.isFinite(timeoutMs) || timeoutMs < 0) {
|
||||
throw new Error(`invalid --timeout-ms: ${String(timeoutMs)}`);
|
||||
}
|
||||
if (!Number.isFinite(attemptTimeoutMs) || attemptTimeoutMs <= 0) {
|
||||
throw new Error(`invalid --attempt-timeout-ms: ${String(attemptTimeoutMs)}`);
|
||||
}
|
||||
if (!Number.isFinite(maxBodyBytes) || maxBodyBytes <= 0) {
|
||||
throw new Error(`invalid --max-body-bytes: ${String(maxBodyBytes)}`);
|
||||
}
|
||||
if (expectKind !== "live" && expectKind !== "ready") {
|
||||
throw new Error(`unknown probe expectation: ${expectKind}`);
|
||||
}
|
||||
|
||||
@@ -23,9 +23,14 @@ interface ProbeResult {
|
||||
stdout: string;
|
||||
}
|
||||
|
||||
function runProbe(args: string[], timeout = 5_000): Promise<ProbeResult> {
|
||||
function runProbe(
|
||||
args: string[],
|
||||
timeout = 5_000,
|
||||
env: NodeJS.ProcessEnv = {},
|
||||
): Promise<ProbeResult> {
|
||||
return new Promise((resolve) => {
|
||||
const child = spawn(process.execPath, [probePath, ...args], {
|
||||
env: { ...process.env, ...env },
|
||||
stdio: ["ignore", "pipe", "pipe"],
|
||||
});
|
||||
let stdout = "";
|
||||
@@ -82,6 +87,47 @@ afterEach(() => {
|
||||
});
|
||||
|
||||
describe("scripts/e2e/lib/upgrade-survivor/probe-gateway.mjs", () => {
|
||||
it("rejects loose numeric probe limits instead of parsing prefixes", async () => {
|
||||
const out = path.join(makeTempDir(), "invalid.json");
|
||||
const timeoutResult = await runProbe([
|
||||
"--base-url",
|
||||
"http://127.0.0.1:9",
|
||||
"--path",
|
||||
"/readyz",
|
||||
"--expect",
|
||||
"ready",
|
||||
"--out",
|
||||
out,
|
||||
"--timeout-ms",
|
||||
"1e3",
|
||||
]);
|
||||
|
||||
expect(timeoutResult.status).not.toBe(0);
|
||||
expect(timeoutResult.stderr).toContain("invalid --timeout-ms: 1e3");
|
||||
|
||||
const bodyLimitResult = await runProbe(
|
||||
[
|
||||
"--base-url",
|
||||
"http://127.0.0.1:9",
|
||||
"--path",
|
||||
"/readyz",
|
||||
"--expect",
|
||||
"ready",
|
||||
"--out",
|
||||
out,
|
||||
],
|
||||
5_000,
|
||||
{
|
||||
OPENCLAW_UPGRADE_SURVIVOR_PROBE_MAX_BODY_BYTES: "64bytes",
|
||||
},
|
||||
);
|
||||
|
||||
expect(bodyLimitResult.status).not.toBe(0);
|
||||
expect(bodyLimitResult.stderr).toContain(
|
||||
"invalid OPENCLAW_UPGRADE_SURVIVOR_PROBE_MAX_BODY_BYTES: 64bytes",
|
||||
);
|
||||
});
|
||||
|
||||
it("writes a result when the ready probe matches", async () => {
|
||||
const server = createHttpServer((_request, response) => {
|
||||
response.writeHead(200, { "content-type": "application/json" });
|
||||
|
||||
Reference in New Issue
Block a user