mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-10-26 18:31:34 +01:00
install daytona provider in runner e2e fixtures
This commit is contained in:
1 parent
f36f688591
commit
f3c465974c
3 files changed
+109
-4
No files matched your search
@@ -32,12 +32,14 @@ describe("runner E2E Daytona image contract", () => {
|
||||
}
|
||||
for (const transport of ["dial_ws_loopback", "dial_wss", "listen_ws"]) {
|
||||
expect(dockerfile).toContain(transport);
|
||||
expect(workflow).toContain(transport);
|
||||
}
|
||||
expect(workflow).toContain('"binaryContractVersion":2');
|
||||
expect(dockerfile).toContain('metadata="$(paperclip-runnerd --build-metadata)"');
|
||||
expect(dockerfile).toContain("provider-pack.json");
|
||||
expect(workflow).toContain("--platform linux/amd64");
|
||||
expect(workflow).toContain("cosign sign --yes");
|
||||
expect(workflow).toContain(".runnerSourceRevision == $revision");
|
||||
expect(workflow).toContain("docker image inspect");
|
||||
expect(workflow).toContain('.Config.User == "daytona"');
|
||||
expect(workflow).toContain("PAPERCLIP_RUNNER_PROVIDER_PACK_ROOT=");
|
||||
expect(workflow).toContain("anonymous_config");
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,71 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import type { RunnerApi } from "./api.js";
|
||||
import { runnerMatrix } from "./catalog.js";
|
||||
import { setupLiveFixtures } from "./live-fixtures.js";
|
||||
|
||||
describe("live runner fixtures", () => {
|
||||
it("installs the Daytona provider through the public API before creating its environment", async () => {
|
||||
const calls: string[] = [];
|
||||
const api = {
|
||||
async post(path: string, data?: Record<string, unknown>) {
|
||||
calls.push(`POST ${path}`);
|
||||
if (path === "/api/plugins/install") {
|
||||
expect(data).toMatchObject({ isLocalPath: true });
|
||||
expect(data?.packageName).toEqual(
|
||||
expect.stringContaining(
|
||||
"packages/plugins/sandbox-providers/daytona",
|
||||
),
|
||||
);
|
||||
return {
|
||||
id: "plugin-daytona",
|
||||
pluginKey: "paperclip.daytona-sandbox-provider",
|
||||
status: "ready",
|
||||
};
|
||||
}
|
||||
if (path === "/api/companies") {
|
||||
return { id: "company-1", name: "Runner E2E" };
|
||||
}
|
||||
if (path.endsWith("/environments")) {
|
||||
expect(calls).toContain("POST /api/plugins/install");
|
||||
return { id: "environment-1", driver: "sandbox" };
|
||||
}
|
||||
if (path.endsWith("/agents")) {
|
||||
return { id: "agent-1", name: "Agent", companyId: "company-1" };
|
||||
}
|
||||
throw new Error(`Unexpected POST ${path}`);
|
||||
},
|
||||
async postSensitive(path: string, data?: Record<string, unknown>) {
|
||||
calls.push(`POST ${path}`);
|
||||
return { id: `secret-${String(data?.key).toLowerCase()}` };
|
||||
},
|
||||
async delete(path: string) {
|
||||
calls.push(`DELETE ${path}`);
|
||||
},
|
||||
} as unknown as RunnerApi;
|
||||
const execution = runnerMatrix.find(
|
||||
(candidate) =>
|
||||
candidate.id === "legacy-codex.daytona.message-marker",
|
||||
);
|
||||
expect(execution).toBeDefined();
|
||||
|
||||
const fixtures = await setupLiveFixtures({
|
||||
api,
|
||||
execution: execution!,
|
||||
executionNonce: "nonce",
|
||||
workspacePath: "/tmp/workspace",
|
||||
credentials: {
|
||||
OPENAI_API_KEY: "openai-test-value",
|
||||
DAYTONA_API_KEY: "daytona-test-value",
|
||||
},
|
||||
daytonaImage: "ghcr.io/paperclip/image@sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
||||
});
|
||||
|
||||
expect(calls.indexOf("POST /api/plugins/install")).toBeLessThan(
|
||||
calls.indexOf("POST /api/companies/company-1/environments"),
|
||||
);
|
||||
await fixtures.teardown();
|
||||
expect(calls).toContain(
|
||||
"DELETE /api/environments/environment-1?destroyReusableSandboxLeases=true",
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -1,3 +1,4 @@
|
||||
import path from "node:path";
|
||||
import { FixtureRegistry } from "./fixture-registry.js";
|
||||
import type { RunnerApi } from "./api.js";
|
||||
import type {
|
||||
@@ -16,6 +17,11 @@ interface CompanyRecord {
|
||||
interface SecretRecord {
|
||||
id: string;
|
||||
}
|
||||
interface PluginRecord {
|
||||
id: string;
|
||||
pluginKey: string;
|
||||
status: string;
|
||||
}
|
||||
interface EnvironmentRecord {
|
||||
id: string;
|
||||
driver: string;
|
||||
@@ -74,6 +80,26 @@ export async function setupLiveFixtures(input: {
|
||||
const { api, execution } = input;
|
||||
const registry = new FixtureRegistry();
|
||||
|
||||
if (execution.environment.id === "daytona") {
|
||||
registry.register<PluginRecord>({
|
||||
id: "sandbox-provider",
|
||||
async setup() {
|
||||
return api.post<PluginRecord>("/api/plugins/install", {
|
||||
packageName: path.resolve(
|
||||
import.meta.dirname,
|
||||
"../../packages/plugins/sandbox-providers/daytona",
|
||||
),
|
||||
isLocalPath: true,
|
||||
});
|
||||
},
|
||||
async teardown() {
|
||||
// The plugin is installed only in the isolated instance/database. The
|
||||
// launcher removes that complete instance after the environment lease
|
||||
// has been destroyed, so no global uninstall mutation is necessary.
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
registry.register<CompanyRecord>({
|
||||
id: "company",
|
||||
async setup() {
|
||||
@@ -120,7 +146,13 @@ export async function setupLiveFixtures(input: {
|
||||
|
||||
registry.register<EnvironmentRecord>({
|
||||
id: "environment",
|
||||
dependencies: ["company", "secrets"],
|
||||
dependencies: [
|
||||
"company",
|
||||
"secrets",
|
||||
...(execution.environment.id === "daytona"
|
||||
? ["sandbox-provider"]
|
||||
: []),
|
||||
],
|
||||
async setup(resolved) {
|
||||
const company = value<CompanyRecord>(resolved, "company");
|
||||
const secretRefs = value<SecretReferenceMap>(resolved, "secrets");
|
||||
|
||||
Reference in new issue
Block a user