install daytona provider in runner e2e fixtures

This commit is contained in:
Dotta committed 2026-08-27 09:26:18 -05:00
1 parent f36f688591
commit f3c465974c
3 files changed
+109 -4

No files matched your search

+5 -3
View File
@@ -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");
});
});
+71
View File
@@ -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",
);
});
});
+33 -1
View File
@@ -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");