mirror of
https://github.com/Dokploy/dokploy
synced 2025-06-26 18:27:59 +00:00
refactor(deployments): improve build error
This commit is contained in:
@@ -189,12 +189,14 @@ export const applicationRouter = createTRPCRouter({
|
|||||||
redeploy: protectedProcedure
|
redeploy: protectedProcedure
|
||||||
.input(apiFindOneApplication)
|
.input(apiFindOneApplication)
|
||||||
.mutation(async ({ input }) => {
|
.mutation(async ({ input }) => {
|
||||||
|
const application = await findApplicationById(input.applicationId);
|
||||||
const jobData: DeploymentJob = {
|
const jobData: DeploymentJob = {
|
||||||
applicationId: input.applicationId,
|
applicationId: input.applicationId,
|
||||||
titleLog: "Rebuild deployment",
|
titleLog: "Rebuild deployment",
|
||||||
descriptionLog: "",
|
descriptionLog: "",
|
||||||
type: "redeploy",
|
type: "redeploy",
|
||||||
applicationType: "application",
|
applicationType: "application",
|
||||||
|
server: !!application.serverId,
|
||||||
};
|
};
|
||||||
await myQueue.add(
|
await myQueue.add(
|
||||||
"deployments",
|
"deployments",
|
||||||
@@ -334,13 +336,14 @@ export const applicationRouter = createTRPCRouter({
|
|||||||
deploy: protectedProcedure
|
deploy: protectedProcedure
|
||||||
.input(apiFindOneApplication)
|
.input(apiFindOneApplication)
|
||||||
.mutation(async ({ input, ctx }) => {
|
.mutation(async ({ input, ctx }) => {
|
||||||
// const application = await findApplicationById(input.applicationId);
|
const application = await findApplicationById(input.applicationId);
|
||||||
const jobData: DeploymentJob = {
|
const jobData: DeploymentJob = {
|
||||||
applicationId: input.applicationId,
|
applicationId: input.applicationId,
|
||||||
titleLog: "Manual deployment",
|
titleLog: "Manual deployment",
|
||||||
descriptionLog: "",
|
descriptionLog: "",
|
||||||
type: "deploy",
|
type: "deploy",
|
||||||
applicationType: "application",
|
applicationType: "application",
|
||||||
|
server: !!application.serverId,
|
||||||
};
|
};
|
||||||
await myQueue.add(
|
await myQueue.add(
|
||||||
"deployments",
|
"deployments",
|
||||||
@@ -350,10 +353,6 @@ export const applicationRouter = createTRPCRouter({
|
|||||||
removeOnFail: true,
|
removeOnFail: true,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
// if (!application.serverId) {
|
|
||||||
// } else {
|
|
||||||
// await enqueueDeploymentJob(application.serverId, jobData);
|
|
||||||
// }
|
|
||||||
}),
|
}),
|
||||||
|
|
||||||
cleanQueues: protectedProcedure
|
cleanQueues: protectedProcedure
|
||||||
|
|||||||
@@ -169,14 +169,6 @@ 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: "",
|
|
||||||
// };
|
|
||||||
|
|
||||||
const compose = await findComposeById(input.composeId);
|
const compose = await findComposeById(input.composeId);
|
||||||
const jobData: DeploymentJob = {
|
const jobData: DeploymentJob = {
|
||||||
composeId: input.composeId,
|
composeId: input.composeId,
|
||||||
@@ -184,6 +176,7 @@ export const composeRouter = createTRPCRouter({
|
|||||||
type: "deploy",
|
type: "deploy",
|
||||||
applicationType: "compose",
|
applicationType: "compose",
|
||||||
descriptionLog: "",
|
descriptionLog: "",
|
||||||
|
server: !!compose.serverId,
|
||||||
};
|
};
|
||||||
await myQueue.add(
|
await myQueue.add(
|
||||||
"deployments",
|
"deployments",
|
||||||
@@ -193,10 +186,6 @@ export const composeRouter = createTRPCRouter({
|
|||||||
removeOnFail: true,
|
removeOnFail: true,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
// if (!compose.serverId) {
|
|
||||||
// } else {
|
|
||||||
// await enqueueDeploymentJob(compose.serverId, jobData);
|
|
||||||
// }
|
|
||||||
}),
|
}),
|
||||||
redeploy: protectedProcedure
|
redeploy: protectedProcedure
|
||||||
.input(apiFindCompose)
|
.input(apiFindCompose)
|
||||||
|
|||||||
@@ -260,10 +260,66 @@ export const rebuildApplication = async ({
|
|||||||
description: descriptionLog,
|
description: descriptionLog,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (application.sourceType === "github") {
|
||||||
|
await buildApplication(application, deployment.logPath);
|
||||||
|
} else if (application.sourceType === "gitlab") {
|
||||||
|
await buildApplication(application, deployment.logPath);
|
||||||
|
} else if (application.sourceType === "bitbucket") {
|
||||||
|
await buildApplication(application, deployment.logPath);
|
||||||
|
} else if (application.sourceType === "docker") {
|
||||||
|
await buildDocker(application, deployment.logPath);
|
||||||
|
} else if (application.sourceType === "git") {
|
||||||
|
await buildApplication(application, deployment.logPath);
|
||||||
|
} else if (application.sourceType === "drop") {
|
||||||
|
await buildApplication(application, deployment.logPath);
|
||||||
|
}
|
||||||
|
await updateDeploymentStatus(deployment.deploymentId, "done");
|
||||||
|
await updateApplicationStatus(applicationId, "done");
|
||||||
|
} catch (error) {
|
||||||
|
await updateDeploymentStatus(deployment.deploymentId, "error");
|
||||||
|
await updateApplicationStatus(applicationId, "error");
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const deployRemoteApplication = async ({
|
||||||
|
applicationId,
|
||||||
|
titleLog = "Manual deployment",
|
||||||
|
descriptionLog = "",
|
||||||
|
}: {
|
||||||
|
applicationId: string;
|
||||||
|
titleLog: string;
|
||||||
|
descriptionLog: string;
|
||||||
|
}) => {
|
||||||
|
const application = await findApplicationById(applicationId);
|
||||||
|
const buildLink = `${await getDokployUrl()}/dashboard/project/${application.projectId}/services/application/${application.applicationId}?tab=deployments`;
|
||||||
|
const deployment = await createDeployment({
|
||||||
|
applicationId: applicationId,
|
||||||
|
title: titleLog,
|
||||||
|
description: descriptionLog,
|
||||||
|
});
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (application.serverId) {
|
if (application.serverId) {
|
||||||
let command = "set -e;";
|
let command = "set -e;";
|
||||||
if (application.sourceType === "docker") {
|
if (application.sourceType === "github") {
|
||||||
|
command += await getGithubCloneCommand(application, deployment.logPath);
|
||||||
|
} else if (application.sourceType === "gitlab") {
|
||||||
|
command += await getGitlabCloneCommand(application, deployment.logPath);
|
||||||
|
} else if (application.sourceType === "bitbucket") {
|
||||||
|
command += await getBitbucketCloneCommand(
|
||||||
|
application,
|
||||||
|
deployment.logPath,
|
||||||
|
);
|
||||||
|
} else if (application.sourceType === "git") {
|
||||||
|
command += await getCustomGitCloneCommand(
|
||||||
|
application,
|
||||||
|
deployment.logPath,
|
||||||
|
);
|
||||||
|
} else if (application.sourceType === "docker") {
|
||||||
command += await buildRemoteDocker(application, deployment.logPath);
|
command += await buildRemoteDocker(application, deployment.logPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -272,20 +328,67 @@ export const rebuildApplication = async ({
|
|||||||
}
|
}
|
||||||
await execAsyncRemote(application.serverId, command);
|
await execAsyncRemote(application.serverId, command);
|
||||||
await mechanizeDockerContainer(application);
|
await mechanizeDockerContainer(application);
|
||||||
} else {
|
}
|
||||||
if (application.sourceType === "github") {
|
|
||||||
await buildApplication(application, deployment.logPath);
|
await updateDeploymentStatus(deployment.deploymentId, "done");
|
||||||
} else if (application.sourceType === "gitlab") {
|
await updateApplicationStatus(applicationId, "done");
|
||||||
await buildApplication(application, deployment.logPath);
|
|
||||||
} else if (application.sourceType === "bitbucket") {
|
await sendBuildSuccessNotifications({
|
||||||
await buildApplication(application, deployment.logPath);
|
projectName: application.project.name,
|
||||||
} else if (application.sourceType === "docker") {
|
applicationName: application.name,
|
||||||
await buildDocker(application, deployment.logPath);
|
applicationType: "application",
|
||||||
} else if (application.sourceType === "git") {
|
buildLink,
|
||||||
await buildApplication(application, deployment.logPath);
|
});
|
||||||
} else if (application.sourceType === "drop") {
|
} catch (error) {
|
||||||
await buildApplication(application, deployment.logPath);
|
await updateDeploymentStatus(deployment.deploymentId, "error");
|
||||||
|
await updateApplicationStatus(applicationId, "error");
|
||||||
|
await sendBuildErrorNotifications({
|
||||||
|
projectName: application.project.name,
|
||||||
|
applicationName: application.name,
|
||||||
|
applicationType: "application",
|
||||||
|
// @ts-ignore
|
||||||
|
errorMessage: error?.message || "Error to build",
|
||||||
|
buildLink,
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log(
|
||||||
|
"Error on ",
|
||||||
|
application.buildType,
|
||||||
|
"/",
|
||||||
|
application.sourceType,
|
||||||
|
error,
|
||||||
|
);
|
||||||
|
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const rebuildRemoteApplication = async ({
|
||||||
|
applicationId,
|
||||||
|
titleLog = "Rebuild deployment",
|
||||||
|
descriptionLog = "",
|
||||||
|
}: {
|
||||||
|
applicationId: string;
|
||||||
|
titleLog: string;
|
||||||
|
descriptionLog: string;
|
||||||
|
}) => {
|
||||||
|
const application = await findApplicationById(applicationId);
|
||||||
|
const deployment = await createDeployment({
|
||||||
|
applicationId: applicationId,
|
||||||
|
title: titleLog,
|
||||||
|
description: descriptionLog,
|
||||||
|
});
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (application.serverId) {
|
||||||
|
if (application.sourceType !== "docker") {
|
||||||
|
let command = "set -e;";
|
||||||
|
command += getBuildCommand(application, deployment.logPath);
|
||||||
|
await execAsyncRemote(application.serverId, command);
|
||||||
}
|
}
|
||||||
|
await mechanizeDockerContainer(application);
|
||||||
}
|
}
|
||||||
await updateDeploymentStatus(deployment.deploymentId, "done");
|
await updateDeploymentStatus(deployment.deploymentId, "done");
|
||||||
await updateApplicationStatus(applicationId, "done");
|
await updateApplicationStatus(applicationId, "done");
|
||||||
|
|||||||
@@ -210,64 +210,18 @@ export const deployCompose = async ({
|
|||||||
});
|
});
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (compose.serverId) {
|
if (compose.sourceType === "github") {
|
||||||
let command = `
|
await cloneGithubRepository(compose, deployment.logPath, true);
|
||||||
set -e;
|
} else if (compose.sourceType === "gitlab") {
|
||||||
`;
|
await cloneGitlabRepository(compose, deployment.logPath, true);
|
||||||
if (compose.sourceType === "github") {
|
} else if (compose.sourceType === "bitbucket") {
|
||||||
command += await getGithubCloneCommand(
|
await cloneBitbucketRepository(compose, deployment.logPath, true);
|
||||||
compose,
|
} else if (compose.sourceType === "git") {
|
||||||
deployment.logPath,
|
await cloneGitRepository(compose, deployment.logPath, true);
|
||||||
true,
|
} else if (compose.sourceType === "raw") {
|
||||||
);
|
await createComposeFile(compose, deployment.logPath);
|
||||||
} 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);
|
|
||||||
}
|
|
||||||
async function* sequentialSteps() {
|
|
||||||
yield execAsyncRemote(compose.serverId, command);
|
|
||||||
yield getBuildComposeCommand(compose, deployment.logPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
const steps = sequentialSteps();
|
|
||||||
for await (const step of steps) {
|
|
||||||
step;
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log(" ---- done ----");
|
|
||||||
} else {
|
|
||||||
if (compose.sourceType === "github") {
|
|
||||||
await cloneGithubRepository(compose, deployment.logPath, true);
|
|
||||||
} else if (compose.sourceType === "gitlab") {
|
|
||||||
await cloneGitlabRepository(compose, deployment.logPath, true);
|
|
||||||
} else if (compose.sourceType === "bitbucket") {
|
|
||||||
await cloneBitbucketRepository(compose, deployment.logPath, true);
|
|
||||||
} else if (compose.sourceType === "git") {
|
|
||||||
await cloneGitRepository(compose, deployment.logPath, true);
|
|
||||||
} else if (compose.sourceType === "raw") {
|
|
||||||
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",
|
||||||
@@ -334,6 +288,132 @@ export const rebuildCompose = async ({
|
|||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const deployRemoteCompose = async ({
|
||||||
|
composeId,
|
||||||
|
titleLog = "Manual deployment",
|
||||||
|
descriptionLog = "",
|
||||||
|
}: {
|
||||||
|
composeId: string;
|
||||||
|
titleLog: string;
|
||||||
|
descriptionLog: string;
|
||||||
|
}) => {
|
||||||
|
const compose = await findComposeById(composeId);
|
||||||
|
const buildLink = `${await getDokployUrl()}/dashboard/project/${compose.projectId}/services/compose/${compose.composeId}?tab=deployments`;
|
||||||
|
const deployment = await createDeploymentCompose({
|
||||||
|
composeId: composeId,
|
||||||
|
title: titleLog,
|
||||||
|
description: descriptionLog,
|
||||||
|
});
|
||||||
|
|
||||||
|
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, deployment.logPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function* sequentialSteps() {
|
||||||
|
yield execAsyncRemote(compose.serverId, command);
|
||||||
|
yield getBuildComposeCommand(compose, deployment.logPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
const steps = sequentialSteps();
|
||||||
|
for await (const step of steps) {
|
||||||
|
step;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(" ---- done ----");
|
||||||
|
}
|
||||||
|
|
||||||
|
await updateDeploymentStatus(deployment.deploymentId, "done");
|
||||||
|
await updateCompose(composeId, {
|
||||||
|
composeStatus: "done",
|
||||||
|
});
|
||||||
|
|
||||||
|
await sendBuildSuccessNotifications({
|
||||||
|
projectName: compose.project.name,
|
||||||
|
applicationName: compose.name,
|
||||||
|
applicationType: "compose",
|
||||||
|
buildLink,
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
await updateDeploymentStatus(deployment.deploymentId, "error");
|
||||||
|
await updateCompose(composeId, {
|
||||||
|
composeStatus: "error",
|
||||||
|
});
|
||||||
|
await sendBuildErrorNotifications({
|
||||||
|
projectName: compose.project.name,
|
||||||
|
applicationName: compose.name,
|
||||||
|
applicationType: "compose",
|
||||||
|
// @ts-ignore
|
||||||
|
errorMessage: error?.message || "Error to build",
|
||||||
|
buildLink,
|
||||||
|
});
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const rebuildRemoteCompose = async ({
|
||||||
|
composeId,
|
||||||
|
titleLog = "Rebuild deployment",
|
||||||
|
descriptionLog = "",
|
||||||
|
}: {
|
||||||
|
composeId: string;
|
||||||
|
titleLog: string;
|
||||||
|
descriptionLog: string;
|
||||||
|
}) => {
|
||||||
|
const compose = await findComposeById(composeId);
|
||||||
|
const deployment = await createDeploymentCompose({
|
||||||
|
composeId: composeId,
|
||||||
|
title: titleLog,
|
||||||
|
description: descriptionLog,
|
||||||
|
});
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (compose.serverId) {
|
||||||
|
await getBuildComposeCommand(compose, deployment.logPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
await updateDeploymentStatus(deployment.deploymentId, "done");
|
||||||
|
await updateCompose(composeId, {
|
||||||
|
composeStatus: "done",
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
await updateDeploymentStatus(deployment.deploymentId, "error");
|
||||||
|
await updateCompose(composeId, {
|
||||||
|
composeStatus: "error",
|
||||||
|
});
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
export const removeCompose = async (compose: Compose) => {
|
export const removeCompose = async (compose: Compose) => {
|
||||||
try {
|
try {
|
||||||
const projectPath = join(COMPOSE_PATH, compose.appName);
|
const projectPath = join(COMPOSE_PATH, compose.appName);
|
||||||
|
|||||||
@@ -1,12 +1,16 @@
|
|||||||
import { type Job, Worker } from "bullmq";
|
import { type Job, Worker } from "bullmq";
|
||||||
import {
|
import {
|
||||||
deployApplication,
|
deployApplication,
|
||||||
|
deployRemoteApplication,
|
||||||
rebuildApplication,
|
rebuildApplication,
|
||||||
|
rebuildRemoteApplication,
|
||||||
updateApplicationStatus,
|
updateApplicationStatus,
|
||||||
} from "../api/services/application";
|
} from "../api/services/application";
|
||||||
import {
|
import {
|
||||||
deployCompose,
|
deployCompose,
|
||||||
|
deployRemoteCompose,
|
||||||
rebuildCompose,
|
rebuildCompose,
|
||||||
|
rebuildRemoteCompose,
|
||||||
updateCompose,
|
updateCompose,
|
||||||
} from "../api/services/compose";
|
} from "../api/services/compose";
|
||||||
import { myQueue, redisConfig } from "./queueSetup";
|
import { myQueue, redisConfig } from "./queueSetup";
|
||||||
@@ -16,6 +20,7 @@ type DeployJob =
|
|||||||
applicationId: string;
|
applicationId: string;
|
||||||
titleLog: string;
|
titleLog: string;
|
||||||
descriptionLog: string;
|
descriptionLog: string;
|
||||||
|
server?: boolean;
|
||||||
type: "deploy" | "redeploy";
|
type: "deploy" | "redeploy";
|
||||||
applicationType: "application";
|
applicationType: "application";
|
||||||
}
|
}
|
||||||
@@ -23,6 +28,7 @@ type DeployJob =
|
|||||||
composeId: string;
|
composeId: string;
|
||||||
titleLog: string;
|
titleLog: string;
|
||||||
descriptionLog: string;
|
descriptionLog: string;
|
||||||
|
server?: boolean;
|
||||||
type: "deploy" | "redeploy";
|
type: "deploy" | "redeploy";
|
||||||
applicationType: "compose";
|
applicationType: "compose";
|
||||||
};
|
};
|
||||||
@@ -35,35 +41,68 @@ export const deploymentWorker = new Worker(
|
|||||||
try {
|
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 === "redeploy") {
|
if (job.data.server) {
|
||||||
await rebuildApplication({
|
if (job.data.type === "redeploy") {
|
||||||
applicationId: job.data.applicationId,
|
await rebuildRemoteApplication({
|
||||||
titleLog: job.data.titleLog,
|
applicationId: job.data.applicationId,
|
||||||
descriptionLog: job.data.descriptionLog,
|
titleLog: job.data.titleLog,
|
||||||
});
|
descriptionLog: job.data.descriptionLog,
|
||||||
} else if (job.data.type === "deploy") {
|
});
|
||||||
await deployApplication({
|
} else if (job.data.type === "deploy") {
|
||||||
applicationId: job.data.applicationId,
|
await deployRemoteApplication({
|
||||||
titleLog: job.data.titleLog,
|
applicationId: job.data.applicationId,
|
||||||
descriptionLog: job.data.descriptionLog,
|
titleLog: job.data.titleLog,
|
||||||
});
|
descriptionLog: job.data.descriptionLog,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
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({
|
||||||
|
applicationId: job.data.applicationId,
|
||||||
|
titleLog: job.data.titleLog,
|
||||||
|
descriptionLog: job.data.descriptionLog,
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if (job.data.applicationType === "compose") {
|
} else if (job.data.applicationType === "compose") {
|
||||||
await updateCompose(job.data.composeId, {
|
await updateCompose(job.data.composeId, {
|
||||||
composeStatus: "running",
|
composeStatus: "running",
|
||||||
});
|
});
|
||||||
if (job.data.type === "deploy") {
|
|
||||||
await deployCompose({
|
if (job.data.server) {
|
||||||
composeId: job.data.composeId,
|
if (job.data.type === "redeploy") {
|
||||||
titleLog: job.data.titleLog,
|
await rebuildRemoteCompose({
|
||||||
descriptionLog: job.data.descriptionLog,
|
composeId: job.data.composeId,
|
||||||
});
|
titleLog: job.data.titleLog,
|
||||||
} else if (job.data.type === "redeploy") {
|
descriptionLog: job.data.descriptionLog,
|
||||||
await rebuildCompose({
|
});
|
||||||
composeId: job.data.composeId,
|
} else if (job.data.type === "deploy") {
|
||||||
titleLog: job.data.titleLog,
|
await deployRemoteCompose({
|
||||||
descriptionLog: job.data.descriptionLog,
|
composeId: job.data.composeId,
|
||||||
});
|
titleLog: job.data.titleLog,
|
||||||
|
descriptionLog: job.data.descriptionLog,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
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) {
|
} catch (error) {
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import { COMPOSE_PATH } from "@/server/constants";
|
|||||||
import type { InferResultType } from "@/server/types/with";
|
import type { InferResultType } from "@/server/types/with";
|
||||||
import boxen from "boxen";
|
import boxen from "boxen";
|
||||||
import {
|
import {
|
||||||
|
getComposePath,
|
||||||
writeDomainsToCompose,
|
writeDomainsToCompose,
|
||||||
writeDomainsToComposeRemote,
|
writeDomainsToComposeRemote,
|
||||||
} from "../docker/domain";
|
} from "../docker/domain";
|
||||||
@@ -73,12 +74,17 @@ export const getBuildComposeCommand = async (
|
|||||||
compose: ComposeNested,
|
compose: ComposeNested,
|
||||||
logPath: string,
|
logPath: string,
|
||||||
) => {
|
) => {
|
||||||
const { sourceType, appName, mounts, composeType, domains } = compose;
|
const { sourceType, appName, mounts, composeType, domains, composePath } =
|
||||||
|
compose;
|
||||||
const command = createCommand(compose);
|
const command = createCommand(compose);
|
||||||
const envCommand = getCreateEnvFileCommand(compose);
|
const envCommand = getCreateEnvFileCommand(compose);
|
||||||
const projectPath = join(COMPOSE_PATH, compose.appName, "code");
|
const projectPath = join(COMPOSE_PATH, compose.appName, "code");
|
||||||
|
|
||||||
const newCompose = await writeDomainsToComposeRemote(compose, domains);
|
const newCompose = await writeDomainsToComposeRemote(
|
||||||
|
compose,
|
||||||
|
domains,
|
||||||
|
logPath,
|
||||||
|
);
|
||||||
const logContent = `
|
const logContent = `
|
||||||
App Name: ${appName}
|
App Name: ${appName}
|
||||||
Build Compose 🐳
|
Build Compose 🐳
|
||||||
@@ -107,6 +113,11 @@ Compose Type: ${composeType} ✅`;
|
|||||||
${envCommand}
|
${envCommand}
|
||||||
|
|
||||||
cd "${projectPath}";
|
cd "${projectPath}";
|
||||||
|
|
||||||
|
if [ ! -f "${composePath}" ]; then
|
||||||
|
echo "❌ Error: Compose file not found" >> "${logPath}";
|
||||||
|
exit 1;
|
||||||
|
fi
|
||||||
|
|
||||||
docker ${command.split(" ").join(" ")} >> "${logPath}" 2>&1 || { echo "Error: ❌ Docker command failed" >> "${logPath}"; exit 1; }
|
docker ${command.split(" ").join(" ")} >> "${logPath}" 2>&1 || { echo "Error: ❌ Docker command failed" >> "${logPath}"; exit 1; }
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import {
|
|||||||
getDockerContextPath,
|
getDockerContextPath,
|
||||||
} from "../filesystem/directory";
|
} from "../filesystem/directory";
|
||||||
import { spawnAsync } from "../process/spawnAsync";
|
import { spawnAsync } from "../process/spawnAsync";
|
||||||
import { createEnvFile } from "./utils";
|
import { createEnvFile, createEnvFileCommand } from "./utils";
|
||||||
|
|
||||||
export const buildCustomDocker = async (
|
export const buildCustomDocker = async (
|
||||||
application: ApplicationNested,
|
application: ApplicationNested,
|
||||||
@@ -86,11 +86,27 @@ export const getDockerCommand = (
|
|||||||
commandArgs.push("--build-arg", arg);
|
commandArgs.push("--build-arg", arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
const command = `
|
/*
|
||||||
|
Do not generate an environment file when publishDirectory is specified,
|
||||||
|
as it could be publicly exposed.
|
||||||
|
*/
|
||||||
|
let command = "";
|
||||||
|
if (!publishDirectory) {
|
||||||
|
command += createEnvFileCommand(dockerFilePath, env);
|
||||||
|
}
|
||||||
|
|
||||||
|
command = `
|
||||||
echo "Building ${appName}" >> ${logPath};
|
echo "Building ${appName}" >> ${logPath};
|
||||||
cd ${dockerContextPath} || exit 1;
|
cd ${dockerContextPath} >> ${logPath} 2>> ${logPath} || {
|
||||||
docker ${commandArgs.join(" ")} >> ${logPath} 2>&1;
|
echo "❌ The path ${dockerContextPath} does not exist" >> ${logPath};
|
||||||
echo "Docker build completed." >> ${logPath};
|
exit 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
docker ${commandArgs.join(" ")} >> ${logPath} 2>> ${logPath} || {
|
||||||
|
echo "❌ Docker build failed" >> ${logPath};
|
||||||
|
exit 1;
|
||||||
|
}
|
||||||
|
echo "✅ Docker build completed." >> ${logPath};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
return command;
|
return command;
|
||||||
|
|||||||
@@ -62,8 +62,11 @@ export const getHerokuCommand = (
|
|||||||
const command = `pack ${args.join(" ")}`;
|
const command = `pack ${args.join(" ")}`;
|
||||||
const bashCommand = `
|
const bashCommand = `
|
||||||
echo "Starting heroku build..." >> ${logPath};
|
echo "Starting heroku build..." >> ${logPath};
|
||||||
${command} >> ${logPath} 2>&1;
|
${command} >> ${logPath} 2>> ${logPath} || {
|
||||||
echo "Heroku build completed." >> ${logPath};
|
echo "❌ Heroku build failed" >> ${logPath};
|
||||||
|
exit 1;
|
||||||
|
}
|
||||||
|
echo "✅ Heroku build completed." >> ${logPath};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
return bashCommand;
|
return bashCommand;
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ import { buildCustomDocker, getDockerCommand } from "./docker-file";
|
|||||||
import { buildHeroku, getHerokuCommand } from "./heroku";
|
import { buildHeroku, getHerokuCommand } from "./heroku";
|
||||||
import { buildNixpacks, getNixpacksCommand } from "./nixpacks";
|
import { buildNixpacks, getNixpacksCommand } from "./nixpacks";
|
||||||
import { buildPaketo, getPaketoCommand } from "./paketo";
|
import { buildPaketo, getPaketoCommand } from "./paketo";
|
||||||
import { buildStatic } from "./static";
|
import { buildStatic, getStaticCommand } from "./static";
|
||||||
import { findServerById } from "@/server/api/services/server";
|
import { findServerById } from "@/server/api/services/server";
|
||||||
import { readSSHKey } from "../filesystem/ssh";
|
import { readSSHKey } from "../filesystem/ssh";
|
||||||
import { getRemoteDocker } from "../servers/remote-docker";
|
import { getRemoteDocker } from "../servers/remote-docker";
|
||||||
@@ -81,8 +81,8 @@ export const getBuildCommand = (
|
|||||||
return getHerokuCommand(application, logPath);
|
return getHerokuCommand(application, logPath);
|
||||||
case "paketo_buildpacks":
|
case "paketo_buildpacks":
|
||||||
return getPaketoCommand(application, logPath);
|
return getPaketoCommand(application, logPath);
|
||||||
// case "static":
|
case "static":
|
||||||
// return buildStatic(application, writeStream);
|
return getStaticCommand(application, logPath);
|
||||||
case "dockerfile":
|
case "dockerfile":
|
||||||
return getDockerCommand(application, logPath);
|
return getDockerCommand(application, logPath);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,11 @@
|
|||||||
import type { WriteStream } from "node:fs";
|
import type { WriteStream } from "node:fs";
|
||||||
import path from "node:path";
|
import path from "node:path";
|
||||||
import { buildStatic } from "@/server/utils/builders/static";
|
import { buildStatic, getStaticCommand } from "@/server/utils/builders/static";
|
||||||
import { nanoid } from "nanoid";
|
import { nanoid } from "nanoid";
|
||||||
import type { ApplicationNested } from ".";
|
import type { ApplicationNested } from ".";
|
||||||
import { prepareEnvironmentVariables } from "../docker/utils";
|
import { prepareEnvironmentVariables } from "../docker/utils";
|
||||||
import { getBuildAppDirectory } from "../filesystem/directory";
|
import { getBuildAppDirectory } from "../filesystem/directory";
|
||||||
import { spawnAsync } from "../process/spawnAsync";
|
import { spawnAsync } from "../process/spawnAsync";
|
||||||
import { executeCommand } from "../servers/command";
|
|
||||||
|
|
||||||
export const buildNixpacks = async (
|
export const buildNixpacks = async (
|
||||||
application: ApplicationNested,
|
application: ApplicationNested,
|
||||||
@@ -83,47 +82,44 @@ export const getNixpacksCommand = (
|
|||||||
const buildContainerId = `${appName}-${nanoid(10)}`;
|
const buildContainerId = `${appName}-${nanoid(10)}`;
|
||||||
const envVariables = prepareEnvironmentVariables(env);
|
const envVariables = prepareEnvironmentVariables(env);
|
||||||
|
|
||||||
try {
|
const args = ["build", buildAppDirectory, "--name", appName];
|
||||||
const args = ["build", buildAppDirectory, "--name", appName];
|
|
||||||
|
|
||||||
for (const env of envVariables) {
|
for (const env of envVariables) {
|
||||||
args.push("--env", env);
|
args.push("--env", env);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (publishDirectory) {
|
if (publishDirectory) {
|
||||||
/* No need for any start command, since we'll use nginx later on */
|
/* No need for any start command, since we'll use nginx later on */
|
||||||
args.push("--no-error-without-start");
|
args.push("--no-error-without-start");
|
||||||
}
|
}
|
||||||
console.log("args", args);
|
console.log("args", args);
|
||||||
const command = `nixpacks ${args.join(" ")}`;
|
const command = `nixpacks ${args.join(" ")}`;
|
||||||
const bashCommand = `
|
let bashCommand = `
|
||||||
echo "Starting nixpacks build..." >> ${logPath};
|
echo "Starting nixpacks build..." >> ${logPath};
|
||||||
${command} >> ${logPath} 2>&1;
|
${command} >> ${logPath} 2>> ${logPath} || {
|
||||||
echo "Nixpacks build completed." >> ${logPath};
|
echo "❌ Nixpacks build failed" >> ${logPath};
|
||||||
|
exit 1;
|
||||||
|
}
|
||||||
|
echo "✅ Nixpacks build completed." >> ${logPath};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Run the container with the image created by nixpacks,
|
Run the container with the image created by nixpacks,
|
||||||
and copy the artifacts on the host filesystem.
|
and copy the artifacts on the host filesystem.
|
||||||
Then, remove the container and create a static build.
|
Then, remove the container and create a static build.
|
||||||
*/
|
*/
|
||||||
|
if (publishDirectory) {
|
||||||
if (publishDirectory) {
|
bashCommand += `
|
||||||
}
|
docker create --name ${buildContainerId} ${appName}
|
||||||
|
docker cp ${buildContainerId}:/app/${publishDirectory} ${path.join(buildAppDirectory, publishDirectory)} >> ${logPath} 2>> ${logPath} || {
|
||||||
// if (publishDirectory) {
|
docker rm ${buildContainerId}
|
||||||
// bashCommand += `
|
echo "❌ Copying ${publishDirectory} to ${path.join(buildAppDirectory, publishDirectory)} failed" >> ${logPath};
|
||||||
// docker create --name ${buildContainerId} ${appName}
|
exit 1;
|
||||||
// docker cp ${buildContainerId}:/app/${publishDirectory} ${path.join(buildAppDirectory, publishDirectory)}
|
}
|
||||||
// docker rm ${buildContainerId}
|
docker rm ${buildContainerId}
|
||||||
// buildStatic ${application} ${writeStream}
|
${getStaticCommand(application, logPath)}
|
||||||
// `;
|
`;
|
||||||
// }
|
|
||||||
|
|
||||||
return bashCommand;
|
|
||||||
} catch (e) {
|
|
||||||
// await spawnAsync("docker", ["rm", buildContainerId], writeToStream);
|
|
||||||
|
|
||||||
throw e;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return bashCommand;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -61,8 +61,11 @@ export const getPaketoCommand = (
|
|||||||
const command = `pack ${args.join(" ")}`;
|
const command = `pack ${args.join(" ")}`;
|
||||||
const bashCommand = `
|
const bashCommand = `
|
||||||
echo "Starting Paketo build..." >> ${logPath};
|
echo "Starting Paketo build..." >> ${logPath};
|
||||||
${command} >> ${logPath} 2>&1;
|
${command} >> ${logPath} 2>> ${logPath} || {
|
||||||
echo "Paketo build completed." >> ${logPath};
|
echo "❌ Paketo build failed" >> ${logPath};
|
||||||
|
exit 1;
|
||||||
|
}
|
||||||
|
echo "✅ Paketo build completed." >> ${logPath};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
return bashCommand;
|
return bashCommand;
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
import type { WriteStream } from "node:fs";
|
import type { WriteStream } from "node:fs";
|
||||||
import { buildCustomDocker } from "@/server/utils/builders/docker-file";
|
import {
|
||||||
|
buildCustomDocker,
|
||||||
|
getDockerCommand,
|
||||||
|
} from "@/server/utils/builders/docker-file";
|
||||||
import type { ApplicationNested } from ".";
|
import type { ApplicationNested } from ".";
|
||||||
import { createFile } from "../docker/utils";
|
import { createFile, getCreateFileCommand } from "../docker/utils";
|
||||||
import { getBuildAppDirectory } from "../filesystem/directory";
|
import { getBuildAppDirectory } from "../filesystem/directory";
|
||||||
|
|
||||||
export const buildStatic = async (
|
export const buildStatic = async (
|
||||||
@@ -36,3 +39,31 @@ export const buildStatic = async (
|
|||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const getStaticCommand = (
|
||||||
|
application: ApplicationNested,
|
||||||
|
logPath: string,
|
||||||
|
) => {
|
||||||
|
const { publishDirectory } = application;
|
||||||
|
const buildAppDirectory = getBuildAppDirectory(application);
|
||||||
|
|
||||||
|
let command = getCreateFileCommand(
|
||||||
|
buildAppDirectory,
|
||||||
|
"Dockerfile",
|
||||||
|
[
|
||||||
|
"FROM nginx:alpine",
|
||||||
|
"WORKDIR /usr/share/nginx/html/",
|
||||||
|
`COPY ${publishDirectory || "."} .`,
|
||||||
|
].join("\n"),
|
||||||
|
);
|
||||||
|
|
||||||
|
command += getDockerCommand(
|
||||||
|
{
|
||||||
|
...application,
|
||||||
|
buildType: "dockerfile",
|
||||||
|
dockerfile: "Dockerfile",
|
||||||
|
},
|
||||||
|
logPath,
|
||||||
|
);
|
||||||
|
return command;
|
||||||
|
};
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ export const createEnvFile = (directory: string, env: string | null) => {
|
|||||||
|
|
||||||
export const createEnvFileCommand = (directory: string, env: string | null) => {
|
export const createEnvFileCommand = (directory: string, env: string | null) => {
|
||||||
const envFilePath = join(dirname(directory), ".env");
|
const envFilePath = join(dirname(directory), ".env");
|
||||||
// let command = ``
|
|
||||||
if (!existsSync(dirname(envFilePath))) {
|
if (!existsSync(dirname(envFilePath))) {
|
||||||
mkdirSync(dirname(envFilePath), { recursive: true });
|
mkdirSync(dirname(envFilePath), { recursive: true });
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -96,7 +96,14 @@ export const loadDockerComposeRemote = async (
|
|||||||
if (!compose.serverId) {
|
if (!compose.serverId) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
const { stdout } = await execAsyncRemote(compose.serverId, `cat ${path}`);
|
const { stdout, stderr } = await execAsyncRemote(
|
||||||
|
compose.serverId,
|
||||||
|
`cat ${path}`,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (stderr) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
if (!stdout) return null;
|
if (!stdout) return null;
|
||||||
const parsedConfig = load(stdout) as ComposeSpecification;
|
const parsedConfig = load(stdout) as ComposeSpecification;
|
||||||
return parsedConfig;
|
return parsedConfig;
|
||||||
@@ -135,21 +142,25 @@ export const writeDomainsToCompose = async (
|
|||||||
export const writeDomainsToComposeRemote = async (
|
export const writeDomainsToComposeRemote = async (
|
||||||
compose: Compose,
|
compose: Compose,
|
||||||
domains: Domain[],
|
domains: Domain[],
|
||||||
|
logPath: string,
|
||||||
) => {
|
) => {
|
||||||
if (!domains.length) {
|
if (!domains.length) {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
const composeConverted = await addDomainToCompose(compose, domains);
|
|
||||||
const path = getComposePath(compose);
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
const composeConverted = await addDomainToCompose(compose, domains);
|
||||||
|
const path = getComposePath(compose);
|
||||||
if (compose.serverId) {
|
if (compose.serverId) {
|
||||||
const composeString = dump(composeConverted, { lineWidth: 1000 });
|
const composeString = dump(composeConverted, { lineWidth: 1000 });
|
||||||
const encodedContent = encodeBase64(composeString);
|
const encodedContent = encodeBase64(composeString);
|
||||||
return `echo "${encodedContent}" | base64 -d > "${path}";`;
|
return `echo "${encodedContent}" | base64 -d > "${path}";`;
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw error;
|
return `
|
||||||
|
echo "❌ Has occured an error: ${error?.message || error}" >> ${logPath};
|
||||||
|
exit 1;
|
||||||
|
`;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
// (node:59875) MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 11 SIGTERM listeners added to [process]. Use emitter.setMaxListeners() to increase limit
|
// (node:59875) MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 11 SIGTERM listeners added to [process]. Use emitter.setMaxListeners() to increase limit
|
||||||
|
|||||||
@@ -59,24 +59,26 @@ export const buildRemoteDocker = async (
|
|||||||
throw new Error("Docker image not found");
|
throw new Error("Docker image not found");
|
||||||
}
|
}
|
||||||
let command = `
|
let command = `
|
||||||
echo "Building ${sourceType}" >> ${logPath};
|
|
||||||
echo "Pulling ${dockerImage}" >> ${logPath};
|
echo "Pulling ${dockerImage}" >> ${logPath};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
if (username && password) {
|
if (username && password) {
|
||||||
command += `
|
command += `
|
||||||
if ! docker login --username ${username} --password ${password} https://index.docker.io/v1/ >> ${logPath} 2>&1; then
|
if ! docker login --username ${username} --password ${password} https://index.docker.io/v1/ >> ${logPath} 2>&1; then
|
||||||
echo "Error logging in to Docker Hub" >> ${logPath};
|
echo "❌ Login failed" >> ${logPath};
|
||||||
exit 1;
|
exit 1;
|
||||||
fi
|
fi
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
command += `
|
command += `
|
||||||
echo "Pulling ${dockerImage}" >> ${logPath};
|
docker pull ${dockerImage} >> ${logPath} 2>> ${logPath} || {
|
||||||
docker pull ${dockerImage} >> ${logPath} 2>&1;
|
echo "❌ Pulling image failed" >> ${logPath};
|
||||||
`;
|
exit 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
echo "✅ Pulling image completed." >> ${logPath};
|
||||||
|
`;
|
||||||
return command;
|
return command;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw error;
|
throw error;
|
||||||
|
|||||||
@@ -29,7 +29,10 @@ export const createComposeFile = async (compose: Compose, logPath: string) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getCreateComposeFileCommand = (compose: Compose) => {
|
export const getCreateComposeFileCommand = (
|
||||||
|
compose: Compose,
|
||||||
|
logPath: string,
|
||||||
|
) => {
|
||||||
const { appName, composeFile } = compose;
|
const { appName, composeFile } = compose;
|
||||||
const outputPath = join(COMPOSE_PATH, appName, "code");
|
const outputPath = join(COMPOSE_PATH, appName, "code");
|
||||||
const filePath = join(outputPath, "docker-compose.yml");
|
const filePath = join(outputPath, "docker-compose.yml");
|
||||||
@@ -38,6 +41,7 @@ export const getCreateComposeFileCommand = (compose: Compose) => {
|
|||||||
rm -rf ${outputPath};
|
rm -rf ${outputPath};
|
||||||
mkdir -p ${outputPath};
|
mkdir -p ${outputPath};
|
||||||
echo "${encodedContent}" | base64 -d > "${filePath}";
|
echo "${encodedContent}" | base64 -d > "${filePath}";
|
||||||
|
echo "File 'docker-compose.yml' created: ✅" >> ${logPath};
|
||||||
`;
|
`;
|
||||||
return bashCommand;
|
return bashCommand;
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user