test: narrow live Docker ACP changed gate

This commit is contained in:
Peter Steinberger
2026-04-26 01:47:35 +01:00
parent 1fe0e6fc4a
commit 099d18f432
4 changed files with 123 additions and 7 deletions

View File

@@ -10,6 +10,8 @@ const TOOLING_PATH_RE =
/^(?:scripts\/|test\/vitest\/|\.github\/|git-hooks\/|vitest(?:\..+)?\.config\.ts$|tsconfig.*\.json$|\.gitignore$|\.oxlint.*|\.oxfmt.*)/u;
const ROOT_GLOBAL_PATH_RE =
/^(?:package\.json$|pnpm-lock\.yaml$|pnpm-workspace\.yaml$|tsdown\.config\.ts$|vitest\.config\.ts$)/u;
const LIVE_DOCKER_TOOLING_PATH_RE =
/^(?:scripts\/test-docker-all\.mjs|scripts\/test-docker-all\.sh|scripts\/lib\/live-docker-auth\.sh|scripts\/test-live-(?:acp-bind|cli-backend|codex-harness|gateway-models|models)-docker\.sh|src\/gateway\/gateway-acp-bind\.live\.test\.ts|src\/gateway\/live-agent-probes\.test\.ts)$/u;
const TEST_PATH_RE =
/(?:^|\/)(?:test|__tests__)\/|(?:\.|\/)(?:test|spec|e2e|browser\.test)\.[cm]?[jt]sx?$/u;
const PUBLIC_EXTENSION_CONTRACT_RE =
@@ -28,7 +30,7 @@ export const RELEASE_METADATA_PATHS = new Set([
"src/config/schema.base.generated.ts",
]);
/** @typedef {"core" | "coreTests" | "extensions" | "extensionTests" | "apps" | "docs" | "tooling" | "releaseMetadata" | "all"} ChangedLane */
/** @typedef {"core" | "coreTests" | "extensions" | "extensionTests" | "apps" | "docs" | "tooling" | "liveDockerTooling" | "releaseMetadata" | "all"} ChangedLane */
/**
* @typedef {{
@@ -56,6 +58,7 @@ export function createEmptyChangedLanes() {
apps: false,
docs: false,
tooling: false,
liveDockerTooling: false,
releaseMetadata: false,
all: false,
};
@@ -66,9 +69,9 @@ export function createEmptyChangedLanes() {
* @returns {ChangedLaneResult}
*/
export function detectChangedLanes(changedPaths) {
const paths = [...new Set(changedPaths.map(normalizeChangedPath).filter(Boolean))].toSorted(
(left, right) => left.localeCompare(right),
);
const paths = [...new Set(changedPaths.map(normalizeChangedPath).filter(Boolean))]
.toSorted((left, right) => left.localeCompare(right))
.filter((changedPath) => changedPath !== "--");
const lanes = createEmptyChangedLanes();
const reasons = [];
let extensionImpactFromCore = false;
@@ -101,6 +104,12 @@ export function detectChangedLanes(changedPaths) {
hasNonDocs = true;
if (LIVE_DOCKER_TOOLING_PATH_RE.test(changedPath)) {
lanes.liveDockerTooling = true;
reasons.push(`${changedPath}: live Docker tooling surface`);
continue;
}
if (ROOT_GLOBAL_PATH_RE.test(changedPath)) {
lanes.all = true;
extensionImpactFromCore = true;
@@ -262,6 +271,9 @@ function parseArgs(argv) {
],
{
onUnhandledArg(arg, target) {
if (arg === "--") {
return "handled";
}
target.paths.push(arg);
return "handled";
},

View File

@@ -19,6 +19,14 @@ import { resolveChangedTestTargetPlan } from "./test-projects.test-support.mjs";
export const CHANGED_CHECK_VITEST_NO_OUTPUT_TIMEOUT_MS = "600000";
const VITEST_NO_OUTPUT_TIMEOUT_ENV_KEY = "OPENCLAW_VITEST_NO_OUTPUT_TIMEOUT_MS";
const VITEST_NO_OUTPUT_RETRY_ENV_KEY = "OPENCLAW_VITEST_NO_OUTPUT_RETRY";
const LIVE_DOCKER_AUTH_SHELL_TARGETS = [
"scripts/lib/live-docker-auth.sh",
"scripts/test-live-acp-bind-docker.sh",
"scripts/test-live-cli-backend-docker.sh",
"scripts/test-live-codex-harness-docker.sh",
"scripts/test-live-gateway-models-docker.sh",
"scripts/test-live-models-docker.sh",
];
export function createChangedCheckChildEnv(baseEnv = process.env) {
const resolvedBaseEnv = resolveLocalHeavyCheckEnv(baseEnv);
@@ -67,6 +75,15 @@ export function createChangedCheckPlan(result, options = {}) {
commands.push({ name, args, ...(env ? { env } : {}) });
}
};
const addCommand = (name, bin, args, env) => {
if (
!commands.some(
(command) => command.name === name && command.bin === bin && sameArgs(command.args, args),
)
) {
commands.push({ name, bin, args, ...(env ? { env } : {}) });
}
};
const addTypecheck = (name, args) => add(name, args, createSparseTsgoSkipEnv(baseEnv));
const addLint = (name, args) => add(name, args, baseEnv);
@@ -138,10 +155,17 @@ export function createChangedCheckPlan(result, options = {}) {
if (lanes.core || lanes.coreTests) {
addLint("lint core", ["lint:core"]);
}
if (
lanes.liveDockerTooling &&
result.paths.some((changedPath) => changedPath.startsWith("src/"))
) {
addTypecheck("typecheck core tests", ["tsgo:core:test"]);
addLint("lint core", ["lint:core"]);
}
if (lanes.extensions || lanes.extensionTests) {
addLint("lint extensions", ["lint:extensions"]);
}
if (lanes.tooling) {
if (lanes.tooling || lanes.liveDockerTooling) {
addLint("lint scripts", ["lint:scripts"]);
}
if (lanes.apps) {
@@ -157,6 +181,21 @@ export function createChangedCheckPlan(result, options = {}) {
add("pairing account guard", ["lint:auth:pairing-account-scope"]);
}
if (lanes.liveDockerTooling) {
addCommand("live Docker shell syntax", "bash", ["-n", ...LIVE_DOCKER_AUTH_SHELL_TARGETS]);
addCommand("live Docker scheduler dry run", "node", ["scripts/test-docker-all.mjs"], {
...baseEnv,
OPENCLAW_DOCKER_ALL_DRY_RUN: "1",
OPENCLAW_DOCKER_ALL_LIVE_MODE: "only",
});
add(
"ACP bind unit tests",
["test", "src/gateway/live-agent-probes.test.ts", "src/agents/acp-spawn.test.ts"],
createChangedCheckVitestEnv(baseEnv),
);
add("ACPX extension tests", ["test:extension", "acpx"], createChangedCheckVitestEnv(baseEnv));
}
const testPlan = resolveChangedTestTargetPlan(result.paths);
const runExtensionTests = result.extensionImpactFromCore;
const testTargets = runExtensionTests
@@ -197,7 +236,7 @@ export async function runChangedCheck(result, options = {}) {
const timings = [];
for (const command of plan.commands) {
const status = await runPnpm(command, timings);
const status = await runPlanCommand(command, timings);
if (status !== 0) {
printSummary(timings, options);
return status;
@@ -291,6 +330,13 @@ async function runPnpm(command, timings) {
return await runCommand({ ...command, bin: "pnpm" }, timings);
}
async function runPlanCommand(command, timings) {
if (command.bin) {
return await runCommand(command, timings);
}
return await runPnpm(command, timings);
}
async function runCommand(command, timings) {
const startedAt = performance.now();
console.error(`\n[check:changed] ${command.name}`);
@@ -338,6 +384,9 @@ function parseArgs(argv) {
],
{
onUnhandledArg(arg, target) {
if (arg === "--") {
return "handled";
}
target.paths.push(normalizeChangedPath(arg));
return "handled";
},