ci(docker): use resolved pnpm for scheduled lanes

(cherry picked from commit 61a539a1b7)
This commit is contained in:
Peter Steinberger
2026-04-26 22:54:17 +01:00
parent 43e651db9a
commit 54e77a9ec4
3 changed files with 32 additions and 1 deletions

View File

@@ -493,6 +493,7 @@ jobs:
export OPENCLAW_DOCKER_ALL_INCLUDE_OPENWEBUI="${INCLUDE_OPENWEBUI}"
export OPENCLAW_DOCKER_ALL_LOG_DIR=".artifacts/docker-tests/release-${DOCKER_E2E_CHUNK}"
export OPENCLAW_DOCKER_ALL_TIMINGS_FILE=".artifacts/docker-tests/release-${DOCKER_E2E_CHUNK}-timings.json"
export OPENCLAW_DOCKER_ALL_PNPM_COMMAND="$(command -v pnpm)"
pnpm test:docker:all
@@ -616,6 +617,7 @@ jobs:
export OPENCLAW_DOCKER_ALL_INCLUDE_OPENWEBUI="${INCLUDE_OPENWEBUI}"
export OPENCLAW_DOCKER_ALL_LOG_DIR=".artifacts/docker-tests/targeted"
export OPENCLAW_DOCKER_ALL_TIMINGS_FILE=".artifacts/docker-tests/targeted-timings.json"
export OPENCLAW_DOCKER_ALL_PNPM_COMMAND="$(command -v pnpm)"
if [[ "${{ steps.plan.outputs.needs_live_image }}" == "1" ]]; then
pnpm test:docker:live-build
fi

View File

@@ -197,12 +197,38 @@ function buildLaneRerunCommand(name, baseEnv) {
["OPENCLAW_DOCKER_E2E_FUNCTIONAL_IMAGE", baseEnv.OPENCLAW_DOCKER_E2E_FUNCTIONAL_IMAGE],
["OPENCLAW_CURRENT_PACKAGE_TGZ", baseEnv.OPENCLAW_CURRENT_PACKAGE_TGZ],
];
if (baseEnv.OPENCLAW_DOCKER_ALL_PNPM_COMMAND) {
env.push(["OPENCLAW_DOCKER_ALL_PNPM_COMMAND", baseEnv.OPENCLAW_DOCKER_ALL_PNPM_COMMAND]);
}
return `${env
.filter(([, value]) => value !== undefined && value !== "")
.map(([key, value]) => `${key}=${shellQuote(value)}`)
.join(" ")} pnpm test:docker:all`;
}
function withResolvedPnpmCommand(command, env) {
const pnpmCommand = env.OPENCLAW_DOCKER_ALL_PNPM_COMMAND?.trim();
if (!pnpmCommand) {
return command;
}
return command.replace(/(^|\s)pnpm(?=\s)/g, `$1${shellQuote(pnpmCommand)}`);
}
function timingSeconds(timingStore, poolLane) {
const fromStore = timingStore?.lanes?.[poolLane.name]?.durationSeconds;
if (typeof fromStore === "number" && Number.isFinite(fromStore) && fromStore > 0) {
return fromStore;
}
return poolLane.estimateSeconds ?? 0;
}
function orderLanes(poolLanes, timingStore) {
return poolLanes
.map((poolLane, index) => ({ index, poolLane, seconds: timingSeconds(timingStore, poolLane) }))
.toSorted((a, b) => b.seconds - a.seconds || a.index - b.index)
.map(({ poolLane }) => poolLane);
}
async function loadTimingStore(file, enabled) {
if (!enabled) {
return { enabled: false, file, lanes: {}, version: 1 };
@@ -611,10 +637,11 @@ function laneEnv(poolLane, baseEnv, logDir, cacheKey) {
}
async function runLane(lane, baseEnv, logDir, fallbackTimeoutMs) {
const { command, name } = lane;
const { name } = lane;
const timeoutMs = lane.timeoutMs ?? fallbackTimeoutMs;
const logFile = path.join(logDir, `${name}.log`);
const env = laneEnv(lane, baseEnv, logDir, lane.cacheKey);
const command = withResolvedPnpmCommand(lane.command, env);
await mkdir(env.OPENCLAW_DOCKER_CLI_TOOLS_DIR, { recursive: true });
await mkdir(env.OPENCLAW_DOCKER_CACHE_HOME_DIR, { recursive: true });
await fs.promises.writeFile(

View File

@@ -44,5 +44,7 @@ describe("docker build helper", () => {
expect(scheduler).toContain("env.npm_execpath ? path.dirname(env.npm_execpath)");
expect(scheduler).toContain("path.dirname(process.execPath)");
expect(scheduler).toContain("env.PATH = [...new Set(pathEntries)].join(path.delimiter)");
expect(scheduler).toContain("withResolvedPnpmCommand");
expect(scheduler).toContain("OPENCLAW_DOCKER_ALL_PNPM_COMMAND");
});
});