fix: isolate GitHub launcher module format
Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
parent
1c48625115
commit
30b9cd8c00
|
|
@ -43,7 +43,9 @@ adapters and the native runner enter the same host-owned lifecycle before
|
|||
dispatch. Local execution keeps its existing workspace and home behavior.
|
||||
Legacy ACP proxies use a private host staging directory while agent sessions start
|
||||
in the sandbox home. For API-key Codex ACP runs, the adapter writes the explicit
|
||||
key to an owner-only login file in the staging copy; host credentials stay unchanged. Native runner launches carry the validated scoped paths
|
||||
key to an owner-only login file in the staging copy; host credentials stay unchanged.
|
||||
Per-run GitHub launchers declare their own CommonJS package scope so warm runs
|
||||
inside ES-module repositories can still execute Git and GitHub CLI commands. Native runner launches carry the validated scoped paths
|
||||
through runnerd to ACPX; CLI configuration remains in its private runtime directories.
|
||||
Warm sandbox task bindings persist independently of the experimental isolated
|
||||
workspace setting. Only the active host run can establish that binding; the
|
||||
|
|
|
|||
|
|
@ -1539,6 +1539,9 @@ export async function prepareGitHubOperationLaunchers(input: {
|
|||
// the managed launchers after startup without loading a host user's profile.
|
||||
const profile = `export PATH=${shellQuote(managedPath)}\n`;
|
||||
const files: Record<string, string> = Object.fromEntries([
|
||||
// Warm task paths can live inside an ESM repository. These extensionless
|
||||
// launchers use CommonJS regardless of the surrounding project's type.
|
||||
["package.json", JSON.stringify({ type: "commonjs" })],
|
||||
...["git", "gh"].map((name) => [name, githubLauncherSource()] as const),
|
||||
...[".zshenv", ".zprofile", ".zshrc", ".bash_profile", ".bashrc", ".profile"].map((name) => [name, profile] as const),
|
||||
]);
|
||||
|
|
|
|||
|
|
@ -6,11 +6,38 @@ import path from "node:path";
|
|||
import { promisify } from "node:util";
|
||||
import { afterEach, describe, expect, it } from "vitest";
|
||||
import { githubBrokerEnvironment, githubLauncherSource } from "./github-launcher.js";
|
||||
import { prepareGitHubOperationLaunchers } from "./execution-target.js";
|
||||
import { runChildProcess } from "./server-utils.js";
|
||||
import type { CommandManagedRuntimeRunner } from "./command-managed-runtime.js";
|
||||
const exec = promisify(execFile);
|
||||
const cleanups: Array<() => Promise<unknown>> = [];
|
||||
afterEach(async () => { for (const cleanup of cleanups.splice(0).reverse()) await cleanup(); });
|
||||
|
||||
describe("managed GitHub launchers", () => {
|
||||
it("runs staged git and gh launchers inside an ES-module repository", async () => {
|
||||
const root = await mkdtemp(path.join(os.tmpdir(), "paperclip-github-esm-"));
|
||||
cleanups.push(() => rm(root, { recursive: true, force: true }));
|
||||
const realBin = path.join(root, "real-bin");
|
||||
await mkdir(realBin);
|
||||
await writeFile(path.join(root, "package.json"), JSON.stringify({ type: "module" }));
|
||||
await writeFile(path.join(realBin, "gh"), "#!/bin/sh\nprintf gh-fixture", { mode: 0o700 });
|
||||
const target = { kind: "remote" as const, transport: "sandbox" as const,
|
||||
providerKey: "fixture", remoteCwd: root,
|
||||
runner: { execute: async (input: Parameters<CommandManagedRuntimeRunner["execute"]>[0]) => runChildProcess("github-esm-fixture", input.command, input.args ?? [], {
|
||||
cwd: input.cwd ?? root, env: input.env ?? {}, stdin: input.stdin,
|
||||
timeoutSec: 15, graceSec: 1, onLog: async () => {},
|
||||
}) },
|
||||
};
|
||||
// The second run models the fresh per-run wrapper staged on warm startup.
|
||||
for (const runId of ["cold", "warm"]) {
|
||||
const env = await prepareGitHubOperationLaunchers({ runId, target, cwd: root,
|
||||
env: { PATH: `${realBin}:${process.env.PATH}`, PAPERCLIP_GITHUB_BROKER_TOKEN: "" } });
|
||||
const launcher = env.PAPERCLIP_GITHUB_LAUNCHER_DIR;
|
||||
expect((await exec(path.join(launcher, "git"), ["--version"], { cwd: root, env: { ...process.env, ...env } })).stdout).toMatch(/^git version /);
|
||||
expect((await exec(path.join(launcher, "gh"), [], { cwd: root, env: { ...process.env, ...env } })).stdout).toBe("gh-fixture");
|
||||
}
|
||||
});
|
||||
|
||||
it("captures each command's identity and clears host credentials when the next person has none", async () => {
|
||||
const root = await mkdtemp(path.join(os.tmpdir(), "paperclip-github-launcher-test-"));
|
||||
cleanups.push(() => rm(root, { recursive: true, force: true }));
|
||||
|
|
|
|||
Loading…
Reference in New Issue