fix: resolved merge conflicts with fork/canary

This commit is contained in:
Jason Parks
2025-03-16 03:02:15 -06:00
502 changed files with 18288 additions and 16475 deletions

View File

@@ -28,7 +28,6 @@ import {
getDokployImageTag,
getUpdateData,
initializeTraefik,
logRotationManager,
parseRawConfig,
paths,
prepareEnvironmentVariables,
@@ -42,10 +41,6 @@ import {
recreateDirectory,
sendDockerCleanupNotifications,
spawnAsync,
startService,
startServiceRemote,
stopService,
stopServiceRemote,
updateLetsEncryptEmail,
updateServerById,
updateServerTraefik,
@@ -53,6 +48,9 @@ import {
writeConfig,
writeMainConfig,
writeTraefikConfigInPath,
startLogCleanup,
stopLogCleanup,
getLogCleanupStatus,
} from "@dokploy/server";
import { checkGPUStatus, setupGPUSupport } from "@dokploy/server";
import { generateOpenApiDocument } from "@dokploy/trpc-openapi";
@@ -86,11 +84,9 @@ export const settingsRouter = createTRPCRouter({
.mutation(async ({ input }) => {
try {
if (input?.serverId) {
await stopServiceRemote(input.serverId, "dokploy-traefik");
await startServiceRemote(input.serverId, "dokploy-traefik");
await execAsync("docker restart dokploy-traefik");
} else if (!IS_CLOUD) {
await stopService("dokploy-traefik");
await startService("dokploy-traefik");
await execAsync("docker restart dokploy-traefik");
}
} catch (err) {
console.error(err);
@@ -101,13 +97,20 @@ export const settingsRouter = createTRPCRouter({
toggleDashboard: adminProcedure
.input(apiEnableDashboard)
.mutation(async ({ input }) => {
const ports = (await getTraefikPorts(input.serverId)).filter(
(port) =>
port.targetPort !== 80 &&
port.targetPort !== 443 &&
port.targetPort !== 8080,
);
await initializeTraefik({
additionalPorts: ports,
enableDashboard: input.enableDashboard,
serverId: input.serverId,
force: true,
});
return true;
}),
cleanUnusedImages: adminProcedure
.input(apiServerSchema)
.mutation(async ({ input }) => {
@@ -512,16 +515,18 @@ export const settingsRouter = createTRPCRouter({
.input(apiServerSchema)
.query(async ({ input }) => {
const command =
"docker service inspect --format='{{range .Spec.TaskTemplate.ContainerSpec.Env}}{{println .}}{{end}}' dokploy-traefik";
"docker container inspect dokploy-traefik --format '{{json .Config.Env}}'";
let result = "";
if (input?.serverId) {
const result = await execAsyncRemote(input.serverId, command);
return result.stdout.trim();
}
if (!IS_CLOUD) {
const result = await execAsync(command);
return result.stdout.trim();
const execResult = await execAsyncRemote(input.serverId, command);
result = execResult.stdout;
} else {
const execResult = await execAsync(command);
result = execResult.stdout;
}
const envVars = JSON.parse(result.trim());
return envVars.join("\n");
}),
writeTraefikEnv: adminProcedure
@@ -531,6 +536,7 @@ export const settingsRouter = createTRPCRouter({
await initializeTraefik({
env: envs,
serverId: input.serverId,
force: true,
});
return true;
@@ -538,27 +544,22 @@ export const settingsRouter = createTRPCRouter({
haveTraefikDashboardPortEnabled: adminProcedure
.input(apiServerSchema)
.query(async ({ input }) => {
const command = `docker service inspect --format='{{json .Endpoint.Ports}}' dokploy-traefik`;
const command = `docker container inspect --format='{{json .NetworkSettings.Ports}}' dokploy-traefik`;
let stdout = "";
if (input?.serverId) {
const result = await execAsyncRemote(input.serverId, command);
stdout = result.stdout;
} else if (!IS_CLOUD) {
const result = await execAsync(
"docker service inspect --format='{{json .Endpoint.Ports}}' dokploy-traefik",
);
const result = await execAsync(command);
stdout = result.stdout;
}
const parsed: any[] = JSON.parse(stdout.trim());
for (const port of parsed) {
if (port.PublishedPort === 8080) {
return true;
}
}
return false;
const ports = JSON.parse(stdout.trim());
return Object.entries(ports).some(([containerPort, bindings]) => {
const [port] = containerPort.split("/");
return port === "8080" && bindings && (bindings as any[]).length > 0;
});
}),
readStatsLogs: adminProcedure
@@ -578,48 +579,51 @@ export const settingsRouter = createTRPCRouter({
totalCount: 0,
};
}
const rawConfig = readMonitoringConfig();
const rawConfig = readMonitoringConfig(
!!input.dateRange?.start && !!input.dateRange?.end,
);
const parsedConfig = parseRawConfig(
rawConfig as string,
input.page,
input.sort,
input.search,
input.status,
input.dateRange,
);
return parsedConfig;
}),
readStats: adminProcedure.query(() => {
if (IS_CLOUD) {
return [];
}
const rawConfig = readMonitoringConfig();
const processedLogs = processLogs(rawConfig as string);
return processedLogs || [];
}),
getLogRotateStatus: adminProcedure.query(async () => {
if (IS_CLOUD) {
return true;
}
return await logRotationManager.getStatus();
}),
toggleLogRotate: adminProcedure
readStats: adminProcedure
.meta({
openapi: {
path: "/read-stats",
method: "POST",
override: true,
enabled: false,
},
})
.input(
z.object({
enable: z.boolean(),
}),
z
.object({
dateRange: z
.object({
start: z.string().optional(),
end: z.string().optional(),
})
.optional(),
})
.optional(),
)
.mutation(async ({ input }) => {
.query(({ input }) => {
if (IS_CLOUD) {
return true;
return [];
}
if (input.enable) {
await logRotationManager.activate();
} else {
await logRotationManager.deactivate();
}
return true;
const rawConfig = readMonitoringConfig(
!!input?.dateRange?.start || !!input?.dateRange?.end,
);
const processedLogs = processLogs(rawConfig as string, input?.dateRange);
return processedLogs || [];
}),
haveActivateRequests: adminProcedure.query(async () => {
if (IS_CLOUD) {
@@ -752,7 +756,6 @@ export const settingsRouter = createTRPCRouter({
z.object({
targetPort: z.number(),
publishedPort: z.number(),
publishMode: z.enum(["ingress", "host"]).default("host"),
}),
),
}),
@@ -768,6 +771,7 @@ export const settingsRouter = createTRPCRouter({
await initializeTraefik({
serverId: input.serverId,
additionalPorts: input.additionalPorts,
force: true,
});
return true;
} catch (error) {
@@ -784,47 +788,75 @@ export const settingsRouter = createTRPCRouter({
getTraefikPorts: adminProcedure
.input(apiServerSchema)
.query(async ({ input }) => {
const command = `docker service inspect --format='{{json .Endpoint.Ports}}' dokploy-traefik`;
return await getTraefikPorts(input?.serverId);
}),
updateLogCleanup: adminProcedure
.input(
z.object({
cronExpression: z.string().nullable(),
}),
)
.mutation(async ({ input }) => {
if (input.cronExpression) {
return startLogCleanup(input.cronExpression);
}
return stopLogCleanup();
}),
try {
let stdout = "";
if (input?.serverId) {
const result = await execAsyncRemote(input.serverId, command);
stdout = result.stdout;
} else if (!IS_CLOUD) {
const result = await execAsync(command);
stdout = result.stdout;
}
getLogCleanupStatus: adminProcedure.query(async () => {
return getLogCleanupStatus();
}),
});
const ports: {
Protocol: string;
TargetPort: number;
PublishedPort: number;
PublishMode: string;
}[] = JSON.parse(stdout.trim());
export const getTraefikPorts = async (serverId?: string) => {
const command = `docker container inspect --format='{{json .NetworkSettings.Ports}}' dokploy-traefik`;
try {
let stdout = "";
if (serverId) {
const result = await execAsyncRemote(serverId, command);
stdout = result.stdout;
} else if (!IS_CLOUD) {
const result = await execAsync(command);
stdout = result.stdout;
}
// Filter out the default ports (80, 443, and optionally 8080)
const additionalPorts = ports
.filter((port) => ![80, 443, 8080].includes(port.PublishedPort))
.map((port) => ({
targetPort: port.TargetPort,
publishedPort: port.PublishedPort,
publishMode: port.PublishMode.toLowerCase() as "host" | "ingress",
}));
const portsMap = JSON.parse(stdout.trim());
const additionalPorts: Array<{
targetPort: number;
publishedPort: number;
}> = [];
return additionalPorts;
} catch (error) {
throw new TRPCError({
code: "INTERNAL_SERVER_ERROR",
message: "Failed to get Traefik ports",
cause: error,
// Convert the Docker container port format to our expected format
for (const [containerPort, bindings] of Object.entries(portsMap)) {
if (!bindings) continue;
const [port = ""] = containerPort.split("/");
if (!port) continue;
const targetPortNum = Number.parseInt(port, 10);
if (Number.isNaN(targetPortNum)) continue;
// Skip default ports
if ([80, 443].includes(targetPortNum)) continue;
for (const binding of bindings as Array<{ HostPort: string }>) {
if (!binding.HostPort) continue;
const publishedPort = Number.parseInt(binding.HostPort, 10);
if (Number.isNaN(publishedPort)) continue;
additionalPorts.push({
targetPort: targetPortNum,
publishedPort,
});
}
}),
});
// {
// "Parallelism": 1,
// "Delay": 10000000000,
// "FailureAction": "rollback",
// "Order": "start-first"
// }
}
return additionalPorts;
} catch (error) {
throw new TRPCError({
code: "INTERNAL_SERVER_ERROR",
message: "Failed to get Traefik ports",
cause: error,
});
}
};