mirror of
https://github.com/Dokploy/dokploy.git
synced 2026-06-20 06:35:22 +02:00
refactor(patch): simplify patch repository management and enhance git configuration handling
- Removed redundant helper functions for retrieving git configurations for applications and composes, streamlining the codebase. - Updated the `ensurePatchRepo` function to directly handle repository cloning based on the application or compose type, improving clarity and maintainability. - Refactored patch creation logic to eliminate unnecessary checks and streamline the process of creating patches. - Enhanced the handling of output paths in repository cloning functions across different git providers, ensuring consistent behavior.
This commit is contained in:
@@ -32,90 +32,6 @@ import {
|
||||
apiUpdatePatch,
|
||||
} from "@/server/db/schema";
|
||||
|
||||
// Helper to get git config from application
|
||||
const getApplicationGitConfig = (
|
||||
app: Awaited<ReturnType<typeof findApplicationById>>,
|
||||
) => {
|
||||
switch (app.sourceType) {
|
||||
case "github":
|
||||
return {
|
||||
gitUrl: `https://github.com/${app.owner}/${app.repository}.git`,
|
||||
gitBranch: app.branch || "main",
|
||||
sshKeyId: null,
|
||||
};
|
||||
case "gitlab":
|
||||
return {
|
||||
gitUrl: `https://gitlab.com/${app.gitlabOwner}/${app.gitlabRepository}.git`,
|
||||
gitBranch: app.gitlabBranch || "main",
|
||||
sshKeyId: null,
|
||||
};
|
||||
case "gitea":
|
||||
return {
|
||||
gitUrl: app.gitea?.giteaUrl
|
||||
? `${app.gitea.giteaUrl}/${app.giteaOwner}/${app.giteaRepository}.git`
|
||||
: "",
|
||||
gitBranch: app.giteaBranch || "main",
|
||||
sshKeyId: null,
|
||||
};
|
||||
case "bitbucket":
|
||||
return {
|
||||
gitUrl: `https://bitbucket.org/${app.bitbucketOwner}/${app.bitbucketRepository}.git`,
|
||||
gitBranch: app.bitbucketBranch || "main",
|
||||
sshKeyId: null,
|
||||
};
|
||||
case "git":
|
||||
return {
|
||||
gitUrl: app.customGitUrl || "",
|
||||
gitBranch: app.customGitBranch || "main",
|
||||
sshKeyId: app.customGitSSHKeyId,
|
||||
};
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
// Helper to get git config from compose
|
||||
const getComposeGitConfig = (
|
||||
compose: Awaited<ReturnType<typeof findComposeById>>,
|
||||
) => {
|
||||
switch (compose.sourceType) {
|
||||
case "github":
|
||||
return {
|
||||
gitUrl: `https://github.com/${compose.owner}/${compose.repository}.git`,
|
||||
gitBranch: compose.branch || "main",
|
||||
sshKeyId: null,
|
||||
};
|
||||
case "gitlab":
|
||||
return {
|
||||
gitUrl: `https://gitlab.com/${compose.gitlabOwner}/${compose.gitlabRepository}.git`,
|
||||
gitBranch: compose.gitlabBranch || "main",
|
||||
sshKeyId: null,
|
||||
};
|
||||
case "gitea":
|
||||
return {
|
||||
gitUrl: compose.gitea?.giteaUrl
|
||||
? `${compose.gitea.giteaUrl}/${compose.giteaOwner}/${compose.giteaRepository}.git`
|
||||
: "",
|
||||
gitBranch: compose.giteaBranch || "main",
|
||||
sshKeyId: null,
|
||||
};
|
||||
case "bitbucket":
|
||||
return {
|
||||
gitUrl: `https://bitbucket.org/${compose.bitbucketOwner}/${compose.bitbucketRepository}.git`,
|
||||
gitBranch: compose.bitbucketBranch || "main",
|
||||
sshKeyId: null,
|
||||
};
|
||||
case "git":
|
||||
return {
|
||||
gitUrl: compose.customGitUrl || "",
|
||||
gitBranch: compose.customGitBranch || "main",
|
||||
sshKeyId: compose.customGitSSHKeyId,
|
||||
};
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
export const patchRouter = createTRPCRouter({
|
||||
// CRUD Operations
|
||||
create: protectedProcedure
|
||||
@@ -222,70 +138,10 @@ export const patchRouter = createTRPCRouter({
|
||||
type: z.enum(["application", "compose"]),
|
||||
}),
|
||||
)
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
if (input.type === "application") {
|
||||
const app = await findApplicationById(input.id);
|
||||
if (
|
||||
app.environment.project.organizationId !==
|
||||
ctx.session.activeOrganizationId
|
||||
) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to access this application",
|
||||
});
|
||||
}
|
||||
|
||||
const gitConfig = getApplicationGitConfig(app);
|
||||
if (!gitConfig || !gitConfig.gitUrl) {
|
||||
throw new TRPCError({
|
||||
code: "BAD_REQUEST",
|
||||
message: "Application does not have a git source configured",
|
||||
});
|
||||
}
|
||||
|
||||
return await ensurePatchRepo({
|
||||
appName: app.appName,
|
||||
type: "application",
|
||||
gitUrl: gitConfig.gitUrl,
|
||||
gitBranch: gitConfig.gitBranch,
|
||||
sshKeyId: gitConfig.sshKeyId,
|
||||
serverId: app.serverId,
|
||||
});
|
||||
}
|
||||
|
||||
if (input.type === "compose") {
|
||||
const compose = await findComposeById(input.id);
|
||||
if (
|
||||
compose.environment.project.organizationId !==
|
||||
ctx.session.activeOrganizationId
|
||||
) {
|
||||
throw new TRPCError({
|
||||
code: "UNAUTHORIZED",
|
||||
message: "You are not authorized to access this compose",
|
||||
});
|
||||
}
|
||||
|
||||
const gitConfig = getComposeGitConfig(compose);
|
||||
if (!gitConfig || !gitConfig.gitUrl) {
|
||||
throw new TRPCError({
|
||||
code: "BAD_REQUEST",
|
||||
message: "Compose does not have a git source configured",
|
||||
});
|
||||
}
|
||||
|
||||
return await ensurePatchRepo({
|
||||
appName: compose.appName,
|
||||
type: "compose",
|
||||
gitUrl: gitConfig.gitUrl,
|
||||
gitBranch: gitConfig.gitBranch,
|
||||
sshKeyId: gitConfig.sshKeyId,
|
||||
serverId: compose.serverId,
|
||||
});
|
||||
}
|
||||
|
||||
throw new TRPCError({
|
||||
code: "BAD_REQUEST",
|
||||
message: "Either application or compose must be provided",
|
||||
.mutation(async ({ input }) => {
|
||||
return await ensurePatchRepo({
|
||||
type: input.type,
|
||||
id: input.id,
|
||||
});
|
||||
}),
|
||||
|
||||
@@ -432,48 +288,14 @@ export const patchRouter = createTRPCRouter({
|
||||
});
|
||||
}
|
||||
|
||||
// Generate patch diff
|
||||
const patchContent = await generatePatch({
|
||||
codePath: input.repoPath,
|
||||
filePath: input.filePath,
|
||||
newContent: input.content,
|
||||
serverId,
|
||||
});
|
||||
|
||||
if (!patchContent.trim()) {
|
||||
// No changes - remove existing patch if any
|
||||
const existingPatch = await findPatchByFilePath(
|
||||
input.filePath,
|
||||
input.id,
|
||||
input.type,
|
||||
);
|
||||
if (existingPatch) {
|
||||
await deletePatch(existingPatch.patchId);
|
||||
}
|
||||
return { deleted: true, patchId: null };
|
||||
}
|
||||
|
||||
// Check if patch exists
|
||||
const existingPatch = await findPatchByFilePath(
|
||||
input.filePath,
|
||||
input.id,
|
||||
input.type,
|
||||
);
|
||||
|
||||
if (existingPatch) {
|
||||
await updatePatch(existingPatch.patchId, { content: patchContent });
|
||||
return { deleted: false, patchId: existingPatch.patchId };
|
||||
}
|
||||
|
||||
const newPatch = await createPatch({
|
||||
filePath: input.filePath,
|
||||
content: patchContent,
|
||||
enabled: true,
|
||||
content: input.content,
|
||||
applicationId: input.type === "application" ? input.id : undefined,
|
||||
composeId: input.type === "compose" ? input.id : undefined,
|
||||
});
|
||||
|
||||
return { deleted: false, patchId: newPatch.patchId };
|
||||
return newPatch;
|
||||
}),
|
||||
|
||||
// Cleanup
|
||||
|
||||
@@ -1,16 +1,18 @@
|
||||
import path, { join } from "node:path";
|
||||
import { join } from "node:path";
|
||||
import { paths } from "@dokploy/server/constants";
|
||||
import { findSSHKeyById } from "@dokploy/server/services/ssh-key";
|
||||
import { TRPCError } from "@trpc/server";
|
||||
import { execAsync, execAsyncRemote } from "../utils/process/execAsync";
|
||||
import { cloneBitbucketRepository } from "../utils/providers/bitbucket";
|
||||
import { cloneGitRepository } from "../utils/providers/git";
|
||||
import { cloneGiteaRepository } from "../utils/providers/gitea";
|
||||
import { cloneGithubRepository } from "../utils/providers/github";
|
||||
import { cloneGitlabRepository } from "../utils/providers/gitlab";
|
||||
import { findApplicationById } from "./application";
|
||||
import { findComposeById } from "./compose";
|
||||
|
||||
interface PatchRepoConfig {
|
||||
appName: string;
|
||||
type: "application" | "compose";
|
||||
gitUrl: string;
|
||||
gitBranch: string;
|
||||
sshKeyId?: string | null;
|
||||
serverId?: string | null;
|
||||
id: string;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -18,98 +20,51 @@ interface PatchRepoConfig {
|
||||
* Returns path to the repo
|
||||
*/
|
||||
export const ensurePatchRepo = async ({
|
||||
appName,
|
||||
type,
|
||||
gitUrl,
|
||||
gitBranch,
|
||||
sshKeyId,
|
||||
serverId,
|
||||
id,
|
||||
}: PatchRepoConfig): Promise<string> => {
|
||||
const { PATCH_REPOS_PATH, SSH_PATH } = paths(!!serverId);
|
||||
const repoPath = join(PATCH_REPOS_PATH, type, appName);
|
||||
const knownHostsPath = path.join(SSH_PATH, "known_hosts");
|
||||
let serverId: string | null = null;
|
||||
|
||||
// Check if repo exists
|
||||
const checkCommand = `test -d "${repoPath}/.git" && echo "exists" || echo "not_exists"`;
|
||||
if (type === "application") {
|
||||
const application = await findApplicationById(id);
|
||||
serverId = application.buildServerId || application.serverId;
|
||||
} else {
|
||||
const compose = await findComposeById(id);
|
||||
serverId = compose.serverId;
|
||||
}
|
||||
|
||||
const application =
|
||||
type === "application"
|
||||
? await findApplicationById(id)
|
||||
: await findComposeById(id);
|
||||
|
||||
const { PATCH_REPOS_PATH } = paths(!!serverId);
|
||||
const repoPath = join(PATCH_REPOS_PATH, type, application.appName);
|
||||
|
||||
const applicationEntity = {
|
||||
...application,
|
||||
type,
|
||||
serverId: serverId,
|
||||
outputPathOverride: repoPath,
|
||||
};
|
||||
|
||||
let command = "set -e;";
|
||||
if (application.sourceType === "github") {
|
||||
command += await cloneGithubRepository(applicationEntity);
|
||||
} else if (application.sourceType === "gitlab") {
|
||||
command += await cloneGitlabRepository(applicationEntity);
|
||||
} else if (application.sourceType === "gitea") {
|
||||
command += await cloneGiteaRepository(applicationEntity);
|
||||
} else if (application.sourceType === "bitbucket") {
|
||||
command += await cloneBitbucketRepository(applicationEntity);
|
||||
} else if (application.sourceType === "git") {
|
||||
command += await cloneGitRepository(applicationEntity);
|
||||
}
|
||||
|
||||
let exists = false;
|
||||
if (serverId) {
|
||||
const result = await execAsyncRemote(serverId, checkCommand);
|
||||
exists = result.stdout.trim() === "exists";
|
||||
await execAsyncRemote(serverId, command);
|
||||
} else {
|
||||
const result = await execAsync(checkCommand);
|
||||
exists = result.stdout.trim() === "exists";
|
||||
}
|
||||
|
||||
// Setup SSH if needed
|
||||
let sshSetup = "";
|
||||
if (sshKeyId) {
|
||||
const sshKey = await findSSHKeyById(sshKeyId);
|
||||
const temporalKeyPath = "/tmp/patch_repo_id_rsa";
|
||||
sshSetup = `
|
||||
echo "${sshKey.privateKey}" > ${temporalKeyPath};
|
||||
chmod 600 ${temporalKeyPath};
|
||||
export GIT_SSH_COMMAND="ssh -i ${temporalKeyPath} -o UserKnownHostsFile=${knownHostsPath} -o StrictHostKeyChecking=accept-new";
|
||||
`;
|
||||
}
|
||||
|
||||
if (!exists) {
|
||||
// Clone the repo
|
||||
const cloneCommand = `
|
||||
set -e;
|
||||
${sshSetup}
|
||||
mkdir -p "${repoPath}";
|
||||
git clone --branch ${gitBranch} --progress "${gitUrl}" "${repoPath}";
|
||||
echo "Repository cloned successfully";
|
||||
`;
|
||||
|
||||
try {
|
||||
if (serverId) {
|
||||
await execAsyncRemote(serverId, cloneCommand);
|
||||
} else {
|
||||
await execAsync(cloneCommand);
|
||||
}
|
||||
} catch (error) {
|
||||
throw new TRPCError({
|
||||
code: "INTERNAL_SERVER_ERROR",
|
||||
message: `Failed to clone repository: ${error}`,
|
||||
});
|
||||
}
|
||||
} else {
|
||||
// Repo exists - check if on correct branch and update
|
||||
const updateCommand = `
|
||||
set -e;
|
||||
cd "${repoPath}";
|
||||
${sshSetup}
|
||||
|
||||
# Fetch all updates including tags
|
||||
git fetch origin --tags --force
|
||||
|
||||
# Checkout the target (branch or tag) - this handles switching branches/tags
|
||||
git checkout --force "${gitBranch}"
|
||||
|
||||
# If it's a branch that corresponds to a remote branch, hard reset to match remote
|
||||
# This ensures we pull the latest changes for that branch.
|
||||
# If it's a tag, we are already at the correct commit after checkout.
|
||||
if git rev-parse --verify "origin/${gitBranch}" >/dev/null 2>&1; then
|
||||
git reset --hard "origin/${gitBranch}"
|
||||
fi
|
||||
|
||||
echo "Updated repository to ${gitBranch}"
|
||||
`;
|
||||
|
||||
try {
|
||||
if (serverId) {
|
||||
await execAsyncRemote(serverId, updateCommand);
|
||||
} else {
|
||||
await execAsync(updateCommand);
|
||||
}
|
||||
} catch (error) {
|
||||
throw new TRPCError({
|
||||
code: "INTERNAL_SERVER_ERROR",
|
||||
message: `Failed to update repository: ${error}`,
|
||||
});
|
||||
}
|
||||
await execAsync(command);
|
||||
}
|
||||
|
||||
return repoPath;
|
||||
@@ -132,8 +87,6 @@ export const readPatchRepoDirectory = async (
|
||||
// Use git ls-tree to get tracked files only
|
||||
const command = `cd "${repoPath}" && git ls-tree -r --name-only HEAD`;
|
||||
|
||||
console.log("command", command);
|
||||
|
||||
let stdout: string;
|
||||
try {
|
||||
if (serverId) {
|
||||
|
||||
@@ -11,8 +11,6 @@ import { and, eq, isNotNull } from "drizzle-orm";
|
||||
|
||||
export type Patch = typeof patch.$inferSelect;
|
||||
|
||||
// CRUD Operations
|
||||
|
||||
export const createPatch = async (input: typeof apiCreatePatch._type) => {
|
||||
if (!input.applicationId && !input.composeId) {
|
||||
throw new TRPCError({
|
||||
@@ -25,9 +23,8 @@ export const createPatch = async (input: typeof apiCreatePatch._type) => {
|
||||
.insert(patch)
|
||||
.values({
|
||||
...input,
|
||||
content: input.content.endsWith("\n")
|
||||
? input.content
|
||||
: `${input.content}\n`,
|
||||
content: input.content,
|
||||
enabled: true,
|
||||
})
|
||||
.returning()
|
||||
.then((value) => value[0]);
|
||||
@@ -187,95 +184,3 @@ export const applyPatches = async ({
|
||||
await execAsync(command);
|
||||
}
|
||||
};
|
||||
|
||||
interface GeneratePatchOptions {
|
||||
codePath: string;
|
||||
filePath: string;
|
||||
newContent: string;
|
||||
serverId?: string | null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a patch from modified file content using git diff
|
||||
*/
|
||||
export const generatePatch = async ({
|
||||
codePath,
|
||||
filePath,
|
||||
newContent,
|
||||
serverId,
|
||||
}: GeneratePatchOptions): Promise<string> => {
|
||||
const fullPath = join(codePath, filePath);
|
||||
|
||||
// Write new content to the file
|
||||
const encodedContent = Buffer.from(newContent).toString("base64");
|
||||
const writeCommand = `echo "${encodedContent}" | base64 -d > "${fullPath}"`;
|
||||
|
||||
if (serverId) {
|
||||
await execAsyncRemote(serverId, writeCommand);
|
||||
} else {
|
||||
await execAsync(writeCommand);
|
||||
}
|
||||
|
||||
// Generate diff
|
||||
const diffCommand = `cd "${codePath}" && git diff -- "${filePath}"`;
|
||||
|
||||
let diffResult: string;
|
||||
if (serverId) {
|
||||
const result = await execAsyncRemote(serverId, diffCommand);
|
||||
diffResult = result.stdout;
|
||||
} else {
|
||||
const result = await execAsync(diffCommand);
|
||||
diffResult = result.stdout;
|
||||
}
|
||||
|
||||
// Reset the file to original state
|
||||
const resetCommand = `cd "${codePath}" && git checkout -- "${filePath}"`;
|
||||
if (serverId) {
|
||||
await execAsyncRemote(serverId, resetCommand);
|
||||
} else {
|
||||
await execAsync(resetCommand);
|
||||
}
|
||||
|
||||
return diffResult;
|
||||
};
|
||||
|
||||
interface ApplyPatchToContentOptions {
|
||||
originalContent: string;
|
||||
patchContent: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply a patch to content in memory (for preview purposes)
|
||||
* Returns the patched content or throws an error if patch fails
|
||||
*/
|
||||
export const applyPatchToContent = async ({
|
||||
originalContent,
|
||||
patchContent,
|
||||
}: ApplyPatchToContentOptions): Promise<string> => {
|
||||
// Create temp files and apply patch
|
||||
const tempDir = "/tmp/patch_preview_" + Date.now();
|
||||
const tempFile = `${tempDir}/file`;
|
||||
const patchFile = `${tempDir}/patch.diff`;
|
||||
|
||||
const encodedOriginal = Buffer.from(originalContent).toString("base64");
|
||||
const encodedPatch = Buffer.from(patchContent).toString("base64");
|
||||
|
||||
const command = `
|
||||
mkdir -p "${tempDir}";
|
||||
echo "${encodedOriginal}" | base64 -d > "${tempFile}";
|
||||
echo "${encodedPatch}" | base64 -d > "${patchFile}";
|
||||
cd "${tempDir}" && patch -p0 < "${patchFile}" 2>/dev/null;
|
||||
cat "${tempFile}";
|
||||
rm -rf "${tempDir}";
|
||||
`;
|
||||
|
||||
try {
|
||||
const result = await execAsync(command);
|
||||
return result.stdout;
|
||||
} catch {
|
||||
throw new TRPCError({
|
||||
code: "BAD_REQUEST",
|
||||
message: "Failed to apply patch to content",
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
@@ -86,6 +86,7 @@ interface CloneBitbucketRepository {
|
||||
enableSubmodules: boolean;
|
||||
serverId: string | null;
|
||||
type?: "application" | "compose";
|
||||
outputPathOverride?: string;
|
||||
}
|
||||
|
||||
export const cloneBitbucketRepository = async ({
|
||||
@@ -101,6 +102,7 @@ export const cloneBitbucketRepository = async ({
|
||||
bitbucketId,
|
||||
enableSubmodules,
|
||||
serverId,
|
||||
outputPathOverride,
|
||||
} = entity;
|
||||
const { COMPOSE_PATH, APPLICATIONS_PATH } = paths(!!serverId);
|
||||
|
||||
@@ -115,7 +117,7 @@ export const cloneBitbucketRepository = async ({
|
||||
return command;
|
||||
}
|
||||
const basePath = type === "compose" ? COMPOSE_PATH : APPLICATIONS_PATH;
|
||||
const outputPath = join(basePath, appName, "code");
|
||||
const outputPath = outputPathOverride ?? join(basePath, appName, "code");
|
||||
command += `rm -rf ${outputPath};`;
|
||||
command += `mkdir -p ${outputPath};`;
|
||||
const repoToUse = entity.bitbucketRepositorySlug || bitbucketRepository;
|
||||
|
||||
@@ -14,6 +14,7 @@ interface CloneGitRepository {
|
||||
enableSubmodules?: boolean;
|
||||
serverId: string | null;
|
||||
type?: "application" | "compose";
|
||||
outputPathOverride?: string;
|
||||
}
|
||||
|
||||
export const cloneGitRepository = async ({
|
||||
@@ -28,6 +29,7 @@ export const cloneGitRepository = async ({
|
||||
customGitSSHKeyId,
|
||||
enableSubmodules,
|
||||
serverId,
|
||||
outputPathOverride,
|
||||
} = entity;
|
||||
const { SSH_PATH, COMPOSE_PATH, APPLICATIONS_PATH } = paths(!!serverId);
|
||||
|
||||
@@ -47,7 +49,7 @@ export const cloneGitRepository = async ({
|
||||
`;
|
||||
}
|
||||
const basePath = type === "compose" ? COMPOSE_PATH : APPLICATIONS_PATH;
|
||||
const outputPath = join(basePath, appName, "code");
|
||||
const outputPath = outputPathOverride ?? join(basePath, appName, "code");
|
||||
const knownHostsPath = path.join(SSH_PATH, "known_hosts");
|
||||
|
||||
if (!isHttpOrHttps(customGitUrl)) {
|
||||
|
||||
@@ -130,6 +130,7 @@ interface CloneGiteaRepository {
|
||||
enableSubmodules: boolean;
|
||||
serverId: string | null;
|
||||
type?: "application" | "compose";
|
||||
outputPathOverride?: string;
|
||||
}
|
||||
|
||||
export const cloneGiteaRepository = async ({
|
||||
@@ -145,6 +146,7 @@ export const cloneGiteaRepository = async ({
|
||||
giteaRepository,
|
||||
enableSubmodules,
|
||||
serverId,
|
||||
outputPathOverride,
|
||||
} = entity;
|
||||
const { APPLICATIONS_PATH, COMPOSE_PATH } = paths(!!serverId);
|
||||
|
||||
@@ -162,7 +164,7 @@ export const cloneGiteaRepository = async ({
|
||||
}
|
||||
|
||||
const basePath = type === "compose" ? COMPOSE_PATH : APPLICATIONS_PATH;
|
||||
const outputPath = join(basePath, appName, "code");
|
||||
const outputPath = outputPathOverride ?? join(basePath, appName, "code");
|
||||
command += `rm -rf ${outputPath};`;
|
||||
command += `mkdir -p ${outputPath};`;
|
||||
|
||||
|
||||
@@ -121,6 +121,7 @@ interface CloneGithubRepository {
|
||||
type?: "application" | "compose";
|
||||
enableSubmodules: boolean;
|
||||
serverId: string | null;
|
||||
outputPathOverride?: string;
|
||||
}
|
||||
export const cloneGithubRepository = async ({
|
||||
type = "application",
|
||||
@@ -136,6 +137,7 @@ export const cloneGithubRepository = async ({
|
||||
githubId,
|
||||
enableSubmodules,
|
||||
serverId,
|
||||
outputPathOverride,
|
||||
} = entity;
|
||||
const { APPLICATIONS_PATH, COMPOSE_PATH } = paths(!!serverId);
|
||||
|
||||
@@ -155,7 +157,7 @@ export const cloneGithubRepository = async ({
|
||||
|
||||
const githubProvider = await findGithubById(githubId);
|
||||
const basePath = isCompose ? COMPOSE_PATH : APPLICATIONS_PATH;
|
||||
const outputPath = join(basePath, appName, "code");
|
||||
const outputPath = outputPathOverride ?? join(basePath, appName, "code");
|
||||
const octokit = authGithub(githubProvider);
|
||||
const token = await getGithubToken(octokit);
|
||||
const repoclone = `github.com/${owner}/${repository}.git`;
|
||||
|
||||
@@ -107,6 +107,7 @@ interface CloneGitlabRepository {
|
||||
enableSubmodules: boolean;
|
||||
serverId: string | null;
|
||||
type?: "application" | "compose";
|
||||
outputPathOverride?: string;
|
||||
}
|
||||
|
||||
export const cloneGitlabRepository = async ({
|
||||
@@ -121,6 +122,7 @@ export const cloneGitlabRepository = async ({
|
||||
gitlabPathNamespace,
|
||||
enableSubmodules,
|
||||
serverId,
|
||||
outputPathOverride,
|
||||
} = entity;
|
||||
const { COMPOSE_PATH, APPLICATIONS_PATH } = paths(!!serverId);
|
||||
|
||||
@@ -141,7 +143,7 @@ export const cloneGitlabRepository = async ({
|
||||
}
|
||||
|
||||
const basePath = type === "compose" ? COMPOSE_PATH : APPLICATIONS_PATH;
|
||||
const outputPath = join(basePath, appName, "code");
|
||||
const outputPath = outputPathOverride ?? join(basePath, appName, "code");
|
||||
command += `rm -rf ${outputPath};`;
|
||||
command += `mkdir -p ${outputPath};`;
|
||||
const repoClone = getGitlabRepoClone(gitlab, gitlabPathNamespace);
|
||||
|
||||
Reference in New Issue
Block a user