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:
parent
d2c8632c4f
commit
0d3c978aad
@ -189,12 +189,14 @@ export const applicationRouter = createTRPCRouter({
|
||||
redeploy: protectedProcedure
|
||||
.input(apiFindOneApplication)
|
||||
.mutation(async ({ input }) => {
|
||||
const application = await findApplicationById(input.applicationId);
|
||||
const jobData: DeploymentJob = {
|
||||
applicationId: input.applicationId,
|
||||
titleLog: "Rebuild deployment",
|
||||
descriptionLog: "",
|
||||
type: "redeploy",
|
||||
applicationType: "application",
|
||||
server: !!application.serverId,
|
||||
};
|
||||
await myQueue.add(
|
||||
"deployments",
|
||||
@ -334,13 +336,14 @@ export const applicationRouter = createTRPCRouter({
|
||||
deploy: protectedProcedure
|
||||
.input(apiFindOneApplication)
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
// const application = await findApplicationById(input.applicationId);
|
||||
const application = await findApplicationById(input.applicationId);
|
||||
const jobData: DeploymentJob = {
|
||||
applicationId: input.applicationId,
|
||||
titleLog: "Manual deployment",
|
||||
descriptionLog: "",
|
||||
type: "deploy",
|
||||
applicationType: "application",
|
||||
server: !!application.serverId,
|
||||
};
|
||||
await myQueue.add(
|
||||
"deployments",
|
||||
@ -350,10 +353,6 @@ export const applicationRouter = createTRPCRouter({
|
||||
removeOnFail: true,
|
||||
},
|
||||
);
|
||||
// if (!application.serverId) {
|
||||
// } else {
|
||||
// await enqueueDeploymentJob(application.serverId, jobData);
|
||||
// }
|
||||
}),
|
||||
|
||||
cleanQueues: protectedProcedure
|
||||
|
@ -169,14 +169,6 @@ export const composeRouter = createTRPCRouter({
|
||||
deploy: protectedProcedure
|
||||
.input(apiFindCompose)
|
||||
.mutation(async ({ input }) => {
|
||||
// const jobData: DeploymentJob = {
|
||||
// composeId: input.composeId,
|
||||
// titleLog: "Manual deployment",
|
||||
// type: "deploy",
|
||||
// applicationType: "compose",
|
||||
// descriptionLog: "",
|
||||
// };
|
||||
|
||||
const compose = await findComposeById(input.composeId);
|
||||
const jobData: DeploymentJob = {
|
||||
composeId: input.composeId,
|
||||
@ -184,6 +176,7 @@ export const composeRouter = createTRPCRouter({
|
||||
type: "deploy",
|
||||
applicationType: "compose",
|
||||
descriptionLog: "",
|
||||
server: !!compose.serverId,
|
||||
};
|
||||
await myQueue.add(
|
||||
"deployments",
|
||||
@ -193,10 +186,6 @@ export const composeRouter = createTRPCRouter({
|
||||
removeOnFail: true,
|
||||
},
|
||||
);
|
||||
// if (!compose.serverId) {
|
||||
// } else {
|
||||
// await enqueueDeploymentJob(compose.serverId, jobData);
|
||||
// }
|
||||
}),
|
||||
redeploy: protectedProcedure
|
||||
.input(apiFindCompose)
|
||||
|
@ -260,10 +260,66 @@ export const rebuildApplication = async ({
|
||||
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 {
|
||||
if (application.serverId) {
|
||||
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);
|
||||
}
|
||||
|
||||
@ -272,20 +328,67 @@ export const rebuildApplication = async ({
|
||||
}
|
||||
await execAsyncRemote(application.serverId, command);
|
||||
await mechanizeDockerContainer(application);
|
||||
} else {
|
||||
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");
|
||||
|
||||
await sendBuildSuccessNotifications({
|
||||
projectName: application.project.name,
|
||||
applicationName: application.name,
|
||||
applicationType: "application",
|
||||
buildLink,
|
||||
});
|
||||
} catch (error) {
|
||||
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 updateApplicationStatus(applicationId, "done");
|
||||
|
@ -210,64 +210,18 @@ export const deployCompose = async ({
|
||||
});
|
||||
|
||||
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);
|
||||
}
|
||||
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);
|
||||
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 updateDeploymentStatus(deployment.deploymentId, "done");
|
||||
await updateCompose(composeId, {
|
||||
composeStatus: "done",
|
||||
@ -334,6 +288,132 @@ export const rebuildCompose = async ({
|
||||
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) => {
|
||||
try {
|
||||
const projectPath = join(COMPOSE_PATH, compose.appName);
|
||||
|
@ -1,12 +1,16 @@
|
||||
import { type Job, Worker } from "bullmq";
|
||||
import {
|
||||
deployApplication,
|
||||
deployRemoteApplication,
|
||||
rebuildApplication,
|
||||
rebuildRemoteApplication,
|
||||
updateApplicationStatus,
|
||||
} from "../api/services/application";
|
||||
import {
|
||||
deployCompose,
|
||||
deployRemoteCompose,
|
||||
rebuildCompose,
|
||||
rebuildRemoteCompose,
|
||||
updateCompose,
|
||||
} from "../api/services/compose";
|
||||
import { myQueue, redisConfig } from "./queueSetup";
|
||||
@ -16,6 +20,7 @@ type DeployJob =
|
||||
applicationId: string;
|
||||
titleLog: string;
|
||||
descriptionLog: string;
|
||||
server?: boolean;
|
||||
type: "deploy" | "redeploy";
|
||||
applicationType: "application";
|
||||
}
|
||||
@ -23,6 +28,7 @@ type DeployJob =
|
||||
composeId: string;
|
||||
titleLog: string;
|
||||
descriptionLog: string;
|
||||
server?: boolean;
|
||||
type: "deploy" | "redeploy";
|
||||
applicationType: "compose";
|
||||
};
|
||||
@ -35,35 +41,68 @@ export const deploymentWorker = new Worker(
|
||||
try {
|
||||
if (job.data.applicationType === "application") {
|
||||
await updateApplicationStatus(job.data.applicationId, "running");
|
||||
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,
|
||||
});
|
||||
if (job.data.server) {
|
||||
if (job.data.type === "redeploy") {
|
||||
await rebuildRemoteApplication({
|
||||
applicationId: job.data.applicationId,
|
||||
titleLog: job.data.titleLog,
|
||||
descriptionLog: job.data.descriptionLog,
|
||||
});
|
||||
} else if (job.data.type === "deploy") {
|
||||
await deployRemoteApplication({
|
||||
applicationId: job.data.applicationId,
|
||||
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") {
|
||||
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,
|
||||
});
|
||||
|
||||
if (job.data.server) {
|
||||
if (job.data.type === "redeploy") {
|
||||
await rebuildRemoteCompose({
|
||||
composeId: job.data.composeId,
|
||||
titleLog: job.data.titleLog,
|
||||
descriptionLog: job.data.descriptionLog,
|
||||
});
|
||||
} else if (job.data.type === "deploy") {
|
||||
await deployRemoteCompose({
|
||||
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) {
|
||||
|
@ -9,6 +9,7 @@ import { COMPOSE_PATH } from "@/server/constants";
|
||||
import type { InferResultType } from "@/server/types/with";
|
||||
import boxen from "boxen";
|
||||
import {
|
||||
getComposePath,
|
||||
writeDomainsToCompose,
|
||||
writeDomainsToComposeRemote,
|
||||
} from "../docker/domain";
|
||||
@ -73,12 +74,17 @@ export const getBuildComposeCommand = async (
|
||||
compose: ComposeNested,
|
||||
logPath: string,
|
||||
) => {
|
||||
const { sourceType, appName, mounts, composeType, domains } = compose;
|
||||
const { sourceType, appName, mounts, composeType, domains, composePath } =
|
||||
compose;
|
||||
const command = createCommand(compose);
|
||||
const envCommand = getCreateEnvFileCommand(compose);
|
||||
const projectPath = join(COMPOSE_PATH, compose.appName, "code");
|
||||
|
||||
const newCompose = await writeDomainsToComposeRemote(compose, domains);
|
||||
const newCompose = await writeDomainsToComposeRemote(
|
||||
compose,
|
||||
domains,
|
||||
logPath,
|
||||
);
|
||||
const logContent = `
|
||||
App Name: ${appName}
|
||||
Build Compose 🐳
|
||||
@ -107,6 +113,11 @@ Compose Type: ${composeType} ✅`;
|
||||
${envCommand}
|
||||
|
||||
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; }
|
||||
|
||||
|
@ -6,7 +6,7 @@ import {
|
||||
getDockerContextPath,
|
||||
} from "../filesystem/directory";
|
||||
import { spawnAsync } from "../process/spawnAsync";
|
||||
import { createEnvFile } from "./utils";
|
||||
import { createEnvFile, createEnvFileCommand } from "./utils";
|
||||
|
||||
export const buildCustomDocker = async (
|
||||
application: ApplicationNested,
|
||||
@ -86,11 +86,27 @@ export const getDockerCommand = (
|
||||
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};
|
||||
cd ${dockerContextPath} || exit 1;
|
||||
docker ${commandArgs.join(" ")} >> ${logPath} 2>&1;
|
||||
echo "Docker build completed." >> ${logPath};
|
||||
cd ${dockerContextPath} >> ${logPath} 2>> ${logPath} || {
|
||||
echo "❌ The path ${dockerContextPath} does not exist" >> ${logPath};
|
||||
exit 1;
|
||||
}
|
||||
|
||||
docker ${commandArgs.join(" ")} >> ${logPath} 2>> ${logPath} || {
|
||||
echo "❌ Docker build failed" >> ${logPath};
|
||||
exit 1;
|
||||
}
|
||||
echo "✅ Docker build completed." >> ${logPath};
|
||||
`;
|
||||
|
||||
return command;
|
||||
|
@ -62,8 +62,11 @@ export const getHerokuCommand = (
|
||||
const command = `pack ${args.join(" ")}`;
|
||||
const bashCommand = `
|
||||
echo "Starting heroku build..." >> ${logPath};
|
||||
${command} >> ${logPath} 2>&1;
|
||||
echo "Heroku build completed." >> ${logPath};
|
||||
${command} >> ${logPath} 2>> ${logPath} || {
|
||||
echo "❌ Heroku build failed" >> ${logPath};
|
||||
exit 1;
|
||||
}
|
||||
echo "✅ Heroku build completed." >> ${logPath};
|
||||
`;
|
||||
|
||||
return bashCommand;
|
||||
|
@ -16,7 +16,7 @@ import { buildCustomDocker, getDockerCommand } from "./docker-file";
|
||||
import { buildHeroku, getHerokuCommand } from "./heroku";
|
||||
import { buildNixpacks, getNixpacksCommand } from "./nixpacks";
|
||||
import { buildPaketo, getPaketoCommand } from "./paketo";
|
||||
import { buildStatic } from "./static";
|
||||
import { buildStatic, getStaticCommand } from "./static";
|
||||
import { findServerById } from "@/server/api/services/server";
|
||||
import { readSSHKey } from "../filesystem/ssh";
|
||||
import { getRemoteDocker } from "../servers/remote-docker";
|
||||
@ -81,8 +81,8 @@ export const getBuildCommand = (
|
||||
return getHerokuCommand(application, logPath);
|
||||
case "paketo_buildpacks":
|
||||
return getPaketoCommand(application, logPath);
|
||||
// case "static":
|
||||
// return buildStatic(application, writeStream);
|
||||
case "static":
|
||||
return getStaticCommand(application, logPath);
|
||||
case "dockerfile":
|
||||
return getDockerCommand(application, logPath);
|
||||
}
|
||||
|
@ -1,12 +1,11 @@
|
||||
import type { WriteStream } from "node:fs";
|
||||
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 type { ApplicationNested } from ".";
|
||||
import { prepareEnvironmentVariables } from "../docker/utils";
|
||||
import { getBuildAppDirectory } from "../filesystem/directory";
|
||||
import { spawnAsync } from "../process/spawnAsync";
|
||||
import { executeCommand } from "../servers/command";
|
||||
|
||||
export const buildNixpacks = async (
|
||||
application: ApplicationNested,
|
||||
@ -83,47 +82,44 @@ export const getNixpacksCommand = (
|
||||
const buildContainerId = `${appName}-${nanoid(10)}`;
|
||||
const envVariables = prepareEnvironmentVariables(env);
|
||||
|
||||
try {
|
||||
const args = ["build", buildAppDirectory, "--name", appName];
|
||||
const args = ["build", buildAppDirectory, "--name", appName];
|
||||
|
||||
for (const env of envVariables) {
|
||||
args.push("--env", env);
|
||||
}
|
||||
for (const env of envVariables) {
|
||||
args.push("--env", env);
|
||||
}
|
||||
|
||||
if (publishDirectory) {
|
||||
/* No need for any start command, since we'll use nginx later on */
|
||||
args.push("--no-error-without-start");
|
||||
}
|
||||
console.log("args", args);
|
||||
const command = `nixpacks ${args.join(" ")}`;
|
||||
const bashCommand = `
|
||||
if (publishDirectory) {
|
||||
/* No need for any start command, since we'll use nginx later on */
|
||||
args.push("--no-error-without-start");
|
||||
}
|
||||
console.log("args", args);
|
||||
const command = `nixpacks ${args.join(" ")}`;
|
||||
let bashCommand = `
|
||||
echo "Starting nixpacks build..." >> ${logPath};
|
||||
${command} >> ${logPath} 2>&1;
|
||||
echo "Nixpacks build completed." >> ${logPath};
|
||||
${command} >> ${logPath} 2>> ${logPath} || {
|
||||
echo "❌ Nixpacks build failed" >> ${logPath};
|
||||
exit 1;
|
||||
}
|
||||
echo "✅ Nixpacks build completed." >> ${logPath};
|
||||
`;
|
||||
|
||||
/*
|
||||
Run the container with the image created by nixpacks,
|
||||
and copy the artifacts on the host filesystem.
|
||||
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)}
|
||||
// docker rm ${buildContainerId}
|
||||
// buildStatic ${application} ${writeStream}
|
||||
// `;
|
||||
// }
|
||||
|
||||
return bashCommand;
|
||||
} catch (e) {
|
||||
// await spawnAsync("docker", ["rm", buildContainerId], writeToStream);
|
||||
|
||||
throw e;
|
||||
/*
|
||||
Run the container with the image created by nixpacks,
|
||||
and copy the artifacts on the host filesystem.
|
||||
Then, remove the container and create a static build.
|
||||
*/
|
||||
if (publishDirectory) {
|
||||
bashCommand += `
|
||||
docker create --name ${buildContainerId} ${appName}
|
||||
docker cp ${buildContainerId}:/app/${publishDirectory} ${path.join(buildAppDirectory, publishDirectory)} >> ${logPath} 2>> ${logPath} || {
|
||||
docker rm ${buildContainerId}
|
||||
echo "❌ Copying ${publishDirectory} to ${path.join(buildAppDirectory, publishDirectory)} failed" >> ${logPath};
|
||||
exit 1;
|
||||
}
|
||||
docker rm ${buildContainerId}
|
||||
${getStaticCommand(application, logPath)}
|
||||
`;
|
||||
}
|
||||
|
||||
return bashCommand;
|
||||
};
|
||||
|
@ -61,8 +61,11 @@ export const getPaketoCommand = (
|
||||
const command = `pack ${args.join(" ")}`;
|
||||
const bashCommand = `
|
||||
echo "Starting Paketo build..." >> ${logPath};
|
||||
${command} >> ${logPath} 2>&1;
|
||||
echo "Paketo build completed." >> ${logPath};
|
||||
${command} >> ${logPath} 2>> ${logPath} || {
|
||||
echo "❌ Paketo build failed" >> ${logPath};
|
||||
exit 1;
|
||||
}
|
||||
echo "✅ Paketo build completed." >> ${logPath};
|
||||
`;
|
||||
|
||||
return bashCommand;
|
||||
|
@ -1,7 +1,10 @@
|
||||
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 { createFile } from "../docker/utils";
|
||||
import { createFile, getCreateFileCommand } from "../docker/utils";
|
||||
import { getBuildAppDirectory } from "../filesystem/directory";
|
||||
|
||||
export const buildStatic = async (
|
||||
@ -36,3 +39,31 @@ export const buildStatic = async (
|
||||
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) => {
|
||||
const envFilePath = join(dirname(directory), ".env");
|
||||
// let command = ``
|
||||
if (!existsSync(dirname(envFilePath))) {
|
||||
mkdirSync(dirname(envFilePath), { recursive: true });
|
||||
}
|
||||
|
@ -96,7 +96,14 @@ export const loadDockerComposeRemote = async (
|
||||
if (!compose.serverId) {
|
||||
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;
|
||||
const parsedConfig = load(stdout) as ComposeSpecification;
|
||||
return parsedConfig;
|
||||
@ -135,21 +142,25 @@ export const writeDomainsToCompose = async (
|
||||
export const writeDomainsToComposeRemote = async (
|
||||
compose: Compose,
|
||||
domains: Domain[],
|
||||
logPath: string,
|
||||
) => {
|
||||
if (!domains.length) {
|
||||
return "";
|
||||
}
|
||||
const composeConverted = await addDomainToCompose(compose, domains);
|
||||
const path = getComposePath(compose);
|
||||
|
||||
try {
|
||||
const composeConverted = await addDomainToCompose(compose, domains);
|
||||
const path = getComposePath(compose);
|
||||
if (compose.serverId) {
|
||||
const composeString = dump(composeConverted, { lineWidth: 1000 });
|
||||
const encodedContent = encodeBase64(composeString);
|
||||
return `echo "${encodedContent}" | base64 -d > "${path}";`;
|
||||
}
|
||||
} 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
|
||||
|
@ -59,24 +59,26 @@ export const buildRemoteDocker = async (
|
||||
throw new Error("Docker image not found");
|
||||
}
|
||||
let command = `
|
||||
echo "Building ${sourceType}" >> ${logPath};
|
||||
echo "Pulling ${dockerImage}" >> ${logPath};
|
||||
`;
|
||||
|
||||
if (username && password) {
|
||||
command += `
|
||||
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;
|
||||
fi
|
||||
`;
|
||||
}
|
||||
|
||||
command += `
|
||||
echo "Pulling ${dockerImage}" >> ${logPath};
|
||||
docker pull ${dockerImage} >> ${logPath} 2>&1;
|
||||
`;
|
||||
docker pull ${dockerImage} >> ${logPath} 2>> ${logPath} || {
|
||||
echo "❌ Pulling image failed" >> ${logPath};
|
||||
exit 1;
|
||||
}
|
||||
|
||||
echo "✅ Pulling image completed." >> ${logPath};
|
||||
`;
|
||||
return command;
|
||||
} catch (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 outputPath = join(COMPOSE_PATH, appName, "code");
|
||||
const filePath = join(outputPath, "docker-compose.yml");
|
||||
@ -38,6 +41,7 @@ export const getCreateComposeFileCommand = (compose: Compose) => {
|
||||
rm -rf ${outputPath};
|
||||
mkdir -p ${outputPath};
|
||||
echo "${encodedContent}" | base64 -d > "${filePath}";
|
||||
echo "File 'docker-compose.yml' created: ✅" >> ${logPath};
|
||||
`;
|
||||
return bashCommand;
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user