feat/fix: fixed stop button & added start button

This commit is contained in:
190km
2024-12-03 02:20:20 +01:00
parent 63998f71ec
commit fd0a472468
6 changed files with 295 additions and 116 deletions

View File

@@ -14,6 +14,7 @@ import { CheckCircle2, ExternalLink, Globe, Terminal } from "lucide-react";
import Link from "next/link";
import { toast } from "sonner";
import { DockerTerminalModal } from "../../settings/web-server/docker-terminal-modal";
import { StartCompose } from "../start-compose";
import { DeployCompose } from "./deploy-compose";
import { RedbuildCompose } from "./rebuild-compose";
import { StopCompose } from "./stop-compose";
@@ -71,7 +72,10 @@ export const ComposeActions = ({ composeId }: Props) => {
Autodeploy {data?.autoDeploy && <CheckCircle2 className="size-4" />}
</Toggle>
<RedbuildCompose composeId={composeId} />
{data?.composeType === "docker-compose" && (
{data?.composeType === "docker-compose" &&
data?.composeStatus === "idle" ? (
<StartCompose composeId={composeId} />
) : (
<StopCompose composeId={composeId} />
)}

View File

@@ -0,0 +1,65 @@
import {
AlertDialog,
AlertDialogAction,
AlertDialogCancel,
AlertDialogContent,
AlertDialogDescription,
AlertDialogFooter,
AlertDialogHeader,
AlertDialogTitle,
AlertDialogTrigger,
} from "@/components/ui/alert-dialog";
import { Button } from "@/components/ui/button";
import { api } from "@/utils/api";
import { CheckCircle2 } from "lucide-react";
import { toast } from "sonner";
interface Props {
composeId: string;
}
export const StartCompose = ({ composeId }: Props) => {
const { mutateAsync, isLoading } = api.compose.start.useMutation();
const utils = api.useUtils();
return (
<AlertDialog>
<AlertDialogTrigger asChild>
<Button variant="secondary" isLoading={isLoading}>
Start
<CheckCircle2 className="size-4" />
</Button>
</AlertDialogTrigger>
<AlertDialogContent>
<AlertDialogHeader>
<AlertDialogTitle>
Are you sure to start the compose?
</AlertDialogTitle>
<AlertDialogDescription>
This will start the compose
</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
<AlertDialogCancel>Cancel</AlertDialogCancel>
<AlertDialogAction
onClick={async () => {
await mutateAsync({
composeId,
})
.then(async () => {
await utils.compose.one.invalidate({
composeId,
});
toast.success("Compose started succesfully");
})
.catch(() => {
toast.error("Error to start the Compose");
});
}}
>
Confirm
</AlertDialogAction>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
);
};

View File

@@ -0,0 +1,65 @@
import {
AlertDialog,
AlertDialogAction,
AlertDialogCancel,
AlertDialogContent,
AlertDialogDescription,
AlertDialogFooter,
AlertDialogHeader,
AlertDialogTitle,
AlertDialogTrigger,
} from "@/components/ui/alert-dialog";
import { Button } from "@/components/ui/button";
import { api } from "@/utils/api";
import { Ban } from "lucide-react";
import { toast } from "sonner";
interface Props {
composeId: string;
}
export const StopCompose = ({ composeId }: Props) => {
const { mutateAsync, isLoading } = api.compose.stop.useMutation();
const utils = api.useUtils();
return (
<AlertDialog>
<AlertDialogTrigger asChild>
<Button variant="destructive" isLoading={isLoading}>
Stop
<Ban className="size-4" />
</Button>
</AlertDialogTrigger>
<AlertDialogContent>
<AlertDialogHeader>
<AlertDialogTitle>
Are you absolutely sure to stop the compose?
</AlertDialogTitle>
<AlertDialogDescription>
This will stop the compose
</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
<AlertDialogCancel>Cancel</AlertDialogCancel>
<AlertDialogAction
onClick={async () => {
await mutateAsync({
composeId,
})
.then(async () => {
await utils.compose.one.invalidate({
composeId,
});
toast.success("Compose stopped succesfully");
})
.catch(() => {
toast.error("Error to stop the Compose");
});
}}
>
Confirm
</AlertDialogAction>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
);
};

View File

@@ -11,7 +11,7 @@ import { extractCommitMessage, extractHash } from "./[refreshToken]";
export default async function handler(
req: NextApiRequest,
res: NextApiResponse
res: NextApiResponse,
) {
const signature = req.headers["x-hub-signature-256"];
const githubBody = req.body;
@@ -40,7 +40,7 @@ export default async function handler(
const verified = await webhooks.verify(
JSON.stringify(githubBody),
signature as string
signature as string,
);
if (!verified) {
@@ -69,7 +69,7 @@ export default async function handler(
eq(applications.sourceType, "github"),
eq(applications.autoDeploy, true),
eq(applications.branch, branchName),
eq(applications.repository, repository)
eq(applications.repository, repository),
),
});
@@ -94,7 +94,7 @@ export default async function handler(
{
removeOnComplete: true,
removeOnFail: true,
}
},
);
}
@@ -103,7 +103,7 @@ export default async function handler(
eq(compose.sourceType, "github"),
eq(compose.autoDeploy, true),
eq(compose.branch, branchName),
eq(compose.repository, repository)
eq(compose.repository, repository),
),
});
@@ -129,7 +129,7 @@ export default async function handler(
{
removeOnComplete: true,
removeOnFail: true,
}
},
);
}

View File

@@ -48,6 +48,7 @@ import {
removeCompose,
removeComposeDirectory,
removeDeploymentsByComposeId,
startCompose,
stopCompose,
updateCompose,
} from "@dokploy/server";
@@ -309,6 +310,20 @@ export const composeRouter = createTRPCRouter({
}
await stopCompose(input.composeId);
return true;
}),
start: protectedProcedure
.input(apiFindCompose)
.mutation(async ({ input, ctx }) => {
const compose = await findComposeById(input.composeId);
if (compose.project.adminId !== ctx.user.adminId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to stop this compose",
});
}
await startCompose(input.composeId);
return true;
}),
getDefaultCommand: protectedProcedure

View File

@@ -463,6 +463,36 @@ export const removeCompose = async (compose: Compose) => {
return true;
};
export const startCompose = async (composeId: string) => {
const compose = await findComposeById(composeId);
try {
const { COMPOSE_PATH } = paths(!!compose.serverId);
if (compose.composeType === "docker-compose") {
if (compose.serverId) {
await execAsyncRemote(
compose.serverId,
`cd ${join(COMPOSE_PATH, compose.appName, "code")} && docker compose -p ${compose.appName} up -d`,
);
} else {
await execAsync(`docker compose -p ${compose.appName} up -d`, {
cwd: join(COMPOSE_PATH, compose.appName, "code"),
});
}
}
await updateCompose(composeId, {
composeStatus: "done",
});
} catch (error) {
await updateCompose(composeId, {
composeStatus: "idle",
});
throw error;
}
return true;
};
export const stopCompose = async (composeId: string) => {
const compose = await findComposeById(composeId);
try {