mirror of
https://github.com/openclaw/openclaw.git
synced 2026-06-03 10:04:07 +00:00
fix(e2e): scope strict ClawHub preflight limits
This commit is contained in:
@@ -1,23 +1,24 @@
|
||||
import fs from "node:fs";
|
||||
import os from "node:os";
|
||||
import path from "node:path";
|
||||
import { readPositiveIntEnv } from "../env-limits.mjs";
|
||||
|
||||
const command = process.argv[2];
|
||||
const scratchRoot = process.env.OPENCLAW_PLUGINS_TMP_DIR || os.tmpdir();
|
||||
const CLAWHUB_PREFLIGHT_TIMEOUT_MS = readPositiveInt(
|
||||
process.env.OPENCLAW_PLUGINS_E2E_CLAWHUB_PREFLIGHT_TIMEOUT_MS,
|
||||
30_000,
|
||||
);
|
||||
const CLAWHUB_PREFLIGHT_BODY_MAX_BYTES = readPositiveInt(
|
||||
process.env.OPENCLAW_PLUGINS_E2E_CLAWHUB_PREFLIGHT_BODY_MAX_BYTES,
|
||||
1024 * 1024,
|
||||
);
|
||||
const readJson = (file) => JSON.parse(fs.readFileSync(file, "utf8"));
|
||||
const scratchFile = (name) => path.join(scratchRoot, name);
|
||||
|
||||
function readPositiveInt(raw, fallback) {
|
||||
const parsed = Number.parseInt(String(raw || ""), 10);
|
||||
return Number.isInteger(parsed) && parsed > 0 ? parsed : fallback;
|
||||
function readClawHubPreflightLimits() {
|
||||
return {
|
||||
bodyMaxBytes: readPositiveIntEnv(
|
||||
"OPENCLAW_PLUGINS_E2E_CLAWHUB_PREFLIGHT_BODY_MAX_BYTES",
|
||||
1024 * 1024,
|
||||
),
|
||||
timeoutMs: readPositiveIntEnv(
|
||||
"OPENCLAW_PLUGINS_E2E_CLAWHUB_PREFLIGHT_TIMEOUT_MS",
|
||||
30_000,
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
function createTimeoutError(label, timeoutMs) {
|
||||
@@ -826,6 +827,7 @@ async function assertClawHubPreflight() {
|
||||
throw new Error(`expected clawhub: spec, got ${spec}`);
|
||||
}
|
||||
|
||||
const limits = readClawHubPreflightLimits();
|
||||
const packageName = parseClawHubPackageName(spec);
|
||||
const baseUrl = (
|
||||
process.env.OPENCLAW_CLAWHUB_URL ||
|
||||
@@ -840,7 +842,7 @@ async function assertClawHubPreflight() {
|
||||
const preflightUrl = `${baseUrl}/api/v1/packages/${encodeURIComponent(packageName)}`;
|
||||
const response = await withTimeout(
|
||||
`ClawHub package preflight for ${packageName}`,
|
||||
CLAWHUB_PREFLIGHT_TIMEOUT_MS,
|
||||
limits.timeoutMs,
|
||||
(signal) =>
|
||||
fetch(preflightUrl, {
|
||||
headers: token ? { Authorization: `Bearer ${token}` } : undefined,
|
||||
@@ -850,12 +852,12 @@ async function assertClawHubPreflight() {
|
||||
if (!response.ok) {
|
||||
const body = await withTimeout(
|
||||
`ClawHub package preflight response for ${packageName}`,
|
||||
CLAWHUB_PREFLIGHT_TIMEOUT_MS,
|
||||
limits.timeoutMs,
|
||||
() =>
|
||||
readBoundedResponseText(
|
||||
response,
|
||||
`ClawHub package preflight response for ${packageName}`,
|
||||
CLAWHUB_PREFLIGHT_BODY_MAX_BYTES,
|
||||
limits.bodyMaxBytes,
|
||||
),
|
||||
);
|
||||
throw new Error(
|
||||
@@ -864,17 +866,17 @@ async function assertClawHubPreflight() {
|
||||
}
|
||||
const rawDetail = await withTimeout(
|
||||
`ClawHub package preflight response for ${packageName}`,
|
||||
CLAWHUB_PREFLIGHT_TIMEOUT_MS,
|
||||
limits.timeoutMs,
|
||||
() =>
|
||||
readBoundedResponseText(
|
||||
response,
|
||||
`ClawHub package preflight response for ${packageName}`,
|
||||
CLAWHUB_PREFLIGHT_BODY_MAX_BYTES,
|
||||
limits.bodyMaxBytes,
|
||||
),
|
||||
);
|
||||
const detail = await withTimeout(
|
||||
`ClawHub package preflight JSON for ${packageName}`,
|
||||
CLAWHUB_PREFLIGHT_TIMEOUT_MS,
|
||||
limits.timeoutMs,
|
||||
() => JSON.parse(rawDetail),
|
||||
);
|
||||
const family = detail.package?.family;
|
||||
|
||||
@@ -48,6 +48,34 @@ function runAssertionAsync(args: string[], env: NodeJS.ProcessEnv) {
|
||||
}
|
||||
|
||||
describe("plugins Docker assertions", () => {
|
||||
it("rejects loose ClawHub preflight limits instead of parsing prefixes", () => {
|
||||
const timeoutResult = spawnSync(process.execPath, [ASSERTIONS_SCRIPT, "clawhub-preflight"], {
|
||||
encoding: "utf8",
|
||||
env: {
|
||||
...process.env,
|
||||
CLAWHUB_PLUGIN_SPEC: "clawhub:@openclaw/kitchen-sink",
|
||||
OPENCLAW_PLUGINS_E2E_CLAWHUB_PREFLIGHT_TIMEOUT_MS: "1e3",
|
||||
},
|
||||
});
|
||||
expect(timeoutResult.status).not.toBe(0);
|
||||
expect(timeoutResult.stderr).toContain(
|
||||
"invalid OPENCLAW_PLUGINS_E2E_CLAWHUB_PREFLIGHT_TIMEOUT_MS: 1e3",
|
||||
);
|
||||
|
||||
const bodyLimitResult = spawnSync(process.execPath, [ASSERTIONS_SCRIPT, "clawhub-preflight"], {
|
||||
encoding: "utf8",
|
||||
env: {
|
||||
...process.env,
|
||||
CLAWHUB_PLUGIN_SPEC: "clawhub:@openclaw/kitchen-sink",
|
||||
OPENCLAW_PLUGINS_E2E_CLAWHUB_PREFLIGHT_BODY_MAX_BYTES: "1000bytes",
|
||||
},
|
||||
});
|
||||
expect(bodyLimitResult.status).not.toBe(0);
|
||||
expect(bodyLimitResult.stderr).toContain(
|
||||
"invalid OPENCLAW_PLUGINS_E2E_CLAWHUB_PREFLIGHT_BODY_MAX_BYTES: 1000bytes",
|
||||
);
|
||||
});
|
||||
|
||||
it("keeps sweep artifact paths aligned with the assertion scratch root", () => {
|
||||
const scripts = [
|
||||
"scripts/e2e/lib/plugins/sweep.sh",
|
||||
@@ -92,6 +120,7 @@ describe("plugins Docker assertions", () => {
|
||||
env: {
|
||||
...process.env,
|
||||
HOME: home,
|
||||
OPENCLAW_PLUGINS_E2E_CLAWHUB_PREFLIGHT_TIMEOUT_MS: "1e3",
|
||||
OPENCLAW_PLUGINS_TMP_DIR: scratchRoot,
|
||||
},
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user