mirror of
https://github.com/morluto/rea.git
synced 2026-10-26 17:35:11 +00:00
fix(process): preserve selected Darwin helper environment through execution
This commit is contained in:
1 parent
921142efbc
commit
f02df45a46
3 files changed
+90
-5
No files matched your search
@@ -19,6 +19,7 @@ import type {
|
||||
import { analysisErrorWithCleanupFailure } from "../domain/analysisErrorCleanup.js";
|
||||
import { safeParseJson } from "../domain/safeJson.js";
|
||||
import { boundedUtf8Text } from "./boundedUtf8Text.js";
|
||||
import { snapshotEnvironment } from "./snapshotEnvironment.js";
|
||||
import {
|
||||
execFileOutput,
|
||||
execFileOutputFailure,
|
||||
@@ -407,7 +408,7 @@ export const createDarwinProcessRunTokenReader = (
|
||||
readonly compiler?: DarwinProcessReaderCompiler;
|
||||
/** Deadline for helper compilation, independent of provider execution. */
|
||||
readonly compileTimeoutMs?: number;
|
||||
/** Environment consulted when `compileTimeoutMs` is omitted. */
|
||||
/** Captured compiler/helper environment and default compile deadline. */
|
||||
readonly environment?: Readonly<Record<string, string | undefined>>;
|
||||
/**
|
||||
* Caller-owned directory holding the compiler's module cache. Unset keeps
|
||||
@@ -421,7 +422,11 @@ export const createDarwinProcessRunTokenReader = (
|
||||
kind: "xcrun",
|
||||
executable: "/usr/bin/xcrun",
|
||||
};
|
||||
const compilerTimeoutMs = resolveSwiftcCompileTimeoutMs(options);
|
||||
const environment = snapshotEnvironment(options.environment ?? process.env);
|
||||
const compilerTimeoutMs = resolveSwiftcCompileTimeoutMs({
|
||||
...options,
|
||||
environment,
|
||||
});
|
||||
const moduleCachePath = options.moduleCachePath ?? "";
|
||||
let root: ProcessReaderRoot | undefined;
|
||||
let executable: string | undefined;
|
||||
@@ -496,7 +501,7 @@ export const createDarwinProcessRunTokenReader = (
|
||||
const compilerTemporary = join(operationRoot.path, "tmp");
|
||||
await mkdir(compilerTemporary);
|
||||
const compilerEnvironment: NodeJS.ProcessEnv = {
|
||||
...process.env,
|
||||
...environment,
|
||||
TMPDIR: compilerTemporary,
|
||||
};
|
||||
const compilerArguments =
|
||||
@@ -640,6 +645,7 @@ export const createDarwinProcessRunTokenReader = (
|
||||
const pending = (async () => {
|
||||
const binary = await compile(signal);
|
||||
const { stdout } = await execFileOutput(binary, arguments_, {
|
||||
env: environment,
|
||||
timeout: 15_000,
|
||||
stopSignal: "SIGTERM",
|
||||
...(signal === undefined ? {} : { signal }),
|
||||
|
||||
@@ -981,12 +981,13 @@ export const createSystemProcessOwnershipHost = (
|
||||
const darwinTokens =
|
||||
platform === "darwin"
|
||||
? createDarwinProcessRunTokenReader({
|
||||
environment: hostEnvironment,
|
||||
...(darwinCompiler === undefined ? {} : { compiler: darwinCompiler }),
|
||||
...(darwinModuleCachePath === undefined
|
||||
? {}
|
||||
: { moduleCachePath: darwinModuleCachePath }),
|
||||
...(options.compileTimeoutMs === undefined
|
||||
? { environment: hostEnvironment }
|
||||
? {}
|
||||
: { compileTimeoutMs: options.compileTimeoutMs }),
|
||||
})
|
||||
: undefined;
|
||||
|
||||
@@ -15,7 +15,7 @@ import { join } from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import { promisify } from "node:util";
|
||||
import { _electron as electron } from "playwright-core";
|
||||
import { expect, it, vi } from "vitest";
|
||||
import { expect, it, onTestFinished, vi } from "vitest";
|
||||
import { z } from "zod";
|
||||
import { createTestTempDirectory } from "../../fixtures/temporaryDirectory.js";
|
||||
|
||||
@@ -457,6 +457,84 @@ const existsPath = async (target: string) =>
|
||||
() => false,
|
||||
);
|
||||
|
||||
it
|
||||
.skipIf(process.platform === "win32")
|
||||
.each([
|
||||
"selected environment",
|
||||
"selected environment and deadline",
|
||||
"default environment",
|
||||
] as const)(
|
||||
"captures the compiler and helper environment from %s",
|
||||
async (selection) => {
|
||||
const directory = await createTestTempDirectory(
|
||||
"rea-process-token-selected-environment-",
|
||||
);
|
||||
const developerDirectory = join(directory, "selected Xcode.app");
|
||||
const compileState = join(directory, "compile-environment.json");
|
||||
const executable = join(directory, "fixture-xcrun");
|
||||
const helper = `#!${process.execPath}
|
||||
console.log(JSON.stringify({ results: process.argv.slice(2).map(pid => ({
|
||||
pid: Number(pid), state: "readable", run_id: process.env.DEVELOPER_DIR,
|
||||
})) }));
|
||||
`;
|
||||
await writeFile(
|
||||
executable,
|
||||
`#!${process.execPath}
|
||||
const fs = process.getBuiltinModule("node:fs");
|
||||
fs.writeFileSync(${JSON.stringify(compileState)}, JSON.stringify({
|
||||
developerDirectory: process.env.DEVELOPER_DIR ?? null,
|
||||
}));
|
||||
const output = process.argv[process.argv.indexOf("-o") + 1];
|
||||
fs.writeFileSync(output, ${JSON.stringify(helper)});
|
||||
fs.chmodSync(output, 0o755);
|
||||
`,
|
||||
{ mode: 0o755 },
|
||||
);
|
||||
onTestFinished(() => {
|
||||
vi.unstubAllEnvs();
|
||||
});
|
||||
vi.stubEnv("DEVELOPER_DIR", developerDirectory);
|
||||
const environment = { ...process.env };
|
||||
const compiler = { kind: "xcrun" as const, executable };
|
||||
const reader =
|
||||
selection === "default environment"
|
||||
? createDarwinProcessRunTokenReader({ compiler })
|
||||
: createSystemProcessOwnershipHost("darwin", environment, {
|
||||
darwinCompiler: compiler,
|
||||
...(selection === "selected environment and deadline"
|
||||
? { compileTimeoutMs: 15_000 }
|
||||
: {}),
|
||||
});
|
||||
environment.DEVELOPER_DIR = join(directory, "later caller selection");
|
||||
vi.stubEnv("DEVELOPER_DIR", join(directory, "later ambient selection"));
|
||||
try {
|
||||
await reader.prepare?.(AbortSignal.timeout(15_000));
|
||||
expect(JSON.parse(await readFile(compileState, "utf8"))).toEqual({
|
||||
developerDirectory,
|
||||
});
|
||||
const processes = [
|
||||
{
|
||||
pid: 123,
|
||||
parentPid: 1,
|
||||
processGroupId: 123,
|
||||
state: "S",
|
||||
command: "fixture",
|
||||
},
|
||||
];
|
||||
const observations =
|
||||
"read" in reader
|
||||
? await reader.read(processes)
|
||||
: await reader.runTokens?.(processes);
|
||||
expect(observations?.get(123)).toEqual({
|
||||
state: "readable",
|
||||
runId: developerDirectory,
|
||||
});
|
||||
} finally {
|
||||
await reader.close?.();
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
it.skipIf(process.platform === "win32")(
|
||||
"forwards a caller-owned module cache and keeps it after the helper root is removed",
|
||||
async () => {
|
||||
|
||||
Reference in new issue
Block a user