Compare commits

..

1 Commits

Author SHA1 Message Date
Mauricio Siu
dfff91c6f3 fix: support hashtag and special chars in branch names for git clone
Branch names were interpolated unquoted into the git clone shell command,
so a `#` (valid in git branch names) started a shell comment and dropped
the rest of the command, causing the clone to fail (#4585).

Escape the branch name with shell-quote (already a dependency) across all
providers: gitlab, github, gitea, bitbucket and custom git.
2026-06-16 07:12:40 -06:00
6 changed files with 11 additions and 18 deletions

View File

@@ -32,19 +32,7 @@ export const startLogCleanup = async (
await execAsync(
`tail -n 1000 ${accessLogPath} > ${accessLogPath}.tmp && mv ${accessLogPath}.tmp ${accessLogPath}`,
);
// Traefik can run as a standalone container ("dokploy-traefik") or a
// swarm service task ("dokploy-traefik.1.<task-id>"), so resolve the
// running container id dynamically instead of assuming the name.
const { stdout: containerId } = await execAsync(
'docker ps -q --filter "name=dokploy-traefik" --filter "status=running" | head -n 1',
);
const traefikContainerId = containerId.trim();
if (!traefikContainerId) {
console.error("Traefik container not found, skipping log reopen");
return;
}
await execAsync(`docker exec ${traefikContainerId} kill -USR1 1`);
await execAsync("docker exec dokploy-traefik kill -USR1 1");
} catch (error) {
console.error("Error during log cleanup:", error);
}

View File

@@ -10,6 +10,7 @@ import {
} from "@dokploy/server/services/bitbucket";
import type { InferResultType } from "@dokploy/server/types/with";
import { TRPCError } from "@trpc/server";
import { quote } from "shell-quote";
import type { z } from "zod";
export type ApplicationWithBitbucket = InferResultType<
@@ -125,7 +126,7 @@ export const cloneBitbucketRepository = async ({
const repoclone = `bitbucket.org/${bitbucketOwner}/${repoToUse}.git`;
const cloneUrl = getBitbucketCloneUrl(bitbucket, repoclone);
command += `echo "Cloning Repo ${repoclone} to ${outputPath}: ✅";`;
command += `git clone --branch ${bitbucketBranch} --depth 1 ${enableSubmodules ? "--recurse-submodules" : ""} ${cloneUrl} ${outputPath} --progress;`;
command += `git clone --branch ${quote([bitbucketBranch])} --depth 1 ${enableSubmodules ? "--recurse-submodules" : ""} ${cloneUrl} ${outputPath} --progress;`;
return command;
};

View File

@@ -4,6 +4,7 @@ import {
findSSHKeyById,
updateSSHKeyById,
} from "@dokploy/server/services/ssh-key";
import { quote } from "shell-quote";
import { execAsync, execAsyncRemote } from "../process/execAsync";
interface CloneGitRepository {
@@ -78,7 +79,7 @@ export const cloneGitRepository = async ({
command += "chmod 600 /tmp/id_rsa;";
command += `export GIT_SSH_COMMAND="${gitSshCommand}";`;
}
command += `if ! git clone --branch ${customGitBranch} --depth 1 ${enableSubmodules ? "--recurse-submodules" : ""} --progress ${customGitUrl} ${outputPath}; then
command += `if ! git clone --branch ${quote([customGitBranch ?? ""])} --depth 1 ${enableSubmodules ? "--recurse-submodules" : ""} --progress ${customGitUrl} ${outputPath}; then
echo "❌ [ERROR] Fail to clone the repository ${customGitUrl}";
exit 1;
fi

View File

@@ -7,6 +7,7 @@ import {
} from "@dokploy/server/services/gitea";
import type { InferResultType } from "@dokploy/server/types/with";
import { TRPCError } from "@trpc/server";
import { quote } from "shell-quote";
export const getErrorCloneRequirements = (entity: {
giteaRepository?: string | null;
@@ -177,7 +178,7 @@ export const cloneGiteaRepository = async ({
);
command += `echo "Cloning Repo ${repoClone} to ${outputPath}: ✅";`;
command += `git clone --branch ${giteaBranch} --depth 1 ${enableSubmodules ? "--recurse-submodules" : ""} ${cloneUrl} ${outputPath} --progress;`;
command += `git clone --branch ${quote([giteaBranch])} --depth 1 ${enableSubmodules ? "--recurse-submodules" : ""} ${cloneUrl} ${outputPath} --progress;`;
return command;
};

View File

@@ -6,6 +6,7 @@ import type { InferResultType } from "@dokploy/server/types/with";
import { createAppAuth } from "@octokit/auth-app";
import { TRPCError } from "@trpc/server";
import { Octokit } from "octokit";
import { quote } from "shell-quote";
import type { z } from "zod";
export const authGithub = (githubProvider: Github): Octokit => {
@@ -167,7 +168,7 @@ export const cloneGithubRepository = async ({
const cloneUrl = `https://oauth2:${token}@${repoclone}`;
command += `echo "Cloning Repo ${repoclone} to ${outputPath}: ✅";`;
command += `git clone --branch ${branch} --depth 1 ${enableSubmodules ? "--recurse-submodules" : ""} ${cloneUrl} ${outputPath} --progress;`;
command += `git clone --branch ${quote([branch])} --depth 1 ${enableSubmodules ? "--recurse-submodules" : ""} ${cloneUrl} ${outputPath} --progress;`;
return command;
};

View File

@@ -8,6 +8,7 @@ import {
} from "@dokploy/server/services/gitlab";
import type { InferResultType } from "@dokploy/server/types/with";
import { TRPCError } from "@trpc/server";
import { quote } from "shell-quote";
import type { z } from "zod";
export const refreshGitlabToken = async (gitlabProviderId: string) => {
@@ -152,7 +153,7 @@ export const cloneGitlabRepository = async ({
const repoClone = getGitlabRepoClone(gitlab, gitlabPathNamespace);
const cloneUrl = getGitlabCloneUrl(gitlab, repoClone);
command += `echo "Cloning Repo ${repoClone} to ${outputPath}: ✅";`;
command += `git clone --branch ${gitlabBranch} --depth 1 ${enableSubmodules ? "--recurse-submodules" : ""} ${cloneUrl} ${outputPath} --progress;`;
command += `git clone --branch ${quote([gitlabBranch])} --depth 1 ${enableSubmodules ? "--recurse-submodules" : ""} ${cloneUrl} ${outputPath} --progress;`;
return command;
};