Merge pull request #3018 from Dokploy/2508-git-based-deployments-should-have-git-hash-and-commit-message-on-deploy-manually

feat: add git commit info extraction to deployment logic
This commit is contained in:
Mauricio Siu
2025-11-14 22:31:36 -06:00
committed by GitHub
4 changed files with 84 additions and 3 deletions

View File

@@ -18,7 +18,10 @@ import {
} from "@dokploy/server/utils/process/execAsync"; } from "@dokploy/server/utils/process/execAsync";
import { cloneBitbucketRepository } from "@dokploy/server/utils/providers/bitbucket"; import { cloneBitbucketRepository } from "@dokploy/server/utils/providers/bitbucket";
import { buildRemoteDocker } from "@dokploy/server/utils/providers/docker"; import { buildRemoteDocker } from "@dokploy/server/utils/providers/docker";
import { cloneGitRepository } from "@dokploy/server/utils/providers/git"; import {
cloneGitRepository,
getGitCommitInfo,
} from "@dokploy/server/utils/providers/git";
import { cloneGiteaRepository } from "@dokploy/server/utils/providers/gitea"; import { cloneGiteaRepository } from "@dokploy/server/utils/providers/gitea";
import { cloneGithubRepository } from "@dokploy/server/utils/providers/github"; import { cloneGithubRepository } from "@dokploy/server/utils/providers/github";
import { cloneGitlabRepository } from "@dokploy/server/utils/providers/gitlab"; import { cloneGitlabRepository } from "@dokploy/server/utils/providers/gitlab";
@@ -29,6 +32,7 @@ import { getDokployUrl } from "./admin";
import { import {
createDeployment, createDeployment,
createDeploymentPreview, createDeploymentPreview,
updateDeployment,
updateDeploymentStatus, updateDeploymentStatus,
} from "./deployment"; } from "./deployment";
import { type Domain, getDomainHost } from "./domain"; import { type Domain, getDomainHost } from "./domain";
@@ -243,6 +247,18 @@ export const deployApplication = async ({
}); });
throw error; throw error;
} finally {
// Only extract commit info for non-docker sources
if (application.sourceType !== "docker") {
const commitInfo = await getGitCommitInfo(application);
if (commitInfo) {
await updateDeployment(deployment.deploymentId, {
title: commitInfo.message,
description: `Commit: ${commitInfo.hash}`,
});
}
}
} }
return true; return true;
}; };

View File

@@ -22,7 +22,10 @@ import {
execAsyncRemote, execAsyncRemote,
} from "@dokploy/server/utils/process/execAsync"; } from "@dokploy/server/utils/process/execAsync";
import { cloneBitbucketRepository } from "@dokploy/server/utils/providers/bitbucket"; import { cloneBitbucketRepository } from "@dokploy/server/utils/providers/bitbucket";
import { cloneGitRepository } from "@dokploy/server/utils/providers/git"; import {
cloneGitRepository,
getGitCommitInfo,
} from "@dokploy/server/utils/providers/git";
import { cloneGiteaRepository } from "@dokploy/server/utils/providers/gitea"; import { cloneGiteaRepository } from "@dokploy/server/utils/providers/gitea";
import { cloneGithubRepository } from "@dokploy/server/utils/providers/github"; import { cloneGithubRepository } from "@dokploy/server/utils/providers/github";
import { cloneGitlabRepository } from "@dokploy/server/utils/providers/gitlab"; import { cloneGitlabRepository } from "@dokploy/server/utils/providers/gitlab";
@@ -30,7 +33,11 @@ import { getCreateComposeFileCommand } from "@dokploy/server/utils/providers/raw
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,
updateDeployment,
updateDeploymentStatus,
} from "./deployment";
import { validUniqueServerAppName } from "./project"; import { validUniqueServerAppName } from "./project";
export type Compose = typeof compose.$inferSelect; export type Compose = typeof compose.$inferSelect;
@@ -239,6 +246,7 @@ export const deployCompose = async ({
await execAsync(commandWithLog); await execAsync(commandWithLog);
} }
command = "set -e;";
command += await getBuildComposeCommand(entity); command += await getBuildComposeCommand(entity);
commandWithLog = `(${command}) >> ${deployment.logPath} 2>&1`; commandWithLog = `(${command}) >> ${deployment.logPath} 2>&1`;
if (compose.serverId) { if (compose.serverId) {
@@ -275,6 +283,19 @@ export const deployCompose = async ({
organizationId: compose.environment.project.organizationId, organizationId: compose.environment.project.organizationId,
}); });
throw error; throw error;
} finally {
if (compose.sourceType !== "raw") {
const commitInfo = await getGitCommitInfo({
...compose,
type: "compose",
});
if (commitInfo) {
await updateDeployment(deployment.deploymentId, {
title: commitInfo.message,
description: `Commit: ${commitInfo.hash}`,
});
}
}
} }
}; };

View File

@@ -131,6 +131,8 @@ exit 1;
exit 1; exit 1;
`; `;
} }
return "";
}; };
export const addDomainToCompose = async ( export const addDomainToCompose = async (
compose: Compose, compose: Compose,

View File

@@ -4,6 +4,7 @@ import {
findSSHKeyById, findSSHKeyById,
updateSSHKeyById, updateSSHKeyById,
} from "@dokploy/server/services/ssh-key"; } from "@dokploy/server/services/ssh-key";
import { execAsync, execAsyncRemote } from "../process/execAsync";
interface CloneGitRepository { interface CloneGitRepository {
appName: string; appName: string;
@@ -145,3 +146,44 @@ const sanitizeRepoPathSSH = (input: string) => {
}, },
}; };
}; };
interface Props {
appName: string;
type?: "application" | "compose";
serverId: string | null;
}
export const getGitCommitInfo = async ({
appName,
type = "application",
serverId,
}: Props) => {
const { COMPOSE_PATH, APPLICATIONS_PATH } = paths(!!serverId);
const basePath = type === "compose" ? COMPOSE_PATH : APPLICATIONS_PATH;
const outputPath = join(basePath, appName, "code");
let stdoutResult = "";
const result = {
message: "",
hash: "",
};
try {
const gitCommand = `git -C ${outputPath} log -1 --pretty=format:"%H---DELIMITER---%B"`;
if (serverId) {
const { stdout } = await execAsyncRemote(serverId, gitCommand);
stdoutResult = stdout.trim();
} else {
const { stdout } = await execAsync(gitCommand);
stdoutResult = stdout.trim();
}
const parts = stdoutResult.split("---DELIMITER---");
if (parts && parts.length === 2) {
result.hash = parts[0]?.trim() || "";
result.message = parts[1]?.trim() || "";
}
} catch (error) {
console.error(`Error getting git commit info: ${error}`);
return null;
}
return result;
};