Skip to content

Commit e629bda

Browse files
committed
feat: add individual deployment deletion
1 parent da32de0 commit e629bda

File tree

2 files changed

+50
-1
lines changed

2 files changed

+50
-1
lines changed

apps/dokploy/components/dashboard/application/deployments/show-deployments.tsx

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import {
66
RefreshCcw,
77
RocketIcon,
88
Settings,
9+
Trash2,
910
} from "lucide-react";
1011
import React, { useEffect, useMemo, useState } from "react";
1112
import { toast } from "sonner";
@@ -78,6 +79,8 @@ export const ShowDeployments = ({
7879
api.rollback.rollback.useMutation();
7980
const { mutateAsync: killProcess, isLoading: isKillingProcess } =
8081
api.deployment.killProcess.useMutation();
82+
const { mutateAsync: removeDeployment, isLoading: isRemovingDeployment } =
83+
api.deployment.removeDeployment.useMutation();
8184

8285
// Cancel deployment mutations
8386
const {
@@ -256,7 +259,15 @@ export const ShowDeployments = ({
256259
const isExpanded = expandedDescriptions.has(
257260
deployment.deploymentId,
258261
);
259-
262+
const lastSuccessfulDeployment = deployments?.find(
263+
(d) => d.status === "done"
264+
);
265+
const isLastSuccessfulDeployment =
266+
lastSuccessfulDeployment?.deploymentId === deployment.deploymentId;
267+
const canDelete =
268+
deployments &&
269+
deployments.length > 1 &&
270+
!isLastSuccessfulDeployment;
260271
return (
261272
<div
262273
key={deployment.deploymentId}
@@ -372,6 +383,33 @@ export const ShowDeployments = ({
372383
View
373384
</Button>
374385

386+
{canDelete && (
387+
<DialogAction
388+
title="Delete Deployment"
389+
description="Are you sure you want to delete this deployment? This action cannot be undone."
390+
type="default"
391+
onClick={async () => {
392+
try {
393+
await removeDeployment({
394+
deploymentId: deployment.deploymentId,
395+
});
396+
toast.success("Deployment deleted successfully");
397+
} catch (error) {
398+
toast.error("Error deleting deployment");
399+
}
400+
}}
401+
>
402+
<Button
403+
variant="destructive"
404+
size="sm"
405+
isLoading={isRemovingDeployment}
406+
>
407+
Delete
408+
<Trash2 className="size-4" />
409+
</Button>
410+
</DialogAction>
411+
)}
412+
375413
{deployment?.rollback &&
376414
deployment.status === "done" &&
377415
type === "application" && (

apps/dokploy/server/api/routers/deployment.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import {
88
findComposeById,
99
findDeploymentById,
1010
findServerById,
11+
removeDeployment,
1112
updateDeploymentStatus,
1213
} from "@dokploy/server";
1314
import { TRPCError } from "@trpc/server";
@@ -107,4 +108,14 @@ export const deploymentRouter = createTRPCRouter({
107108

108109
await updateDeploymentStatus(deployment.deploymentId, "error");
109110
}),
111+
112+
removeDeployment: protectedProcedure
113+
.input(
114+
z.object({
115+
deploymentId: z.string().min(1),
116+
}),
117+
)
118+
.mutation(async ({ input }) => {
119+
return await removeDeployment(input.deploymentId);
120+
}),
110121
});

0 commit comments

Comments
 (0)