fix(environments): address sandbox probe review notes

This commit is contained in:
Devin Foley committed 2026-07-09 16:33:51 -07:00
1 parent 6aed879611
commit 21040bad77
4 files changed
+83 -2

No files matched your search

@@ -459,6 +459,43 @@ describeEmbeddedPostgres("environmentCustomImageService", () => {
});
});
it("does not rewrite generic missing image setup failures as template conflicts", async () => {
const { environmentId } = await seed();
const workerManager = createWorkerManager();
workerManager.call.mockImplementation(async (_pluginId, method) => {
if (method === "environmentStartInteractiveSetup") {
throw new Error("Base image not found in registry");
}
throw new Error(`Unexpected plugin call: ${method}`);
});
const service = environmentCustomImageService(db, { pluginWorkerManager: workerManager });
const [template] = await db.insert(environmentCustomImageTemplates).values({
environmentId,
provider: "fake-plugin",
templateKind: "snapshot",
templateRef: "snapshot-valid",
status: "active",
}).returning();
await expect(service.startSetupSession({
environmentId,
templateId: template!.id,
actor: { userId: "user-1" },
})).rejects.toThrow("Base image not found in registry");
const [session] = await db
.select({
status: environmentCustomImageSetupSessions.status,
failureReason: environmentCustomImageSetupSessions.failureReason,
})
.from(environmentCustomImageSetupSessions)
.where(eq(environmentCustomImageSetupSessions.templateId, template!.id));
expect(session).toEqual({
status: "failed",
failureReason: "Base image not found in registry",
});
});
it("applies the active template regardless of base-config changes and falls back when none exists", async () => {
const { companyId, environmentId } = await seed();
const environment = await db.select().from(environments).where(eq(environments.id, environmentId)).then((rows) => rows[0]!);
@@ -192,7 +192,7 @@ function providerErrorMessage(error: unknown): string {
function isProviderMissingTemplateError(error: unknown): boolean {
const message = providerErrorMessage(error).toLowerCase();
return (
(message.includes("snapshot") || message.includes("template") || message.includes("image"))
(message.includes("snapshot") || message.includes("template"))
&& (message.includes("not found") || message.includes("missing"))
);
}
+44
View File
@@ -531,6 +531,50 @@ describe("CompanyEnvironments — test provider button", () => {
expect(container.textContent).toContain("Test probes clean up the validation sandbox after the check");
});
it("does not show sandbox lifecycle success copy for failed sandbox provider tests", async () => {
root = createRoot(container);
const queryClient = new QueryClient({ defaultOptions: { queries: { retry: false } } });
mockEnvironmentsApi.list.mockResolvedValue([
{ id: "env-1", name: "Daytona", driver: "sandbox", description: null, config: { provider: "daytona" } },
]);
mockEnvironmentsApi.capabilities.mockResolvedValue(supportedDaytonaCapabilities());
mockEnvironmentsApi.probe.mockResolvedValue({
ok: false,
driver: "sandbox",
summary: "Daytona sandbox probe failed.",
details: {
provider: "daytona",
error: "Sandbox image was not found.",
metadata: {
provider: "daytona",
sandboxId: "473167E9",
sandboxName: "paperclip-probe",
},
},
});
await act(async () => {
root!.render(
<QueryClientProvider client={queryClient}>
<TooltipProvider>
<CompanyEnvironments />
</TooltipProvider>
</QueryClientProvider>,
);
});
await flushReact();
await act(async () => {
testProviderButtons(container)[0].dispatchEvent(new MouseEvent("click", { bubbles: true }));
});
await flushReact();
expect(container.textContent).toContain("Daytona sandbox probe failed.");
expect(container.textContent).toContain("Sandbox image was not found.");
expect(container.textContent).not.toContain("Verified temporary daytona sandbox");
expect(container.textContent).not.toContain("Test probes clean up the validation sandbox after the check");
});
it("keeps the second environment's testing state when an earlier probe settles", async () => {
root = createRoot(container);
const queryClient = new QueryClient({ defaultOptions: { queries: { retry: false } } });
+1 -1
View File
@@ -215,7 +215,7 @@ function readStringValue(value: unknown): string | null {
}
function sandboxProbeLifecycleNote(probe: EnvironmentProbeResult): string | null {
if (probe.driver !== "sandbox") return null;
if (probe.driver !== "sandbox" || !probe.ok) return null;
const metadata = readProbeMetadata(probe);
const provider = readStringValue(metadata.provider) ?? readStringValue(readRecord(probe.details)?.provider) ?? "sandbox";
const sandboxName = readStringValue(metadata.sandboxName);