mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-10-25 17:45:53 +01:00
fix(runner): clean partial GitHub launcher staging failures
This commit is contained in:
1 parent
db827c2af2
commit
db3857807b
2 files changed
+39
-2
No files matched your search
@@ -24,6 +24,31 @@ describe("heartbeat GitHub launcher lifetime", () => {
|
||||
expect(second.cleanupLocation).toBeNull();
|
||||
expect(first.env).toMatchObject({ GH_TOKEN: "", PAPERCLIP_GITHUB_BROKER_TOKEN: "", PAPERCLIP_GITHUB_BROKER_URL: "" });
|
||||
});
|
||||
it.each([false, true])("cleans partial run-scoped staging and preserves its error (cleanup fails: %s)", async (cleanupFails) => {
|
||||
const stagingError = new Error("remote launcher staging failed");
|
||||
const prepareLaunchers = vi.fn(async () => { throw stagingError; });
|
||||
const cleanupLaunchers = vi.fn(async () => {
|
||||
if (cleanupFails) throw new Error("cleanup unavailable");
|
||||
});
|
||||
await expect(prepareHeartbeatGitHubLaunchers({
|
||||
native: true, githubConfigured: true, agentId: "agent-a", target,
|
||||
runId: "failed-run", cwd: "/workspace", env: {}, brokerUrl: "https://paperclip.test",
|
||||
createBrokerToken: () => "current-run-secret",
|
||||
}, prepareLaunchers, cleanupLaunchers)).rejects.toBe(stagingError);
|
||||
expect(cleanupLaunchers).toHaveBeenCalledExactlyOnceWith({ runId: "failed-run", target });
|
||||
});
|
||||
|
||||
it("does not remove shared anonymous wrappers when staging a later run fails", async () => {
|
||||
const stagingError = new Error("remote launcher staging failed");
|
||||
const cleanupLaunchers = vi.fn(async () => undefined);
|
||||
await expect(prepareHeartbeatGitHubLaunchers({
|
||||
native: true, githubConfigured: false, agentId: "agent-a", target,
|
||||
runId: "failed-run", cwd: "/workspace", env: {}, brokerUrl: "https://paperclip.test",
|
||||
createBrokerToken: () => { throw new Error("must not mint a capability"); },
|
||||
}, async () => { throw stagingError; }, cleanupLaunchers)).rejects.toBe(stagingError);
|
||||
expect(cleanupLaunchers).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it.each([
|
||||
{ native: true, githubConfigured: true, target },
|
||||
{ native: false, githubConfigured: false, target },
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { createHash } from "node:crypto";
|
||||
import { githubBrokerEnvironment } from "@paperclipai/adapter-utils/github-launcher";
|
||||
import { prepareGitHubOperationLaunchers } from "@paperclipai/adapter-utils/execution-target";
|
||||
import { cleanupGitHubOperationLaunchers, prepareGitHubOperationLaunchers } from "@paperclipai/adapter-utils/execution-target";
|
||||
|
||||
type LauncherInput = Parameters<typeof prepareGitHubOperationLaunchers>[0];
|
||||
|
||||
@@ -13,6 +13,7 @@ export async function prepareHeartbeatGitHubLaunchers(
|
||||
createBrokerToken: () => string;
|
||||
},
|
||||
prepareLaunchers = prepareGitHubOperationLaunchers,
|
||||
cleanupLaunchers = cleanupGitHubOperationLaunchers,
|
||||
) {
|
||||
// An unconfigured sandbox has no managed GitHub identity to broker. Its
|
||||
// token-free wrappers still isolate image credentials, but may live as long
|
||||
@@ -30,5 +31,16 @@ export async function prepareHeartbeatGitHubLaunchers(
|
||||
url: anonymous ? "" : input.brokerUrl,
|
||||
token: anonymous ? "" : input.createBrokerToken(),
|
||||
});
|
||||
return { env: await prepareLaunchers({ ...location, cwd: input.cwd, env }), cleanupLocation: anonymous ? null : location };
|
||||
try {
|
||||
return {
|
||||
env: await prepareLaunchers({ ...location, cwd: input.cwd, env }),
|
||||
cleanupLocation: anonymous ? null : location,
|
||||
};
|
||||
} catch (error) {
|
||||
// The caller cannot retain a cleanup location until staging returns. Clean
|
||||
// partial run-specific files here, preserving the original staging failure.
|
||||
// Anonymous files may still belong to a live warm provider; never delete them.
|
||||
if (!anonymous) await cleanupLaunchers(location).catch(() => undefined);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user