diff --git a/apps/dokploy/__test__/deploy/preview-build-server.test.ts b/apps/dokploy/__test__/deploy/preview-build-server.test.ts index 4ab4a63d4..8c9ba9fdf 100644 --- a/apps/dokploy/__test__/deploy/preview-build-server.test.ts +++ b/apps/dokploy/__test__/deploy/preview-build-server.test.ts @@ -102,6 +102,7 @@ const createMockPreview = () => ({ deployments: [ { buildServerId: "build-server-id", + status: "done", }, ], domain: { @@ -230,6 +231,7 @@ describe("preview deployment build server and registry", () => { deployments: [ { buildServerId: "previous-build-server-id", + status: "done", }, ], } as any); @@ -270,6 +272,39 @@ describe("preview deployment build server and registry", () => { deployments: [ { buildServerId: null, + status: "done", + }, + ], + } as any); + + await rebuildPreviewApplication({ + applicationId: "application-id", + previewDeploymentId: "preview-id", + titleLog: "Rebuild preview deployment", + descriptionLog: "", + }); + + expect(githubProvider.cloneGithubRepository).toHaveBeenCalledWith( + expect.objectContaining({ + serverId: "build-server-id", + appName: "preview-test-application", + branch: "feature/test-preview", + }), + ); + + expect(execProcess.execAsyncRemote).toHaveBeenCalledWith( + "build-server-id", + expect.stringContaining("git clone command;"), + ); + }); + + it("reclones after a failed deployment on the same build server", async () => { + vi.mocked(previewService.findPreviewDeploymentById).mockResolvedValue({ + ...createMockPreview(), + deployments: [ + { + buildServerId: "build-server-id", + status: "error", }, ], } as any); diff --git a/apps/dokploy/__test__/deploy/preview-cleanup-build-servers.test.ts b/apps/dokploy/__test__/deploy/preview-cleanup-build-servers.test.ts index 273b651d1..d8cc20d21 100644 --- a/apps/dokploy/__test__/deploy/preview-cleanup-build-servers.test.ts +++ b/apps/dokploy/__test__/deploy/preview-cleanup-build-servers.test.ts @@ -126,4 +126,25 @@ describe("preview deployment cleanup", () => { "deployment-server-id", ); }); + + it("keeps preview records when cleanup on a historical build server fails", async () => { + vi.mocked(directoryUtils.removeDirectoryCode).mockImplementation( + async (_appName, serverId) => { + if (serverId === "previous-build-server-id") { + throw new Error("Historical build server is unavailable"); + } + }, + ); + + await expect(removePreviewDeployment("preview-id")).rejects.toThrow( + "Historical build server is unavailable", + ); + + expect(directoryUtils.removeDirectoryCode).toHaveBeenCalledWith( + "preview-test-application", + "previous-build-server-id", + ); + + expect(db.delete).not.toHaveBeenCalled(); + }); }); diff --git a/apps/dokploy/__test__/deploy/preview-pruning-build-servers.test.ts b/apps/dokploy/__test__/deploy/preview-pruning-build-servers.test.ts index 88300277d..48168d84d 100644 --- a/apps/dokploy/__test__/deploy/preview-pruning-build-servers.test.ts +++ b/apps/dokploy/__test__/deploy/preview-pruning-build-servers.test.ts @@ -16,6 +16,7 @@ vi.mock("@dokploy/server/db", () => ({ query: { deployments: { findMany: vi.fn(), + findFirst: vi.fn(), }, }, delete: vi.fn(() => ({ @@ -76,6 +77,10 @@ describe("preview deployment pruning", () => { rollbackId: null, }; + vi.mocked(db.query.deployments.findFirst).mockResolvedValue( + prunedDeployment as any, + ); + vi.mocked(db.query.deployments.findMany).mockResolvedValue([ ...retainedDeployments, prunedDeployment, @@ -137,4 +142,24 @@ describe("preview deployment pruning", () => { expect.stringContaining("Initializing deployment"), ); }); + + it("keeps historical deployment records when source cleanup fails", async () => { + vi.mocked(directoryUtils.removeDirectoryCode).mockRejectedValueOnce( + new Error("Historical build server is unavailable"), + ); + + await createDeploymentPreview({ + title: "Preview deployment", + description: "", + previewDeploymentId: "preview-id", + }); + + expect(directoryUtils.removeDirectoryCode).toHaveBeenCalledWith( + "preview-test-application", + "previous-build-server-id", + ); + + expect(db.query.deployments.findFirst).not.toHaveBeenCalled(); + expect(db.delete).not.toHaveBeenCalled(); + }); });