fix(runner-e2e): align restart control directory
This commit is contained in:
parent
dfe7aaf26e
commit
e04611d65d
|
|
@ -26,6 +26,21 @@ const AMBIENT_EXTERNAL_STATE_KEYS = [
|
|||
] as const;
|
||||
const PROVIDER_SECRET_KEY = /^(?:OPENAI|ANTHROPIC|OPENROUTER|DAYTONA)(?:_|$)/;
|
||||
|
||||
export function runnerE2EServerControlPaths(temporaryRoot: string) {
|
||||
const controlDirectory = path.join(temporaryRoot, "control");
|
||||
return {
|
||||
controlDirectory,
|
||||
restartRequestPath: path.join(
|
||||
controlDirectory,
|
||||
"server-restart.request.json",
|
||||
),
|
||||
restartAcknowledgementPath: path.join(
|
||||
controlDirectory,
|
||||
"server-restart.ack.json",
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Local native cells use the debug binary produced by build:runner-binaries.
|
||||
* Preserve an explicit override for release builds and developer workflows.
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import { RunnerApi, pollUntil } from "./api.js";
|
|||
import { buildRuntimeUsage, summarizeExecutionBilling } from "./billing.js";
|
||||
import { runnerExecutionById } from "./catalog.js";
|
||||
import { classifyFailure } from "./failure-classifier.js";
|
||||
import { runnerE2EServerControlPaths } from "./harness-env.js";
|
||||
import { setupLiveFixtures, type LiveFixtureValues } from "./live-fixtures.js";
|
||||
import { evaluateMatcher, type MatcherResult } from "./matchers.js";
|
||||
import {
|
||||
|
|
@ -166,15 +167,11 @@ async function restartIsolatedPaperclipServer(input: {
|
|||
requestId: string;
|
||||
deadlineAt: number;
|
||||
}): Promise<void> {
|
||||
const controlDirectory = path.join(privateRoot!, "control");
|
||||
const requestPath = path.join(
|
||||
const {
|
||||
controlDirectory,
|
||||
"server-restart.request.json",
|
||||
);
|
||||
const acknowledgementPath = path.join(
|
||||
controlDirectory,
|
||||
"server-restart.ack.json",
|
||||
);
|
||||
restartRequestPath: requestPath,
|
||||
restartAcknowledgementPath: acknowledgementPath,
|
||||
} = runnerE2EServerControlPaths(temporaryRoot!);
|
||||
await mkdir(controlDirectory, { recursive: true });
|
||||
const temporaryRequestPath = `${requestPath}.${process.pid}.${input.requestId}.tmp`;
|
||||
await writeFile(
|
||||
|
|
@ -237,10 +234,11 @@ const executionIds = (() => {
|
|||
})();
|
||||
const executions = executionIds.map(runnerExecutionById);
|
||||
const attempt = Number(process.env.PAPERCLIP_RUNNER_E2E_ATTEMPT ?? "1");
|
||||
const temporaryRoot = process.env.PAPERCLIP_RUNNER_E2E_TEMP_ROOT;
|
||||
const privateRoot = process.env.PAPERCLIP_RUNNER_E2E_PRIVATE_DIR;
|
||||
const workspacePath = process.env.PAPERCLIP_RUNNER_E2E_WORKSPACE;
|
||||
if (!privateRoot || !workspacePath)
|
||||
throw new Error("Runner E2E private/workspace paths are required");
|
||||
if (!temporaryRoot || !privateRoot || !workspacePath)
|
||||
throw new Error("Runner E2E temporary/private/workspace paths are required");
|
||||
|
||||
function record(value: unknown): Record<string, unknown> {
|
||||
return value && typeof value === "object" && !Array.isArray(value)
|
||||
|
|
@ -1424,8 +1422,7 @@ for (const execution of executions) {
|
|||
)?.[1] ??
|
||||
/Using fallback workspace "([^"]+)"/.exec(runLogContent)?.[1];
|
||||
const cwd = String(workspaceContext.cwd ?? fallbackWorkspace ?? "");
|
||||
const isolatedRoot = process.env.PAPERCLIP_RUNNER_E2E_TEMP_ROOT ?? "";
|
||||
if (!isolatedRoot || !cwd.startsWith(`${isolatedRoot}/`)) {
|
||||
if (!cwd.startsWith(`${temporaryRoot}/`)) {
|
||||
invariantFailures.push(
|
||||
`local run workspace escaped the isolated root: ${cwd}`,
|
||||
);
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import path from "node:path";
|
|||
import {
|
||||
assertIsolatedServerEnvironment,
|
||||
buildPaperclipServerEnvironment,
|
||||
runnerE2EServerControlPaths,
|
||||
} from "./harness-env.js";
|
||||
|
||||
function required(name: string) {
|
||||
|
|
@ -21,12 +22,11 @@ const port = required("PAPERCLIP_RUNNER_E2E_PORT");
|
|||
const repositoryRoot = path.resolve(import.meta.dirname, "../..");
|
||||
const tsxCli = path.join(repositoryRoot, "cli/node_modules/tsx/dist/cli.mjs");
|
||||
const paperclipCli = path.join(repositoryRoot, "cli/src/index.ts");
|
||||
const controlDirectory = path.join(temporaryRoot, "control");
|
||||
const restartRequestPath = path.join(
|
||||
const {
|
||||
controlDirectory,
|
||||
"server-restart.request.json",
|
||||
);
|
||||
const restartAckPath = path.join(controlDirectory, "server-restart.ack.json");
|
||||
restartRequestPath,
|
||||
restartAcknowledgementPath: restartAckPath,
|
||||
} = runnerE2EServerControlPaths(temporaryRoot);
|
||||
const restartTimeoutMs = 180_000;
|
||||
const gracefulStopTimeoutMs = 30_000;
|
||||
const serverEnvironment = buildPaperclipServerEnvironment(process.env, {
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import {
|
|||
assertIsolatedServerEnvironment,
|
||||
buildPaperclipServerEnvironment,
|
||||
resolvePaperclipRunnerBinaryForHarness,
|
||||
runnerE2EServerControlPaths,
|
||||
} from "./harness-env.js";
|
||||
import { runnerExecutionById } from "./catalog.js";
|
||||
import { assertEmbeddedDatabaseIsolation } from "./instance-isolation.js";
|
||||
|
|
@ -354,6 +355,22 @@ describe("runner E2E failure policy", () => {
|
|||
});
|
||||
|
||||
describe("runner E2E server isolation", () => {
|
||||
it("shares restart control files beneath the isolated temporary root", () => {
|
||||
expect(runnerE2EServerControlPaths("/tmp/cell")).toEqual({
|
||||
controlDirectory: path.join("/tmp/cell", "control"),
|
||||
restartRequestPath: path.join(
|
||||
"/tmp/cell",
|
||||
"control",
|
||||
"server-restart.request.json",
|
||||
),
|
||||
restartAcknowledgementPath: path.join(
|
||||
"/tmp/cell",
|
||||
"control",
|
||||
"server-restart.ack.json",
|
||||
),
|
||||
});
|
||||
});
|
||||
|
||||
it("strips database and paid-provider credentials from the Paperclip process", () => {
|
||||
const env = buildPaperclipServerEnvironment(
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in New Issue