Refactor deployment logic: remove unused remote preview deployment function, streamline deployment commands, and enhance error handling for Docker image pulling. Update build command generation for Docker source type.

This commit is contained in:
Mauricio Siu
2025-11-09 03:24:13 -06:00
parent f96114ad80
commit a05b75fc67
4 changed files with 42 additions and 211 deletions

View File

@@ -2,7 +2,6 @@ import {
deployApplication,
deployCompose,
deployPreviewApplication,
deployRemotePreviewApplication,
rebuildApplication,
rebuildCompose,
updateApplicationStatus,
@@ -54,24 +53,14 @@ export const deploymentWorker = new Worker(
await updatePreviewDeployment(job.data.previewDeploymentId, {
previewStatus: "running",
});
if (job.data.server) {
if (job.data.type === "deploy") {
await deployRemotePreviewApplication({
applicationId: job.data.applicationId,
titleLog: job.data.titleLog,
descriptionLog: job.data.descriptionLog,
previewDeploymentId: job.data.previewDeploymentId,
});
}
} else {
if (job.data.type === "deploy") {
await deployPreviewApplication({
applicationId: job.data.applicationId,
titleLog: job.data.titleLog,
descriptionLog: job.data.descriptionLog,
previewDeploymentId: job.data.previewDeploymentId,
});
}
if (job.data.type === "deploy") {
await deployPreviewApplication({
applicationId: job.data.applicationId,
titleLog: job.data.titleLog,
descriptionLog: job.data.descriptionLog,
previewDeploymentId: job.data.previewDeploymentId,
});
}
}
} catch (error) {

View File

@@ -18,10 +18,7 @@ import {
execAsyncRemote,
} from "@dokploy/server/utils/process/execAsync";
import { cloneBitbucketRepository } from "@dokploy/server/utils/providers/bitbucket";
import {
buildDocker,
buildRemoteDocker,
} from "@dokploy/server/utils/providers/docker";
import { buildRemoteDocker } from "@dokploy/server/utils/providers/docker";
import { cloneGitRepository } from "@dokploy/server/utils/providers/git";
import { cloneGiteaRepository } from "@dokploy/server/utils/providers/gitea";
import { cloneGithubRepository } from "@dokploy/server/utils/providers/github";
@@ -192,9 +189,12 @@ export const deployApplication = async ({
command += await cloneGitRepository(application);
} else if (application.sourceType === "drop") {
await buildApplication(application, deployment.logPath);
} else if (application.sourceType === "docker") {
command += await buildRemoteDocker(application);
}
command += getBuildCommand(application);
const commandWithLog = `(${command}) >> ${deployment.logPath} 2>&1`;
if (application.serverId) {
await execAsyncRemote(application.serverId, commandWithLog);
@@ -206,16 +206,16 @@ export const deployApplication = async ({
await updateDeploymentStatus(deployment.deploymentId, "done");
await updateApplicationStatus(applicationId, "done");
// if (application.rollbackActive) {
// const tagImage =
// application.sourceType === "docker"
// ? application.dockerImage
// : application.appName;
// await createRollback({
// appName: tagImage || "",
// deploymentId: deployment.deploymentId,
// });
// }
if (application.rollbackActive) {
const tagImage =
application.sourceType === "docker"
? application.dockerImage
: application.appName;
await createRollback({
appName: tagImage || "",
deploymentId: deployment.deploymentId,
});
}
await sendBuildSuccessNotifications({
projectName: application.environment.project.name,
@@ -359,131 +359,23 @@ export const deployPreviewApplication = async ({
application.buildArgs = `${application.previewBuildArgs}\nDOKPLOY_DEPLOY_URL=${previewDeployment?.domain?.host}`;
application.buildSecrets = `${application.previewBuildSecrets}\nDOKPLOY_DEPLOY_URL=${previewDeployment?.domain?.host}`;
let command = "set -e;";
if (application.sourceType === "github") {
await cloneGithubRepository({
command += await cloneGithubRepository({
...application,
appName: previewDeployment.appName,
branch: previewDeployment.branch,
logPath: deployment.logPath,
});
await buildApplication(application, deployment.logPath);
}
const successComment = getIssueComment(
application.name,
"success",
previewDomain,
);
await updateIssueComment({
...issueParams,
body: `### Dokploy Preview Deployment\n\n${successComment}`,
});
await updateDeploymentStatus(deployment.deploymentId, "done");
await updatePreviewDeployment(previewDeploymentId, {
previewStatus: "done",
});
} catch (error) {
const comment = getIssueComment(application.name, "error", previewDomain);
await updateIssueComment({
...issueParams,
body: `### Dokploy Preview Deployment\n\n${comment}`,
});
await updateDeploymentStatus(deployment.deploymentId, "error");
await updatePreviewDeployment(previewDeploymentId, {
previewStatus: "error",
});
throw error;
}
command += getBuildCommand(application);
return true;
};
export const deployRemotePreviewApplication = async ({
applicationId,
titleLog = "Preview Deployment",
descriptionLog = "",
previewDeploymentId,
}: {
applicationId: string;
titleLog: string;
descriptionLog: string;
previewDeploymentId: string;
}) => {
const application = await findApplicationById(applicationId);
const deployment = await createDeploymentPreview({
title: titleLog,
description: descriptionLog,
previewDeploymentId: previewDeploymentId,
});
const previewDeployment =
await findPreviewDeploymentById(previewDeploymentId);
await updatePreviewDeployment(previewDeploymentId, {
createdAt: new Date().toISOString(),
});
const previewDomain = getDomainHost(previewDeployment?.domain as Domain);
const issueParams = {
owner: application?.owner || "",
repository: application?.repository || "",
issue_number: previewDeployment.pullRequestNumber,
comment_id: Number.parseInt(previewDeployment.pullRequestCommentId),
githubId: application?.githubId || "",
};
try {
const commentExists = await issueCommentExists({
...issueParams,
});
if (!commentExists) {
const result = await createPreviewDeploymentComment({
...issueParams,
previewDomain,
appName: previewDeployment.appName,
githubId: application?.githubId || "",
previewDeploymentId,
});
if (!result) {
throw new TRPCError({
code: "NOT_FOUND",
message: "Pull request comment not found",
});
const commandWithLog = `(${command}) >> ${deployment.logPath} 2>&1`;
if (application.serverId) {
await execAsyncRemote(application.serverId, commandWithLog);
} else {
await execAsync(commandWithLog);
}
issueParams.comment_id = Number.parseInt(result?.pullRequestCommentId);
}
const buildingComment = getIssueComment(
application.name,
"running",
previewDomain,
);
await updateIssueComment({
...issueParams,
body: `### Dokploy Preview Deployment\n\n${buildingComment}`,
});
application.appName = previewDeployment.appName;
application.env = `${application.previewEnv}\nDOKPLOY_DEPLOY_URL=${previewDeployment?.domain?.host}`;
application.buildArgs = `${application.previewBuildArgs}\nDOKPLOY_DEPLOY_URL=${previewDeployment?.domain?.host}`;
application.buildSecrets = `${application.previewBuildSecrets}\nDOKPLOY_DEPLOY_URL=${previewDeployment?.domain?.host}`;
if (application.serverId) {
let command = "set -e;";
if (application.sourceType === "github") {
command += await cloneGithubRepository({
...application,
appName: previewDeployment.appName,
branch: previewDeployment.branch,
serverId: application.serverId,
logPath: deployment.logPath,
});
}
command += getBuildCommand(application, deployment.logPath);
await execAsyncRemote(application.serverId, command);
await mechanizeDockerContainer(application);
}
const successComment = getIssueComment(
application.name,
"success",

View File

@@ -79,6 +79,10 @@ export const buildApplication = async (
export const getBuildCommand = (application: ApplicationNested) => {
let command = "";
const { buildType, registry } = application;
if (application.sourceType === "docker") {
return "";
}
switch (buildType) {
case "nixpacks":
command = getNixpacksCommand(application);

View File

@@ -1,60 +1,6 @@
import { createWriteStream } from "node:fs";
import { type ApplicationNested, mechanizeDockerContainer } from "../builders";
import { pullImage } from "../docker/utils";
import type { ApplicationNested } from "../builders";
interface RegistryAuth {
username: string;
password: string;
registryUrl: string;
}
export const buildDocker = async (
application: ApplicationNested,
logPath: string,
): Promise<void> => {
const { buildType, dockerImage, username, password } = application;
const authConfig: Partial<RegistryAuth> = {
username: username || "",
password: password || "",
registryUrl: application.registryUrl || "",
};
const writeStream = createWriteStream(logPath, { flags: "a" });
writeStream.write(`\nBuild ${buildType}\n`);
writeStream.write(`Pulling ${dockerImage}: ✅\n`);
try {
if (!dockerImage) {
throw new Error("Docker image not found");
}
await pullImage(
dockerImage,
(data) => {
if (writeStream.writable) {
writeStream.write(`${data}\n`);
}
},
authConfig,
);
await mechanizeDockerContainer(application);
writeStream.write("\nDocker Deployed: ✅\n");
} catch (error) {
writeStream.write(
`❌ Error: ${error instanceof Error ? error.message : String(error)}`,
);
throw error;
} finally {
writeStream.end();
}
};
export const buildRemoteDocker = async (
application: ApplicationNested,
logPath: string,
) => {
export const buildRemoteDocker = async (application: ApplicationNested) => {
const { registryUrl, dockerImage, username, password } = application;
try {
@@ -62,25 +8,25 @@ export const buildRemoteDocker = async (
throw new Error("Docker image not found");
}
let command = `
echo "Pulling ${dockerImage}" >> ${logPath};
echo "Pulling ${dockerImage}";
`;
if (username && password) {
command += `
if ! echo "${password}" | docker login --username "${username}" --password-stdin "${registryUrl || ""}" >> ${logPath} 2>&1; then
echo "❌ Login failed" >> ${logPath};
if ! echo "${password}" | docker login --username "${username}" --password-stdin "${registryUrl || ""}" 2>&1; then
echo "❌ Login failed";
exit 1;
fi
`;
}
command += `
docker pull ${dockerImage} >> ${logPath} 2>> ${logPath} || {
echo "❌ Pulling image failed" >> ${logPath};
docker pull ${dockerImage} 2>&1 || {
echo "❌ Pulling image failed";
exit 1;
}
echo "✅ Pulling image completed." >> ${logPath};
echo "✅ Pulling image completed.";
`;
return command;
} catch (error) {