mirror of
https://github.com/Dokploy/dokploy
synced 2025-06-26 18:27:59 +00:00
feat: deploy compose on external servers
This commit is contained in:
@@ -11,7 +11,7 @@ interface Props {
|
|||||||
logPath: string | null;
|
logPath: string | null;
|
||||||
open: boolean;
|
open: boolean;
|
||||||
onClose: () => void;
|
onClose: () => void;
|
||||||
serverId: string;
|
serverId?: string;
|
||||||
}
|
}
|
||||||
export const ShowDeployment = ({ logPath, open, onClose, serverId }: Props) => {
|
export const ShowDeployment = ({ logPath, open, onClose, serverId }: Props) => {
|
||||||
const [data, setData] = useState("");
|
const [data, setData] = useState("");
|
||||||
|
|||||||
@@ -9,10 +9,16 @@ import { useEffect, useRef, useState } from "react";
|
|||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
logPath: string | null;
|
logPath: string | null;
|
||||||
|
serverId?: string;
|
||||||
open: boolean;
|
open: boolean;
|
||||||
onClose: () => void;
|
onClose: () => void;
|
||||||
}
|
}
|
||||||
export const ShowDeploymentCompose = ({ logPath, open, onClose }: Props) => {
|
export const ShowDeploymentCompose = ({
|
||||||
|
logPath,
|
||||||
|
open,
|
||||||
|
onClose,
|
||||||
|
serverId,
|
||||||
|
}: Props) => {
|
||||||
const [data, setData] = useState("");
|
const [data, setData] = useState("");
|
||||||
const endOfLogsRef = useRef<HTMLDivElement>(null);
|
const endOfLogsRef = useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
@@ -21,7 +27,7 @@ export const ShowDeploymentCompose = ({ logPath, open, onClose }: Props) => {
|
|||||||
|
|
||||||
const protocol = window.location.protocol === "https:" ? "wss:" : "ws:";
|
const protocol = window.location.protocol === "https:" ? "wss:" : "ws:";
|
||||||
|
|
||||||
const wsUrl = `${protocol}//${window.location.host}/listen-deployment?logPath=${logPath}`;
|
const wsUrl = `${protocol}//${window.location.host}/listen-deployment?logPath=${logPath}&serverId=${serverId}`;
|
||||||
const ws = new WebSocket(wsUrl);
|
const ws = new WebSocket(wsUrl);
|
||||||
|
|
||||||
ws.onmessage = (e) => {
|
ws.onmessage = (e) => {
|
||||||
|
|||||||
@@ -111,6 +111,7 @@ export const ShowDeploymentsCompose = ({ composeId }: Props) => {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<ShowDeploymentCompose
|
<ShowDeploymentCompose
|
||||||
|
serverId={data?.serverId || ""}
|
||||||
open={activeLog !== null}
|
open={activeLog !== null}
|
||||||
onClose={() => setActiveLog(null)}
|
onClose={() => setActiveLog(null)}
|
||||||
logPath={activeLog}
|
logPath={activeLog}
|
||||||
|
|||||||
@@ -116,6 +116,7 @@ export const ComposeActions = ({ composeId }: Props) => {
|
|||||||
</DropdownMenuContent>
|
</DropdownMenuContent>
|
||||||
</DropdownMenu>
|
</DropdownMenu>
|
||||||
)}
|
)}
|
||||||
|
{data?.server?.name}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -173,9 +173,7 @@ export const AddApplication = ({ projectId, projectName }: Props) => {
|
|||||||
{server.name}
|
{server.name}
|
||||||
</SelectItem>
|
</SelectItem>
|
||||||
))}
|
))}
|
||||||
<SelectLabel>
|
<SelectLabel>Servers ({servers?.length})</SelectLabel>
|
||||||
Registries ({servers?.length})
|
|
||||||
</SelectLabel>
|
|
||||||
</SelectGroup>
|
</SelectGroup>
|
||||||
</SelectContent>
|
</SelectContent>
|
||||||
</Select>
|
</Select>
|
||||||
|
|||||||
@@ -22,7 +22,9 @@ import { Input } from "@/components/ui/input";
|
|||||||
import {
|
import {
|
||||||
Select,
|
Select,
|
||||||
SelectContent,
|
SelectContent,
|
||||||
|
SelectGroup,
|
||||||
SelectItem,
|
SelectItem,
|
||||||
|
SelectLabel,
|
||||||
SelectTrigger,
|
SelectTrigger,
|
||||||
SelectValue,
|
SelectValue,
|
||||||
} from "@/components/ui/select";
|
} from "@/components/ui/select";
|
||||||
@@ -51,6 +53,9 @@ const AddComposeSchema = z.object({
|
|||||||
"App name supports lowercase letters, numbers, '-' and can only start and end letters, and does not support continuous '-'",
|
"App name supports lowercase letters, numbers, '-' and can only start and end letters, and does not support continuous '-'",
|
||||||
}),
|
}),
|
||||||
description: z.string().optional(),
|
description: z.string().optional(),
|
||||||
|
serverId: z.string().min(1, {
|
||||||
|
message: "Server is required",
|
||||||
|
}),
|
||||||
});
|
});
|
||||||
|
|
||||||
type AddCompose = z.infer<typeof AddComposeSchema>;
|
type AddCompose = z.infer<typeof AddComposeSchema>;
|
||||||
@@ -63,6 +68,7 @@ interface Props {
|
|||||||
export const AddCompose = ({ projectId, projectName }: Props) => {
|
export const AddCompose = ({ projectId, projectName }: Props) => {
|
||||||
const utils = api.useUtils();
|
const utils = api.useUtils();
|
||||||
const slug = slugify(projectName);
|
const slug = slugify(projectName);
|
||||||
|
const { data: servers } = api.server.all.useQuery();
|
||||||
const { mutateAsync, isLoading, error, isError } =
|
const { mutateAsync, isLoading, error, isError } =
|
||||||
api.compose.create.useMutation();
|
api.compose.create.useMutation();
|
||||||
|
|
||||||
@@ -72,6 +78,7 @@ export const AddCompose = ({ projectId, projectName }: Props) => {
|
|||||||
description: "",
|
description: "",
|
||||||
composeType: "docker-compose",
|
composeType: "docker-compose",
|
||||||
appName: `${slug}-`,
|
appName: `${slug}-`,
|
||||||
|
serverId: "",
|
||||||
},
|
},
|
||||||
resolver: zodResolver(AddComposeSchema),
|
resolver: zodResolver(AddComposeSchema),
|
||||||
});
|
});
|
||||||
@@ -87,6 +94,7 @@ export const AddCompose = ({ projectId, projectName }: Props) => {
|
|||||||
projectId,
|
projectId,
|
||||||
composeType: data.composeType,
|
composeType: data.composeType,
|
||||||
appName: data.appName,
|
appName: data.appName,
|
||||||
|
serverId: data.serverId,
|
||||||
})
|
})
|
||||||
.then(async () => {
|
.then(async () => {
|
||||||
toast.success("Compose Created");
|
toast.success("Compose Created");
|
||||||
@@ -148,6 +156,37 @@ export const AddCompose = ({ projectId, projectName }: Props) => {
|
|||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
<FormField
|
||||||
|
control={form.control}
|
||||||
|
name="serverId"
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem>
|
||||||
|
<FormLabel>Select a Server</FormLabel>
|
||||||
|
<Select
|
||||||
|
onValueChange={field.onChange}
|
||||||
|
defaultValue={field.value}
|
||||||
|
>
|
||||||
|
<SelectTrigger>
|
||||||
|
<SelectValue placeholder="Select a Server" />
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
<SelectGroup>
|
||||||
|
{servers?.map((server) => (
|
||||||
|
<SelectItem
|
||||||
|
key={server.serverId}
|
||||||
|
value={server.serverId}
|
||||||
|
>
|
||||||
|
{server.name}
|
||||||
|
</SelectItem>
|
||||||
|
))}
|
||||||
|
<SelectLabel>Servers ({servers?.length})</SelectLabel>
|
||||||
|
</SelectGroup>
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
<FormMessage />
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
<FormField
|
<FormField
|
||||||
control={form.control}
|
control={form.control}
|
||||||
name="appName"
|
name="appName"
|
||||||
|
|||||||
@@ -59,7 +59,6 @@ import { addNewService, checkServiceAccess } from "../services/user";
|
|||||||
|
|
||||||
import { unzipDrop } from "@/server/utils/builders/drop";
|
import { unzipDrop } from "@/server/utils/builders/drop";
|
||||||
import { uploadFileSchema } from "@/utils/schema";
|
import { uploadFileSchema } from "@/utils/schema";
|
||||||
import { Queue } from "bullmq";
|
|
||||||
|
|
||||||
export const applicationRouter = createTRPCRouter({
|
export const applicationRouter = createTRPCRouter({
|
||||||
create: protectedProcedure
|
create: protectedProcedure
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import {
|
|||||||
type DeploymentJob,
|
type DeploymentJob,
|
||||||
cleanQueuesByCompose,
|
cleanQueuesByCompose,
|
||||||
} from "@/server/queues/deployments-queue";
|
} from "@/server/queues/deployments-queue";
|
||||||
import { myQueue } from "@/server/queues/queueSetup";
|
import { enqueueDeploymentJob, myQueue } from "@/server/queues/queueSetup";
|
||||||
import { createCommand } from "@/server/utils/builders/compose";
|
import { createCommand } from "@/server/utils/builders/compose";
|
||||||
import {
|
import {
|
||||||
randomizeComposeFile,
|
randomizeComposeFile,
|
||||||
@@ -49,6 +49,7 @@ import { createMount } from "../services/mount";
|
|||||||
import { findProjectById } from "../services/project";
|
import { findProjectById } from "../services/project";
|
||||||
import { addNewService, checkServiceAccess } from "../services/user";
|
import { addNewService, checkServiceAccess } from "../services/user";
|
||||||
import { createTRPCRouter, protectedProcedure } from "../trpc";
|
import { createTRPCRouter, protectedProcedure } from "../trpc";
|
||||||
|
import { findApplicationById } from "../services/application";
|
||||||
|
|
||||||
export const composeRouter = createTRPCRouter({
|
export const composeRouter = createTRPCRouter({
|
||||||
create: protectedProcedure
|
create: protectedProcedure
|
||||||
@@ -162,6 +163,22 @@ export const composeRouter = createTRPCRouter({
|
|||||||
deploy: protectedProcedure
|
deploy: protectedProcedure
|
||||||
.input(apiFindCompose)
|
.input(apiFindCompose)
|
||||||
.mutation(async ({ input }) => {
|
.mutation(async ({ input }) => {
|
||||||
|
// const jobData: DeploymentJob = {
|
||||||
|
// composeId: input.composeId,
|
||||||
|
// titleLog: "Manual deployment",
|
||||||
|
// type: "deploy",
|
||||||
|
// applicationType: "compose",
|
||||||
|
// descriptionLog: "",
|
||||||
|
// };
|
||||||
|
// await myQueue.add(
|
||||||
|
// "deployments",
|
||||||
|
// { ...jobData },
|
||||||
|
// {
|
||||||
|
// removeOnComplete: true,
|
||||||
|
// removeOnFail: true,
|
||||||
|
// },
|
||||||
|
// );
|
||||||
|
const compose = await findComposeById(input.composeId);
|
||||||
const jobData: DeploymentJob = {
|
const jobData: DeploymentJob = {
|
||||||
composeId: input.composeId,
|
composeId: input.composeId,
|
||||||
titleLog: "Manual deployment",
|
titleLog: "Manual deployment",
|
||||||
@@ -169,14 +186,10 @@ export const composeRouter = createTRPCRouter({
|
|||||||
applicationType: "compose",
|
applicationType: "compose",
|
||||||
descriptionLog: "",
|
descriptionLog: "",
|
||||||
};
|
};
|
||||||
await myQueue.add(
|
if (!compose.serverId) {
|
||||||
"deployments",
|
} else {
|
||||||
{ ...jobData },
|
await enqueueDeploymentJob(compose.serverId, jobData);
|
||||||
{
|
}
|
||||||
removeOnComplete: true,
|
|
||||||
removeOnFail: true,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}),
|
}),
|
||||||
redeploy: protectedProcedure
|
redeploy: protectedProcedure
|
||||||
.input(apiFindCompose)
|
.input(apiFindCompose)
|
||||||
|
|||||||
@@ -3,23 +3,43 @@ import { COMPOSE_PATH } from "@/server/constants";
|
|||||||
import { db } from "@/server/db";
|
import { db } from "@/server/db";
|
||||||
import { type apiCreateCompose, compose } from "@/server/db/schema";
|
import { type apiCreateCompose, compose } from "@/server/db/schema";
|
||||||
import { generateAppName } from "@/server/db/schema/utils";
|
import { generateAppName } from "@/server/db/schema/utils";
|
||||||
import { buildCompose } from "@/server/utils/builders/compose";
|
import {
|
||||||
|
buildCompose,
|
||||||
|
getBuildComposeCommand,
|
||||||
|
} from "@/server/utils/builders/compose";
|
||||||
import { randomizeSpecificationFile } from "@/server/utils/docker/compose";
|
import { randomizeSpecificationFile } from "@/server/utils/docker/compose";
|
||||||
import { cloneCompose, loadDockerCompose } from "@/server/utils/docker/domain";
|
import { cloneCompose, loadDockerCompose } from "@/server/utils/docker/domain";
|
||||||
import { sendBuildErrorNotifications } from "@/server/utils/notifications/build-error";
|
import { sendBuildErrorNotifications } from "@/server/utils/notifications/build-error";
|
||||||
import { sendBuildSuccessNotifications } from "@/server/utils/notifications/build-success";
|
import { sendBuildSuccessNotifications } from "@/server/utils/notifications/build-success";
|
||||||
import { execAsync } from "@/server/utils/process/execAsync";
|
import { execAsync } from "@/server/utils/process/execAsync";
|
||||||
import { cloneBitbucketRepository } from "@/server/utils/providers/bitbucket";
|
import {
|
||||||
import { cloneGitRepository } from "@/server/utils/providers/git";
|
cloneBitbucketRepository,
|
||||||
import { cloneGithubRepository } from "@/server/utils/providers/github";
|
getBitbucketCloneCommand,
|
||||||
import { cloneGitlabRepository } from "@/server/utils/providers/gitlab";
|
} from "@/server/utils/providers/bitbucket";
|
||||||
import { createComposeFile } from "@/server/utils/providers/raw";
|
import {
|
||||||
|
cloneGitRepository,
|
||||||
|
getCustomGitCloneCommand,
|
||||||
|
} from "@/server/utils/providers/git";
|
||||||
|
import {
|
||||||
|
cloneGithubRepository,
|
||||||
|
getGithubCloneCommand,
|
||||||
|
} from "@/server/utils/providers/github";
|
||||||
|
import {
|
||||||
|
cloneGitlabRepository,
|
||||||
|
getGitlabCloneCommand,
|
||||||
|
} from "@/server/utils/providers/gitlab";
|
||||||
|
import {
|
||||||
|
createComposeFile,
|
||||||
|
getCreateComposeFileCommand,
|
||||||
|
} from "@/server/utils/providers/raw";
|
||||||
import { generatePassword } from "@/templates/utils";
|
import { generatePassword } from "@/templates/utils";
|
||||||
import { TRPCError } from "@trpc/server";
|
import { TRPCError } from "@trpc/server";
|
||||||
import { eq } from "drizzle-orm";
|
import { eq } from "drizzle-orm";
|
||||||
import { getDokployUrl } from "./admin";
|
import { getDokployUrl } from "./admin";
|
||||||
import { createDeploymentCompose, updateDeploymentStatus } from "./deployment";
|
import { createDeploymentCompose, updateDeploymentStatus } from "./deployment";
|
||||||
import { validUniqueServerAppName } from "./project";
|
import { validUniqueServerAppName } from "./project";
|
||||||
|
import { getBuildCommand } from "@/server/utils/builders";
|
||||||
|
import { executeCommand } from "@/server/utils/servers/command";
|
||||||
|
|
||||||
export type Compose = typeof compose.$inferSelect;
|
export type Compose = typeof compose.$inferSelect;
|
||||||
|
|
||||||
@@ -97,6 +117,7 @@ export const findComposeById = async (composeId: string) => {
|
|||||||
github: true,
|
github: true,
|
||||||
gitlab: true,
|
gitlab: true,
|
||||||
bitbucket: true,
|
bitbucket: true,
|
||||||
|
server: true,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
if (!result) {
|
if (!result) {
|
||||||
@@ -173,6 +194,40 @@ export const deployCompose = async ({
|
|||||||
});
|
});
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
if (compose.serverId) {
|
||||||
|
let command = `
|
||||||
|
set -e
|
||||||
|
`;
|
||||||
|
if (compose.sourceType === "github") {
|
||||||
|
command += await getGithubCloneCommand(
|
||||||
|
compose,
|
||||||
|
deployment.logPath,
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
} else if (compose.sourceType === "gitlab") {
|
||||||
|
command += await getGitlabCloneCommand(
|
||||||
|
compose,
|
||||||
|
deployment.logPath,
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
} else if (compose.sourceType === "bitbucket") {
|
||||||
|
command += await getBitbucketCloneCommand(
|
||||||
|
compose,
|
||||||
|
deployment.logPath,
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
} else if (compose.sourceType === "git") {
|
||||||
|
command += await getCustomGitCloneCommand(
|
||||||
|
compose,
|
||||||
|
deployment.logPath,
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
} else if (compose.sourceType === "raw") {
|
||||||
|
command += getCreateComposeFileCommand(compose);
|
||||||
|
}
|
||||||
|
command += getBuildComposeCommand(compose, deployment.logPath);
|
||||||
|
await executeCommand(compose.serverId, command);
|
||||||
|
} else {
|
||||||
if (compose.sourceType === "github") {
|
if (compose.sourceType === "github") {
|
||||||
await cloneGithubRepository(compose, deployment.logPath, true);
|
await cloneGithubRepository(compose, deployment.logPath, true);
|
||||||
} else if (compose.sourceType === "gitlab") {
|
} else if (compose.sourceType === "gitlab") {
|
||||||
@@ -184,7 +239,10 @@ export const deployCompose = async ({
|
|||||||
} else if (compose.sourceType === "raw") {
|
} else if (compose.sourceType === "raw") {
|
||||||
await createComposeFile(compose, deployment.logPath);
|
await createComposeFile(compose, deployment.logPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
await buildCompose(compose, deployment.logPath);
|
await buildCompose(compose, deployment.logPath);
|
||||||
|
}
|
||||||
|
|
||||||
await updateDeploymentStatus(deployment.deploymentId, "done");
|
await updateDeploymentStatus(deployment.deploymentId, "done");
|
||||||
await updateCompose(composeId, {
|
await updateCompose(composeId, {
|
||||||
composeStatus: "done",
|
composeStatus: "done",
|
||||||
|
|||||||
@@ -100,14 +100,27 @@ export const createDeploymentCompose = async (
|
|||||||
try {
|
try {
|
||||||
const compose = await findComposeById(deployment.composeId);
|
const compose = await findComposeById(deployment.composeId);
|
||||||
|
|
||||||
await removeLastTenComposeDeployments(deployment.composeId);
|
// await removeLastTenComposeDeployments(deployment.composeId);
|
||||||
const formattedDateTime = format(new Date(), "yyyy-MM-dd:HH:mm:ss");
|
const formattedDateTime = format(new Date(), "yyyy-MM-dd:HH:mm:ss");
|
||||||
const fileName = `${compose.appName}-${formattedDateTime}.log`;
|
const fileName = `${compose.appName}-${formattedDateTime}.log`;
|
||||||
const logFilePath = path.join(LOGS_PATH, compose.appName, fileName);
|
const logFilePath = path.join(LOGS_PATH, compose.appName, fileName);
|
||||||
|
|
||||||
|
if (compose.serverId) {
|
||||||
|
const server = await findServerById(compose.serverId);
|
||||||
|
|
||||||
|
const command = `
|
||||||
|
mkdir -p ${LOGS_PATH}/${compose.appName};
|
||||||
|
echo "Initializing deployment" >> ${logFilePath};
|
||||||
|
`;
|
||||||
|
|
||||||
|
await executeCommand(server.serverId, command);
|
||||||
|
} else {
|
||||||
await fsPromises.mkdir(path.join(LOGS_PATH, compose.appName), {
|
await fsPromises.mkdir(path.join(LOGS_PATH, compose.appName), {
|
||||||
recursive: true,
|
recursive: true,
|
||||||
});
|
});
|
||||||
await fsPromises.writeFile(logFilePath, "Initializing deployment");
|
await fsPromises.writeFile(logFilePath, "Initializing deployment");
|
||||||
|
}
|
||||||
|
|
||||||
const deploymentCreate = await db
|
const deploymentCreate = await db
|
||||||
.insert(deployments)
|
.insert(deployments)
|
||||||
.values({
|
.values({
|
||||||
|
|||||||
@@ -136,6 +136,7 @@ export const apiCreateCompose = createSchema.pick({
|
|||||||
projectId: true,
|
projectId: true,
|
||||||
composeType: true,
|
composeType: true,
|
||||||
appName: true,
|
appName: true,
|
||||||
|
serverId: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
export const apiCreateComposeByTemplate = createSchema
|
export const apiCreateComposeByTemplate = createSchema
|
||||||
|
|||||||
@@ -3,8 +3,14 @@ import { findServerById, type Server } from "../api/services/server";
|
|||||||
import type { DeploymentJob } from "./deployments-queue";
|
import type { DeploymentJob } from "./deployments-queue";
|
||||||
import {
|
import {
|
||||||
deployApplication,
|
deployApplication,
|
||||||
|
rebuildApplication,
|
||||||
updateApplicationStatus,
|
updateApplicationStatus,
|
||||||
} from "../api/services/application";
|
} from "../api/services/application";
|
||||||
|
import {
|
||||||
|
updateCompose,
|
||||||
|
deployCompose,
|
||||||
|
rebuildCompose,
|
||||||
|
} from "../api/services/compose";
|
||||||
|
|
||||||
export const redisConfig: ConnectionOptions = {
|
export const redisConfig: ConnectionOptions = {
|
||||||
host: "31.220.108.27",
|
host: "31.220.108.27",
|
||||||
@@ -54,15 +60,42 @@ async function setupServerQueueAndWorker(server: Server) {
|
|||||||
`deployments-${server.serverId}`,
|
`deployments-${server.serverId}`,
|
||||||
async (job: Job<DeploymentJob>) => {
|
async (job: Job<DeploymentJob>) => {
|
||||||
// Ejecuta el trabajo de despliegue
|
// Ejecuta el trabajo de despliegue
|
||||||
|
try {
|
||||||
if (job.data.applicationType === "application") {
|
if (job.data.applicationType === "application") {
|
||||||
await updateApplicationStatus(job.data.applicationId, "running");
|
await updateApplicationStatus(job.data.applicationId, "running");
|
||||||
if (job.data.type === "deploy") {
|
if (job.data.type === "redeploy") {
|
||||||
|
await rebuildApplication({
|
||||||
|
applicationId: job.data.applicationId,
|
||||||
|
titleLog: job.data.titleLog,
|
||||||
|
descriptionLog: job.data.descriptionLog,
|
||||||
|
});
|
||||||
|
} else if (job.data.type === "deploy") {
|
||||||
await deployApplication({
|
await deployApplication({
|
||||||
applicationId: job.data.applicationId,
|
applicationId: job.data.applicationId,
|
||||||
titleLog: job.data.titleLog,
|
titleLog: job.data.titleLog,
|
||||||
descriptionLog: job.data.descriptionLog,
|
descriptionLog: job.data.descriptionLog,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
} else if (job.data.applicationType === "compose") {
|
||||||
|
await updateCompose(job.data.composeId, {
|
||||||
|
composeStatus: "running",
|
||||||
|
});
|
||||||
|
if (job.data.type === "deploy") {
|
||||||
|
await deployCompose({
|
||||||
|
composeId: job.data.composeId,
|
||||||
|
titleLog: job.data.titleLog,
|
||||||
|
descriptionLog: job.data.descriptionLog,
|
||||||
|
});
|
||||||
|
} else if (job.data.type === "redeploy") {
|
||||||
|
await rebuildCompose({
|
||||||
|
composeId: job.data.composeId,
|
||||||
|
titleLog: job.data.titleLog,
|
||||||
|
descriptionLog: job.data.descriptionLog,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.log("Error", error);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -65,6 +65,30 @@ Compose Type: ${composeType} ✅`;
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const getBuildComposeCommand = (
|
||||||
|
compose: ComposeNested,
|
||||||
|
logPath: string,
|
||||||
|
) => {
|
||||||
|
const { sourceType, appName, mounts, composeType, domains } = compose;
|
||||||
|
const command = createCommand(compose);
|
||||||
|
const projectPath = join(COMPOSE_PATH, compose.appName, "code");
|
||||||
|
const logContent = `
|
||||||
|
App Name: ${appName}
|
||||||
|
Build Compose 🐳
|
||||||
|
Detected: ${mounts.length} mounts 📂
|
||||||
|
Command: docker ${command}
|
||||||
|
Source Type: docker ${sourceType} ✅
|
||||||
|
Compose Type: ${composeType} ✅`;
|
||||||
|
|
||||||
|
const bashCommand = `
|
||||||
|
echo "${logContent}" >> ${logPath};
|
||||||
|
cd ${projectPath} || exit 1;
|
||||||
|
docker ${command.split(" ").join(" ")} >> ${logPath} 2>&1;
|
||||||
|
echo "Docker Compose Deployed: ✅" >> ${logPath};
|
||||||
|
`;
|
||||||
|
return bashCommand;
|
||||||
|
};
|
||||||
|
|
||||||
const sanitizeCommand = (command: string) => {
|
const sanitizeCommand = (command: string) => {
|
||||||
const sanitizedCommand = command.trim();
|
const sanitizedCommand = command.trim();
|
||||||
|
|
||||||
|
|||||||
@@ -27,6 +27,13 @@ export const createComposeFile = async (compose: Compose, logPath: string) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const getCreateComposeFileCommand = (compose: Compose) => {
|
||||||
|
const { appName, composeFile } = compose;
|
||||||
|
const outputPath = join(COMPOSE_PATH, appName, "code");
|
||||||
|
const filePath = join(outputPath, "docker-compose.yml");
|
||||||
|
return `echo "${composeFile}" > ${filePath}`;
|
||||||
|
};
|
||||||
|
|
||||||
export const createComposeFileRaw = async (compose: Compose) => {
|
export const createComposeFileRaw = async (compose: Compose) => {
|
||||||
const { appName, composeFile } = compose;
|
const { appName, composeFile } = compose;
|
||||||
const outputPath = join(COMPOSE_PATH, appName, "code");
|
const outputPath = join(COMPOSE_PATH, appName, "code");
|
||||||
|
|||||||
Reference in New Issue
Block a user