diff --git a/apps/dokploy/server/api/routers/application.ts b/apps/dokploy/server/api/routers/application.ts index f08f6d555..157a89630 100644 --- a/apps/dokploy/server/api/routers/application.ts +++ b/apps/dokploy/server/api/routers/application.ts @@ -1,7 +1,7 @@ import { addNewService, checkServiceAccess, - clearOldDeploymentsByApplicationId, + clearOldDeployments, createApplication, deleteAllMiddlewares, findApplicationById, @@ -761,9 +761,7 @@ export const applicationRouter = createTRPCRouter({ "You are not authorized to clear deployments for this application", }); } - const result = await clearOldDeploymentsByApplicationId( - input.applicationId, - ); + const result = await clearOldDeployments(input.applicationId); return { success: true, message: `${result.deletedCount} old deployments cleared successfully`, diff --git a/apps/dokploy/server/api/routers/compose.ts b/apps/dokploy/server/api/routers/compose.ts index fb5ba9b1c..de99e4d7f 100644 --- a/apps/dokploy/server/api/routers/compose.ts +++ b/apps/dokploy/server/api/routers/compose.ts @@ -2,7 +2,7 @@ import { addDomainToCompose, addNewService, checkServiceAccess, - clearOldDeploymentsByComposeId, + clearOldDeployments, cloneCompose, createCommand, createCompose, @@ -278,7 +278,7 @@ export const composeRouter = createTRPCRouter({ "You are not authorized to clear deployments for this compose", }); } - const result = await clearOldDeploymentsByComposeId(input.composeId); + const result = await clearOldDeployments(input.composeId, "compose"); return { success: true, message: `${result.deletedCount} old deployments cleared successfully`, diff --git a/packages/server/src/services/deployment.ts b/packages/server/src/services/deployment.ts index 18f3d96aa..5af7ebc80 100644 --- a/packages/server/src/services/deployment.ts +++ b/packages/server/src/services/deployment.ts @@ -19,7 +19,7 @@ import { } from "@dokploy/server/utils/process/execAsync"; import { TRPCError } from "@trpc/server"; import { format } from "date-fns"; -import { desc, eq } from "drizzle-orm"; +import { and, desc, eq, or } from "drizzle-orm"; import { type Application, findApplicationById, @@ -852,110 +852,24 @@ export const findAllDeploymentsByServerId = async (serverId: string) => { return deploymentsList; }; -export const clearOldDeploymentsByApplicationId = async ( - applicationId: string, +export const clearOldDeployments = async ( + id: string, + type: "application" | "compose" = "application", ) => { // Get all deployments ordered by creation date (newest first) const deploymentsList = await db.query.deployments.findMany({ - where: eq(deployments.applicationId, applicationId), + where: and( + eq(deployments[`${type}Id`], id), + or(eq(deployments.status, "done"), eq(deployments.status, "error")), + ), orderBy: desc(deployments.createdAt), }); - // Find the most recent successful deployment (status "done") - const activeDeployment = deploymentsList.find( - (deployment) => deployment.status === "done", - ); - - // If there's an active deployment, keep it and remove all others - // If there's no active deployment, keep the most recent one and remove the rest - const deploymentsToKeep: string[] = []; - - if (activeDeployment) { - deploymentsToKeep.push(activeDeployment.deploymentId); - } else if (deploymentsList.length > 0) { - // Keep the most recent deployment even if it's not "done" - deploymentsToKeep.push(deploymentsList[0]!.deploymentId); - } - - const deploymentsToDelete = deploymentsList.filter( - (deployment) => !deploymentsToKeep.includes(deployment.deploymentId), - ); - - // Delete old deployments and their log files - for (const deployment of deploymentsToDelete) { - if (deployment.rollbackId) { - await removeRollbackById(deployment.rollbackId); - } - - // Remove log file if it exists - const logPath = deployment.logPath; - if (logPath && logPath !== "." && existsSync(logPath)) { - try { - await fsPromises.unlink(logPath); - } catch (error) { - console.error(`Error removing log file ${logPath}:`, error); - } - } - - // Delete deployment from database + for (const deployment of deploymentsList) { await removeDeployment(deployment.deploymentId); } return { - deletedCount: deploymentsToDelete.length, - keptDeployment: deploymentsToKeep[0] || null, - }; -}; - -export const clearOldDeploymentsByComposeId = async (composeId: string) => { - // Get all deployments ordered by creation date (newest first) - const deploymentsList = await db.query.deployments.findMany({ - where: eq(deployments.composeId, composeId), - orderBy: desc(deployments.createdAt), - }); - - // Find the most recent successful deployment (status "done") - const activeDeployment = deploymentsList.find( - (deployment) => deployment.status === "done", - ); - - // If there's an active deployment, keep it and remove all others - // If there's no active deployment, keep the most recent one and remove the rest - const deploymentsToKeep: string[] = []; - - if (activeDeployment) { - deploymentsToKeep.push(activeDeployment.deploymentId); - } else if (deploymentsList.length > 0) { - // Keep the most recent deployment even if it's not "done" - deploymentsToKeep.push(deploymentsList[0]!.deploymentId); - } - - const deploymentsToDelete = deploymentsList.filter( - (deployment) => !deploymentsToKeep.includes(deployment.deploymentId), - ); - - // Delete old deployments and their log files - for (const deployment of deploymentsToDelete) { - if (deployment.rollbackId) { - await removeRollbackById(deployment.rollbackId); - } - - // Remove log file if it exists - const logPath = deployment.logPath; - if (logPath && logPath !== "." && existsSync(logPath)) { - try { - await fsPromises.unlink(logPath); - } catch (error) { - console.error(`Error removing log file ${logPath}:`, error); - } - } - - // Delete deployment from database - await removeDeployment(deployment.deploymentId); - } - - return { - deletedCount: deploymentsToDelete.length, - keptDeployment: deploymentsToKeep[0] || null, + deletedCount: deploymentsList.length, }; };