mirror of
https://github.com/openclaw/openclaw.git
synced 2026-06-30 19:59:35 +00:00
fix(scripts): share Docker E2E artifact bounds
This commit is contained in:
@@ -8,6 +8,7 @@ import { spawnSync } from "node:child_process";
|
||||
import fs from "node:fs";
|
||||
import os from "node:os";
|
||||
import path from "node:path";
|
||||
import { readDockerE2eJsonArtifact } from "./lib/docker-e2e-json-artifacts.mjs";
|
||||
|
||||
const DEFAULT_WORKFLOW = "openclaw-live-and-e2e-checks-reusable.yml";
|
||||
|
||||
@@ -76,7 +77,7 @@ function run(command, args, options = {}) {
|
||||
}
|
||||
|
||||
function readJson(file) {
|
||||
return JSON.parse(fs.readFileSync(file, "utf8"));
|
||||
return readDockerE2eJsonArtifact(file);
|
||||
}
|
||||
|
||||
function shellQuote(value) {
|
||||
|
||||
@@ -2,12 +2,9 @@
|
||||
// Summarizes Docker E2E timing artifacts.
|
||||
// Accepts scheduler summary.json or lane-timings.json so agents can see the
|
||||
// slowest lanes and phase critical path before deciding what to rerun.
|
||||
import fs from "node:fs";
|
||||
import { readDockerE2eJsonArtifact } from "./lib/docker-e2e-json-artifacts.mjs";
|
||||
import { parsePositiveInt } from "./lib/numeric-options.mjs";
|
||||
|
||||
const JSON_ARTIFACT_MAX_BYTES_ENV = "OPENCLAW_DOCKER_E2E_JSON_ARTIFACT_MAX_BYTES";
|
||||
const DEFAULT_JSON_ARTIFACT_MAX_BYTES = 16 * 1024 * 1024;
|
||||
|
||||
function usage() {
|
||||
return "Usage: node scripts/docker-e2e-timings.mjs <summary.json|lane-timings.json> [--limit N]";
|
||||
}
|
||||
@@ -44,29 +41,7 @@ function parseArgs(argv) {
|
||||
}
|
||||
|
||||
function readJson(file) {
|
||||
return JSON.parse(readJsonArtifactText(file));
|
||||
}
|
||||
|
||||
function readJsonArtifactText(file) {
|
||||
const maxBytes = readPositiveIntEnv(JSON_ARTIFACT_MAX_BYTES_ENV, DEFAULT_JSON_ARTIFACT_MAX_BYTES);
|
||||
const stat = fs.statSync(file);
|
||||
if (!stat.isFile()) {
|
||||
throw new Error(`JSON artifact is not a file: ${file}`);
|
||||
}
|
||||
if (stat.size > maxBytes) {
|
||||
throw new Error(`JSON artifact exceeded ${maxBytes} bytes: ${file} (${stat.size} bytes)`);
|
||||
}
|
||||
const text = fs.readFileSync(file, "utf8");
|
||||
const bytes = Buffer.byteLength(text, "utf8");
|
||||
if (bytes > maxBytes) {
|
||||
throw new Error(`JSON artifact exceeded ${maxBytes} bytes: ${file} (${bytes} bytes)`);
|
||||
}
|
||||
return text;
|
||||
}
|
||||
|
||||
function readPositiveIntEnv(name, fallback) {
|
||||
const raw = process.env[name];
|
||||
return raw === undefined || raw === "" ? fallback : parsePositiveInt(raw, name);
|
||||
return readDockerE2eJsonArtifact(file);
|
||||
}
|
||||
|
||||
function seconds(value) {
|
||||
|
||||
@@ -1,11 +1,7 @@
|
||||
// Docker E2E CI helper.
|
||||
// Converts scheduler JSON into GitHub Actions outputs and compact markdown
|
||||
// summaries so the workflow does not duplicate Docker E2E planning logic.
|
||||
import fs from "node:fs";
|
||||
import { parsePositiveInt } from "./lib/numeric-options.mjs";
|
||||
|
||||
const JSON_ARTIFACT_MAX_BYTES_ENV = "OPENCLAW_DOCKER_E2E_JSON_ARTIFACT_MAX_BYTES";
|
||||
const DEFAULT_JSON_ARTIFACT_MAX_BYTES = 16 * 1024 * 1024;
|
||||
import { readDockerE2eJsonArtifact } from "./lib/docker-e2e-json-artifacts.mjs";
|
||||
|
||||
function usage() {
|
||||
return [
|
||||
@@ -17,29 +13,7 @@ function usage() {
|
||||
}
|
||||
|
||||
function readJson(file) {
|
||||
return JSON.parse(readJsonArtifactText(file));
|
||||
}
|
||||
|
||||
function readJsonArtifactText(file) {
|
||||
const maxBytes = readPositiveIntEnv(JSON_ARTIFACT_MAX_BYTES_ENV, DEFAULT_JSON_ARTIFACT_MAX_BYTES);
|
||||
const stat = fs.statSync(file);
|
||||
if (!stat.isFile()) {
|
||||
throw new Error(`JSON artifact is not a file: ${file}`);
|
||||
}
|
||||
if (stat.size > maxBytes) {
|
||||
throw new Error(`JSON artifact exceeded ${maxBytes} bytes: ${file} (${stat.size} bytes)`);
|
||||
}
|
||||
const text = fs.readFileSync(file, "utf8");
|
||||
const bytes = Buffer.byteLength(text, "utf8");
|
||||
if (bytes > maxBytes) {
|
||||
throw new Error(`JSON artifact exceeded ${maxBytes} bytes: ${file} (${bytes} bytes)`);
|
||||
}
|
||||
return text;
|
||||
}
|
||||
|
||||
function readPositiveIntEnv(name, fallback) {
|
||||
const raw = process.env[name];
|
||||
return raw === undefined || raw === "" ? fallback : parsePositiveInt(raw, name);
|
||||
return readDockerE2eJsonArtifact(file);
|
||||
}
|
||||
|
||||
function boolOutput(value) {
|
||||
|
||||
31
scripts/lib/docker-e2e-json-artifacts.mjs
Normal file
31
scripts/lib/docker-e2e-json-artifacts.mjs
Normal file
@@ -0,0 +1,31 @@
|
||||
import fs from "node:fs";
|
||||
import { parsePositiveInt } from "./numeric-options.mjs";
|
||||
|
||||
const JSON_ARTIFACT_MAX_BYTES_ENV = "OPENCLAW_DOCKER_E2E_JSON_ARTIFACT_MAX_BYTES";
|
||||
const DEFAULT_JSON_ARTIFACT_MAX_BYTES = 16 * 1024 * 1024;
|
||||
|
||||
export function readDockerE2eJsonArtifact(file) {
|
||||
return JSON.parse(readDockerE2eJsonArtifactText(file));
|
||||
}
|
||||
|
||||
function readDockerE2eJsonArtifactText(file) {
|
||||
const maxBytes = readPositiveIntEnv(JSON_ARTIFACT_MAX_BYTES_ENV, DEFAULT_JSON_ARTIFACT_MAX_BYTES);
|
||||
const stat = fs.statSync(file);
|
||||
if (!stat.isFile()) {
|
||||
throw new Error(`JSON artifact is not a file: ${file}`);
|
||||
}
|
||||
if (stat.size > maxBytes) {
|
||||
throw new Error(`JSON artifact exceeded ${maxBytes} bytes: ${file} (${stat.size} bytes)`);
|
||||
}
|
||||
const text = fs.readFileSync(file, "utf8");
|
||||
const bytes = Buffer.byteLength(text, "utf8");
|
||||
if (bytes > maxBytes) {
|
||||
throw new Error(`JSON artifact exceeded ${maxBytes} bytes: ${file} (${bytes} bytes)`);
|
||||
}
|
||||
return text;
|
||||
}
|
||||
|
||||
function readPositiveIntEnv(name, fallback) {
|
||||
const raw = process.env[name];
|
||||
return raw === undefined || raw === "" ? fallback : parsePositiveInt(raw, name);
|
||||
}
|
||||
@@ -122,6 +122,26 @@ describe("Docker E2E helper CLIs", () => {
|
||||
);
|
||||
});
|
||||
|
||||
it("rejects oversized rerun JSON artifacts without a Node stack trace", () => {
|
||||
const root = mkdtempSync(`${tmpdir()}/openclaw-docker-e2e-rerun-`);
|
||||
try {
|
||||
const file = path.join(root, "summary.json");
|
||||
writeFileSync(file, `${JSON.stringify({ filler: "x".repeat(128) })}\n`, "utf8");
|
||||
|
||||
const result = runHelper("scripts/docker-e2e-rerun.mjs", file, "--ref", "abc123", {
|
||||
OPENCLAW_DOCKER_E2E_JSON_ARTIFACT_MAX_BYTES: "64",
|
||||
});
|
||||
|
||||
expect(result.status).toBe(1);
|
||||
expect(result.stdout).toBe("");
|
||||
expect(result.stderr).toContain("JSON artifact exceeded 64 bytes");
|
||||
expect(result.stderr).not.toContain("Error:");
|
||||
expect(result.stderr).not.toContain("at file:");
|
||||
} finally {
|
||||
rmSync(root, { force: true, recursive: true });
|
||||
}
|
||||
});
|
||||
|
||||
it.each(["summary.json", "failures.json"])(
|
||||
"prints local cleanup reruns without synthesizing Docker lane reruns from %s",
|
||||
(fileName) => {
|
||||
|
||||
Reference in New Issue
Block a user