mirror of
https://github.com/Dokploy/dokploy.git
synced 2026-07-05 22:15:22 +02:00
Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
75fc030984 | ||
|
|
060a170aee | ||
|
|
40718293a1 | ||
|
|
9ac68985e0 | ||
|
|
35ff8dcfe6 |
@@ -267,6 +267,28 @@ export const ShowGeneralApplication = ({ applicationId }: Props) => {
|
|||||||
className="flex flex-row gap-2 items-center"
|
className="flex flex-row gap-2 items-center"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div className="flex flex-row items-center gap-2 rounded-md px-4 py-2 border">
|
||||||
|
<span className="text-sm font-medium">Clean Cache</span>
|
||||||
|
<Switch
|
||||||
|
aria-label="Toggle italic"
|
||||||
|
checked={data?.cleanCache || false}
|
||||||
|
onCheckedChange={async (enabled) => {
|
||||||
|
await update({
|
||||||
|
applicationId,
|
||||||
|
cleanCache: enabled,
|
||||||
|
})
|
||||||
|
.then(async () => {
|
||||||
|
toast.success("Clean Cache Updated");
|
||||||
|
await refetch();
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
toast.error("Error updating Clean Cache");
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
className="flex flex-row gap-2 items-center"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
<ShowProviderForm applicationId={applicationId} />
|
<ShowProviderForm applicationId={applicationId} />
|
||||||
|
|||||||
@@ -13,7 +13,11 @@ import Link from "next/link";
|
|||||||
import { AddManager } from "./manager/add-manager";
|
import { AddManager } from "./manager/add-manager";
|
||||||
import { AddWorker } from "./workers/add-worker";
|
import { AddWorker } from "./workers/add-worker";
|
||||||
|
|
||||||
export const AddNode = () => {
|
interface Props {
|
||||||
|
serverId?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const AddNode = ({ serverId }: Props) => {
|
||||||
return (
|
return (
|
||||||
<Dialog>
|
<Dialog>
|
||||||
<DialogTrigger asChild>
|
<DialogTrigger asChild>
|
||||||
@@ -53,10 +57,10 @@ export const AddNode = () => {
|
|||||||
<TabsTrigger value="manager">Manager</TabsTrigger>
|
<TabsTrigger value="manager">Manager</TabsTrigger>
|
||||||
</TabsList>
|
</TabsList>
|
||||||
<TabsContent value="worker" className="pt-4">
|
<TabsContent value="worker" className="pt-4">
|
||||||
<AddWorker />
|
<AddWorker serverId={serverId} />
|
||||||
</TabsContent>
|
</TabsContent>
|
||||||
<TabsContent value="manager" className="pt-4">
|
<TabsContent value="manager" className="pt-4">
|
||||||
<AddManager />
|
<AddManager serverId={serverId} />
|
||||||
</TabsContent>
|
</TabsContent>
|
||||||
</Tabs>
|
</Tabs>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -9,8 +9,12 @@ import copy from "copy-to-clipboard";
|
|||||||
import { CopyIcon } from "lucide-react";
|
import { CopyIcon } from "lucide-react";
|
||||||
import { toast } from "sonner";
|
import { toast } from "sonner";
|
||||||
|
|
||||||
export const AddManager = () => {
|
interface Props {
|
||||||
const { data } = api.cluster.addManager.useQuery();
|
serverId?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const AddManager = ({ serverId }: Props) => {
|
||||||
|
const { data } = api.cluster.addManager.useQuery({ serverId });
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
import { Dialog, DialogContent, DialogTrigger } from "@/components/ui/dialog";
|
||||||
|
import { DropdownMenuItem } from "@/components/ui/dropdown-menu";
|
||||||
|
import { useState } from "react";
|
||||||
|
import { ShowNodes } from "./show-nodes";
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
serverId: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const ShowNodesModal = ({ serverId }: Props) => {
|
||||||
|
const [isOpen, setIsOpen] = useState(false);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Dialog open={isOpen} onOpenChange={setIsOpen}>
|
||||||
|
<DialogTrigger asChild>
|
||||||
|
<DropdownMenuItem
|
||||||
|
className="w-full cursor-pointer "
|
||||||
|
onSelect={(e) => e.preventDefault()}
|
||||||
|
>
|
||||||
|
Show Nodes
|
||||||
|
</DropdownMenuItem>
|
||||||
|
</DialogTrigger>
|
||||||
|
<DialogContent className="sm:max-w-5xl overflow-y-auto max-h-screen ">
|
||||||
|
<div className="grid w-full gap-1">
|
||||||
|
<ShowNodes serverId={serverId} />
|
||||||
|
</div>
|
||||||
|
</DialogContent>
|
||||||
|
</Dialog>
|
||||||
|
);
|
||||||
|
};
|
||||||
@@ -32,13 +32,25 @@ import {
|
|||||||
TooltipTrigger,
|
TooltipTrigger,
|
||||||
} from "@/components/ui/tooltip";
|
} from "@/components/ui/tooltip";
|
||||||
import { api } from "@/utils/api";
|
import { api } from "@/utils/api";
|
||||||
import { Boxes, HelpCircle, LockIcon, MoreHorizontal } from "lucide-react";
|
import {
|
||||||
|
Boxes,
|
||||||
|
HelpCircle,
|
||||||
|
LockIcon,
|
||||||
|
MoreHorizontal,
|
||||||
|
Loader2,
|
||||||
|
} from "lucide-react";
|
||||||
import { toast } from "sonner";
|
import { toast } from "sonner";
|
||||||
import { AddNode } from "./add-node";
|
import { AddNode } from "./add-node";
|
||||||
import { ShowNodeData } from "./show-node-data";
|
import { ShowNodeData } from "./show-node-data";
|
||||||
|
|
||||||
export const ShowNodes = () => {
|
interface Props {
|
||||||
const { data, isLoading, refetch } = api.cluster.getNodes.useQuery();
|
serverId?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const ShowNodes = ({ serverId }: Props) => {
|
||||||
|
const { data, isLoading, refetch } = api.cluster.getNodes.useQuery({
|
||||||
|
serverId,
|
||||||
|
});
|
||||||
const { data: registry } = api.registry.all.useQuery();
|
const { data: registry } = api.registry.all.useQuery();
|
||||||
|
|
||||||
const { mutateAsync: deleteNode } = api.cluster.removeWorker.useMutation();
|
const { mutateAsync: deleteNode } = api.cluster.removeWorker.useMutation();
|
||||||
@@ -58,14 +70,17 @@ export const ShowNodes = () => {
|
|||||||
</div>
|
</div>
|
||||||
{haveAtLeastOneRegistry && (
|
{haveAtLeastOneRegistry && (
|
||||||
<div className="flex flex-row gap-2">
|
<div className="flex flex-row gap-2">
|
||||||
<AddNode />
|
<AddNode serverId={serverId} />
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent className="space-y-2 py-8 border-t min-h-[35vh]">
|
<CardContent className="space-y-2 py-8 border-t min-h-[35vh]">
|
||||||
{haveAtLeastOneRegistry ? (
|
{isLoading ? (
|
||||||
|
<div className="flex items-center justify-center w-full h-[40vh]">
|
||||||
|
<Loader2 className="size-8 animate-spin text-muted-foreground" />
|
||||||
|
</div>
|
||||||
|
) : haveAtLeastOneRegistry ? (
|
||||||
<div className="grid md:grid-cols-1 gap-4">
|
<div className="grid md:grid-cols-1 gap-4">
|
||||||
{isLoading && <div>Loading...</div>}
|
|
||||||
<Table>
|
<Table>
|
||||||
<TableCaption>
|
<TableCaption>
|
||||||
A list of your managers / workers.
|
A list of your managers / workers.
|
||||||
@@ -137,6 +152,7 @@ export const ShowNodes = () => {
|
|||||||
onClick={async () => {
|
onClick={async () => {
|
||||||
await deleteNode({
|
await deleteNode({
|
||||||
nodeId: node.ID,
|
nodeId: node.ID,
|
||||||
|
serverId,
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
refetch();
|
refetch();
|
||||||
|
|||||||
@@ -9,8 +9,12 @@ import copy from "copy-to-clipboard";
|
|||||||
import { CopyIcon } from "lucide-react";
|
import { CopyIcon } from "lucide-react";
|
||||||
import { toast } from "sonner";
|
import { toast } from "sonner";
|
||||||
|
|
||||||
export const AddWorker = () => {
|
interface Props {
|
||||||
const { data } = api.cluster.addWorker.useQuery();
|
serverId?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const AddWorker = ({ serverId }: Props) => {
|
||||||
|
const { data } = api.cluster.addWorker.useQuery({ serverId });
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ import { ShowMonitoringModal } from "./show-monitoring-modal";
|
|||||||
import { ShowSwarmOverviewModal } from "./show-swarm-overview-modal";
|
import { ShowSwarmOverviewModal } from "./show-swarm-overview-modal";
|
||||||
import { ShowTraefikFileSystemModal } from "./show-traefik-file-system-modal";
|
import { ShowTraefikFileSystemModal } from "./show-traefik-file-system-modal";
|
||||||
import { WelcomeSuscription } from "./welcome-stripe/welcome-suscription";
|
import { WelcomeSuscription } from "./welcome-stripe/welcome-suscription";
|
||||||
|
import { ShowNodesModal } from "../cluster/nodes/show-nodes-modal";
|
||||||
|
|
||||||
export const ShowServers = () => {
|
export const ShowServers = () => {
|
||||||
const { t } = useTranslation("settings");
|
const { t } = useTranslation("settings");
|
||||||
@@ -328,6 +329,9 @@ export const ShowServers = () => {
|
|||||||
<ShowSwarmOverviewModal
|
<ShowSwarmOverviewModal
|
||||||
serverId={server.serverId}
|
serverId={server.serverId}
|
||||||
/>
|
/>
|
||||||
|
<ShowNodesModal
|
||||||
|
serverId={server.serverId}
|
||||||
|
/>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</DropdownMenuContent>
|
</DropdownMenuContent>
|
||||||
|
|||||||
1
apps/dokploy/drizzle/0078_uneven_omega_sentinel.sql
Normal file
1
apps/dokploy/drizzle/0078_uneven_omega_sentinel.sql
Normal file
@@ -0,0 +1 @@
|
|||||||
|
ALTER TABLE "application" ADD COLUMN "cleanCache" boolean DEFAULT false;
|
||||||
5163
apps/dokploy/drizzle/meta/0078_snapshot.json
Normal file
5163
apps/dokploy/drizzle/meta/0078_snapshot.json
Normal file
File diff suppressed because it is too large
Load Diff
@@ -547,6 +547,13 @@
|
|||||||
"when": 1741510086231,
|
"when": 1741510086231,
|
||||||
"tag": "0077_chemical_dreadnoughts",
|
"tag": "0077_chemical_dreadnoughts",
|
||||||
"breakpoints": true
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 78,
|
||||||
|
"version": "7",
|
||||||
|
"when": 1742112194375,
|
||||||
|
"tag": "0078_uneven_omega_sentinel",
|
||||||
|
"breakpoints": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "dokploy",
|
"name": "dokploy",
|
||||||
"version": "v0.20.3",
|
"version": "v0.20.4",
|
||||||
"private": true,
|
"private": true,
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
|
|||||||
@@ -1,22 +1,35 @@
|
|||||||
import { getPublicIpWithFallback } from "@/server/wss/terminal";
|
import { getPublicIpWithFallback } from "@/server/wss/terminal";
|
||||||
import { type DockerNode, IS_CLOUD, docker, execAsync } from "@dokploy/server";
|
import {
|
||||||
|
type DockerNode,
|
||||||
|
IS_CLOUD,
|
||||||
|
execAsync,
|
||||||
|
getRemoteDocker,
|
||||||
|
} from "@dokploy/server";
|
||||||
import { TRPCError } from "@trpc/server";
|
import { TRPCError } from "@trpc/server";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { createTRPCRouter, protectedProcedure } from "../trpc";
|
import { createTRPCRouter, protectedProcedure } from "../trpc";
|
||||||
|
|
||||||
export const clusterRouter = createTRPCRouter({
|
export const clusterRouter = createTRPCRouter({
|
||||||
getNodes: protectedProcedure.query(async () => {
|
getNodes: protectedProcedure
|
||||||
if (IS_CLOUD) {
|
.input(
|
||||||
return [];
|
z.object({
|
||||||
}
|
serverId: z.string().optional(),
|
||||||
const workers: DockerNode[] = await docker.listNodes();
|
}),
|
||||||
|
)
|
||||||
|
.query(async ({ input }) => {
|
||||||
|
if (IS_CLOUD) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
return workers;
|
const docker = await getRemoteDocker(input.serverId);
|
||||||
}),
|
const workers: DockerNode[] = await docker.listNodes();
|
||||||
|
|
||||||
|
return workers;
|
||||||
|
}),
|
||||||
removeWorker: protectedProcedure
|
removeWorker: protectedProcedure
|
||||||
.input(
|
.input(
|
||||||
z.object({
|
z.object({
|
||||||
nodeId: z.string(),
|
nodeId: z.string(),
|
||||||
|
serverId: z.string().optional(),
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
.mutation(async ({ input }) => {
|
.mutation(async ({ input }) => {
|
||||||
@@ -40,37 +53,51 @@ export const clusterRouter = createTRPCRouter({
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
addWorker: protectedProcedure.query(async () => {
|
addWorker: protectedProcedure
|
||||||
if (IS_CLOUD) {
|
.input(
|
||||||
return {
|
z.object({
|
||||||
command: "",
|
serverId: z.string().optional(),
|
||||||
version: "",
|
}),
|
||||||
};
|
)
|
||||||
}
|
.query(async ({ input }) => {
|
||||||
const result = await docker.swarmInspect();
|
if (IS_CLOUD) {
|
||||||
const docker_version = await docker.version();
|
return {
|
||||||
|
command: "",
|
||||||
|
version: "",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
const docker = await getRemoteDocker(input.serverId);
|
||||||
|
const result = await docker.swarmInspect();
|
||||||
|
const docker_version = await docker.version();
|
||||||
|
|
||||||
return {
|
|
||||||
command: `docker swarm join --token ${
|
|
||||||
result.JoinTokens.Worker
|
|
||||||
} ${await getPublicIpWithFallback()}:2377`,
|
|
||||||
version: docker_version.Version,
|
|
||||||
};
|
|
||||||
}),
|
|
||||||
addManager: protectedProcedure.query(async () => {
|
|
||||||
if (IS_CLOUD) {
|
|
||||||
return {
|
return {
|
||||||
command: "",
|
command: `docker swarm join --token ${
|
||||||
version: "",
|
result.JoinTokens.Worker
|
||||||
|
} ${await getPublicIpWithFallback()}:2377`,
|
||||||
|
version: docker_version.Version,
|
||||||
};
|
};
|
||||||
}
|
}),
|
||||||
const result = await docker.swarmInspect();
|
addManager: protectedProcedure
|
||||||
const docker_version = await docker.version();
|
.input(
|
||||||
return {
|
z.object({
|
||||||
command: `docker swarm join --token ${
|
serverId: z.string().optional(),
|
||||||
result.JoinTokens.Manager
|
}),
|
||||||
} ${await getPublicIpWithFallback()}:2377`,
|
)
|
||||||
version: docker_version.Version,
|
.query(async ({ input }) => {
|
||||||
};
|
if (IS_CLOUD) {
|
||||||
}),
|
return {
|
||||||
|
command: "",
|
||||||
|
version: "",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
const docker = await getRemoteDocker(input.serverId);
|
||||||
|
const result = await docker.swarmInspect();
|
||||||
|
const docker_version = await docker.version();
|
||||||
|
return {
|
||||||
|
command: `docker swarm join --token ${
|
||||||
|
result.JoinTokens.Manager
|
||||||
|
} ${await getPublicIpWithFallback()}:2377`,
|
||||||
|
version: docker_version.Version,
|
||||||
|
};
|
||||||
|
}),
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -141,6 +141,7 @@ export const applications = pgTable("application", {
|
|||||||
command: text("command"),
|
command: text("command"),
|
||||||
refreshToken: text("refreshToken").$defaultFn(() => nanoid()),
|
refreshToken: text("refreshToken").$defaultFn(() => nanoid()),
|
||||||
sourceType: sourceType("sourceType").notNull().default("github"),
|
sourceType: sourceType("sourceType").notNull().default("github"),
|
||||||
|
cleanCache: boolean("cleanCache").default(false),
|
||||||
// Github
|
// Github
|
||||||
repository: text("repository"),
|
repository: text("repository"),
|
||||||
owner: text("owner"),
|
owner: text("owner"),
|
||||||
@@ -408,6 +409,7 @@ const createSchema = createInsertSchema(applications, {
|
|||||||
previewPath: z.string().optional(),
|
previewPath: z.string().optional(),
|
||||||
previewCertificateType: z.enum(["letsencrypt", "none", "custom"]).optional(),
|
previewCertificateType: z.enum(["letsencrypt", "none", "custom"]).optional(),
|
||||||
watchPaths: z.array(z.string()).optional(),
|
watchPaths: z.array(z.string()).optional(),
|
||||||
|
cleanCache: z.boolean().optional(),
|
||||||
});
|
});
|
||||||
|
|
||||||
export const apiCreateApplication = createSchema.pick({
|
export const apiCreateApplication = createSchema.pick({
|
||||||
|
|||||||
@@ -159,6 +159,7 @@ table application {
|
|||||||
command text
|
command text
|
||||||
refreshToken text
|
refreshToken text
|
||||||
sourceType sourceType [not null, default: 'github']
|
sourceType sourceType [not null, default: 'github']
|
||||||
|
cleanCache boolean [default: false]
|
||||||
repository text
|
repository text
|
||||||
owner text
|
owner text
|
||||||
branch text
|
branch text
|
||||||
|
|||||||
@@ -182,12 +182,6 @@ export const deployApplication = async ({
|
|||||||
});
|
});
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// const admin = await findUserById(application.project.userId);
|
|
||||||
|
|
||||||
// if (admin.cleanupCacheApplications) {
|
|
||||||
// await cleanupFullDocker(application?.serverId);
|
|
||||||
// }
|
|
||||||
|
|
||||||
if (application.sourceType === "github") {
|
if (application.sourceType === "github") {
|
||||||
await cloneGithubRepository({
|
await cloneGithubRepository({
|
||||||
...application,
|
...application,
|
||||||
@@ -257,11 +251,6 @@ export const rebuildApplication = async ({
|
|||||||
});
|
});
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// const admin = await findUserById(application.project.userId);
|
|
||||||
|
|
||||||
// if (admin.cleanupCacheApplications) {
|
|
||||||
// await cleanupFullDocker(application?.serverId);
|
|
||||||
// }
|
|
||||||
if (application.sourceType === "github") {
|
if (application.sourceType === "github") {
|
||||||
await buildApplication(application, deployment.logPath);
|
await buildApplication(application, deployment.logPath);
|
||||||
} else if (application.sourceType === "gitlab") {
|
} else if (application.sourceType === "gitlab") {
|
||||||
@@ -306,11 +295,6 @@ export const deployRemoteApplication = async ({
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
if (application.serverId) {
|
if (application.serverId) {
|
||||||
// const admin = await findUserById(application.project.userId);
|
|
||||||
|
|
||||||
// if (admin.cleanupCacheApplications) {
|
|
||||||
// await cleanupFullDocker(application?.serverId);
|
|
||||||
// }
|
|
||||||
let command = "set -e;";
|
let command = "set -e;";
|
||||||
if (application.sourceType === "github") {
|
if (application.sourceType === "github") {
|
||||||
command += await getGithubCloneCommand({
|
command += await getGithubCloneCommand({
|
||||||
@@ -451,12 +435,6 @@ export const deployPreviewApplication = async ({
|
|||||||
application.env = `${application.previewEnv}\nDOKPLOY_DEPLOY_URL=${previewDeployment?.domain?.host}`;
|
application.env = `${application.previewEnv}\nDOKPLOY_DEPLOY_URL=${previewDeployment?.domain?.host}`;
|
||||||
application.buildArgs = application.previewBuildArgs;
|
application.buildArgs = application.previewBuildArgs;
|
||||||
|
|
||||||
// const admin = await findUserById(application.project.userId);
|
|
||||||
|
|
||||||
// if (admin.cleanupCacheOnPreviews) {
|
|
||||||
// await cleanupFullDocker(application?.serverId);
|
|
||||||
// }
|
|
||||||
|
|
||||||
if (application.sourceType === "github") {
|
if (application.sourceType === "github") {
|
||||||
await cloneGithubRepository({
|
await cloneGithubRepository({
|
||||||
...application,
|
...application,
|
||||||
@@ -565,11 +543,6 @@ export const deployRemotePreviewApplication = async ({
|
|||||||
application.buildArgs = application.previewBuildArgs;
|
application.buildArgs = application.previewBuildArgs;
|
||||||
|
|
||||||
if (application.serverId) {
|
if (application.serverId) {
|
||||||
// const admin = await findUserById(application.project.userId);
|
|
||||||
|
|
||||||
// if (admin.cleanupCacheOnPreviews) {
|
|
||||||
// await cleanupFullDocker(application?.serverId);
|
|
||||||
// }
|
|
||||||
let command = "set -e;";
|
let command = "set -e;";
|
||||||
if (application.sourceType === "github") {
|
if (application.sourceType === "github") {
|
||||||
command += await getGithubCloneCommand({
|
command += await getGithubCloneCommand({
|
||||||
@@ -634,11 +607,6 @@ export const rebuildRemoteApplication = async ({
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
if (application.serverId) {
|
if (application.serverId) {
|
||||||
// const admin = await findUserById(application.project.userId);
|
|
||||||
|
|
||||||
// if (admin.cleanupCacheApplications) {
|
|
||||||
// await cleanupFullDocker(application?.serverId);
|
|
||||||
// }
|
|
||||||
if (application.sourceType !== "docker") {
|
if (application.sourceType !== "docker") {
|
||||||
let command = "set -e;";
|
let command = "set -e;";
|
||||||
command += getBuildCommand(application, deployment.logPath);
|
command += getBuildCommand(application, deployment.logPath);
|
||||||
|
|||||||
@@ -216,10 +216,6 @@ export const deployCompose = async ({
|
|||||||
});
|
});
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// const admin = await findUserById(compose.project.userId);
|
|
||||||
// if (admin.cleanupCacheOnCompose) {
|
|
||||||
// await cleanupFullDocker(compose?.serverId);
|
|
||||||
// }
|
|
||||||
if (compose.sourceType === "github") {
|
if (compose.sourceType === "github") {
|
||||||
await cloneGithubRepository({
|
await cloneGithubRepository({
|
||||||
...compose,
|
...compose,
|
||||||
@@ -285,11 +281,6 @@ export const rebuildCompose = async ({
|
|||||||
});
|
});
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// const admin = await findUserById(compose.project.userId);
|
|
||||||
// if (admin.cleanupCacheOnCompose) {
|
|
||||||
// await cleanupFullDocker(compose?.serverId);
|
|
||||||
// }
|
|
||||||
|
|
||||||
if (compose.sourceType === "raw") {
|
if (compose.sourceType === "raw") {
|
||||||
await createComposeFile(compose, deployment.logPath);
|
await createComposeFile(compose, deployment.logPath);
|
||||||
}
|
}
|
||||||
@@ -331,10 +322,6 @@ export const deployRemoteCompose = async ({
|
|||||||
});
|
});
|
||||||
try {
|
try {
|
||||||
if (compose.serverId) {
|
if (compose.serverId) {
|
||||||
// const admin = await findUserById(compose.project.userId);
|
|
||||||
// if (admin.cleanupCacheOnCompose) {
|
|
||||||
// await cleanupFullDocker(compose?.serverId);
|
|
||||||
// }
|
|
||||||
let command = "set -e;";
|
let command = "set -e;";
|
||||||
|
|
||||||
if (compose.sourceType === "github") {
|
if (compose.sourceType === "github") {
|
||||||
@@ -429,10 +416,6 @@ export const rebuildRemoteCompose = async ({
|
|||||||
});
|
});
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// const admin = await findUserById(compose.project.userId);
|
|
||||||
// if (admin.cleanupCacheOnCompose) {
|
|
||||||
// await cleanupFullDocker(compose?.serverId);
|
|
||||||
// }
|
|
||||||
if (compose.sourceType === "raw") {
|
if (compose.sourceType === "raw") {
|
||||||
const command = getCreateComposeFileCommand(compose, deployment.logPath);
|
const command = getCreateComposeFileCommand(compose, deployment.logPath);
|
||||||
await execAsyncRemote(compose.serverId, command);
|
await execAsyncRemote(compose.serverId, command);
|
||||||
|
|||||||
@@ -12,8 +12,14 @@ export const buildCustomDocker = async (
|
|||||||
application: ApplicationNested,
|
application: ApplicationNested,
|
||||||
writeStream: WriteStream,
|
writeStream: WriteStream,
|
||||||
) => {
|
) => {
|
||||||
const { appName, env, publishDirectory, buildArgs, dockerBuildStage } =
|
const {
|
||||||
application;
|
appName,
|
||||||
|
env,
|
||||||
|
publishDirectory,
|
||||||
|
buildArgs,
|
||||||
|
dockerBuildStage,
|
||||||
|
cleanCache,
|
||||||
|
} = application;
|
||||||
const dockerFilePath = getBuildAppDirectory(application);
|
const dockerFilePath = getBuildAppDirectory(application);
|
||||||
try {
|
try {
|
||||||
const image = `${appName}`;
|
const image = `${appName}`;
|
||||||
@@ -29,6 +35,10 @@ export const buildCustomDocker = async (
|
|||||||
|
|
||||||
const commandArgs = ["build", "-t", image, "-f", dockerFilePath, "."];
|
const commandArgs = ["build", "-t", image, "-f", dockerFilePath, "."];
|
||||||
|
|
||||||
|
if (cleanCache) {
|
||||||
|
commandArgs.push("--no-cache");
|
||||||
|
}
|
||||||
|
|
||||||
if (dockerBuildStage) {
|
if (dockerBuildStage) {
|
||||||
commandArgs.push("--target", dockerBuildStage);
|
commandArgs.push("--target", dockerBuildStage);
|
||||||
}
|
}
|
||||||
@@ -65,8 +75,14 @@ export const getDockerCommand = (
|
|||||||
application: ApplicationNested,
|
application: ApplicationNested,
|
||||||
logPath: string,
|
logPath: string,
|
||||||
) => {
|
) => {
|
||||||
const { appName, env, publishDirectory, buildArgs, dockerBuildStage } =
|
const {
|
||||||
application;
|
appName,
|
||||||
|
env,
|
||||||
|
publishDirectory,
|
||||||
|
buildArgs,
|
||||||
|
dockerBuildStage,
|
||||||
|
cleanCache,
|
||||||
|
} = application;
|
||||||
const dockerFilePath = getBuildAppDirectory(application);
|
const dockerFilePath = getBuildAppDirectory(application);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -88,6 +104,10 @@ export const getDockerCommand = (
|
|||||||
commandArgs.push("--target", dockerBuildStage);
|
commandArgs.push("--target", dockerBuildStage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (cleanCache) {
|
||||||
|
commandArgs.push("--no-cache");
|
||||||
|
}
|
||||||
|
|
||||||
for (const arg of args) {
|
for (const arg of args) {
|
||||||
commandArgs.push("--build-arg", arg);
|
commandArgs.push("--build-arg", arg);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ export const buildHeroku = async (
|
|||||||
application: ApplicationNested,
|
application: ApplicationNested,
|
||||||
writeStream: WriteStream,
|
writeStream: WriteStream,
|
||||||
) => {
|
) => {
|
||||||
const { env, appName } = application;
|
const { env, appName, cleanCache } = application;
|
||||||
const buildAppDirectory = getBuildAppDirectory(application);
|
const buildAppDirectory = getBuildAppDirectory(application);
|
||||||
const envVariables = prepareEnvironmentVariables(
|
const envVariables = prepareEnvironmentVariables(
|
||||||
env,
|
env,
|
||||||
@@ -29,6 +29,10 @@ export const buildHeroku = async (
|
|||||||
args.push("--env", env);
|
args.push("--env", env);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (cleanCache) {
|
||||||
|
args.push("--clear-cache");
|
||||||
|
}
|
||||||
|
|
||||||
await spawnAsync("pack", args, (data) => {
|
await spawnAsync("pack", args, (data) => {
|
||||||
if (writeStream.writable) {
|
if (writeStream.writable) {
|
||||||
writeStream.write(data);
|
writeStream.write(data);
|
||||||
@@ -44,7 +48,7 @@ export const getHerokuCommand = (
|
|||||||
application: ApplicationNested,
|
application: ApplicationNested,
|
||||||
logPath: string,
|
logPath: string,
|
||||||
) => {
|
) => {
|
||||||
const { env, appName } = application;
|
const { env, appName, cleanCache } = application;
|
||||||
|
|
||||||
const buildAppDirectory = getBuildAppDirectory(application);
|
const buildAppDirectory = getBuildAppDirectory(application);
|
||||||
const envVariables = prepareEnvironmentVariables(
|
const envVariables = prepareEnvironmentVariables(
|
||||||
@@ -61,6 +65,10 @@ export const getHerokuCommand = (
|
|||||||
`heroku/builder:${application.herokuVersion || "24"}`,
|
`heroku/builder:${application.herokuVersion || "24"}`,
|
||||||
];
|
];
|
||||||
|
|
||||||
|
if (cleanCache) {
|
||||||
|
args.push("--clear-cache");
|
||||||
|
}
|
||||||
|
|
||||||
for (const env of envVariables) {
|
for (const env of envVariables) {
|
||||||
args.push("--env", `'${env}'`);
|
args.push("--env", `'${env}'`);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ export const buildNixpacks = async (
|
|||||||
application: ApplicationNested,
|
application: ApplicationNested,
|
||||||
writeStream: WriteStream,
|
writeStream: WriteStream,
|
||||||
) => {
|
) => {
|
||||||
const { env, appName, publishDirectory } = application;
|
const { env, appName, publishDirectory, cleanCache } = application;
|
||||||
|
|
||||||
const buildAppDirectory = getBuildAppDirectory(application);
|
const buildAppDirectory = getBuildAppDirectory(application);
|
||||||
const buildContainerId = `${appName}-${nanoid(10)}`;
|
const buildContainerId = `${appName}-${nanoid(10)}`;
|
||||||
@@ -32,6 +32,10 @@ export const buildNixpacks = async (
|
|||||||
try {
|
try {
|
||||||
const args = ["build", buildAppDirectory, "--name", appName];
|
const args = ["build", buildAppDirectory, "--name", appName];
|
||||||
|
|
||||||
|
if (cleanCache) {
|
||||||
|
args.push("--no-cache");
|
||||||
|
}
|
||||||
|
|
||||||
for (const env of envVariables) {
|
for (const env of envVariables) {
|
||||||
args.push("--env", env);
|
args.push("--env", env);
|
||||||
}
|
}
|
||||||
@@ -91,7 +95,7 @@ export const getNixpacksCommand = (
|
|||||||
application: ApplicationNested,
|
application: ApplicationNested,
|
||||||
logPath: string,
|
logPath: string,
|
||||||
) => {
|
) => {
|
||||||
const { env, appName, publishDirectory } = application;
|
const { env, appName, publishDirectory, cleanCache } = application;
|
||||||
|
|
||||||
const buildAppDirectory = getBuildAppDirectory(application);
|
const buildAppDirectory = getBuildAppDirectory(application);
|
||||||
const buildContainerId = `${appName}-${nanoid(10)}`;
|
const buildContainerId = `${appName}-${nanoid(10)}`;
|
||||||
@@ -102,6 +106,10 @@ export const getNixpacksCommand = (
|
|||||||
|
|
||||||
const args = ["build", buildAppDirectory, "--name", appName];
|
const args = ["build", buildAppDirectory, "--name", appName];
|
||||||
|
|
||||||
|
if (cleanCache) {
|
||||||
|
args.push("--no-cache");
|
||||||
|
}
|
||||||
|
|
||||||
for (const env of envVariables) {
|
for (const env of envVariables) {
|
||||||
args.push("--env", `'${env}'`);
|
args.push("--env", `'${env}'`);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ export const buildPaketo = async (
|
|||||||
application: ApplicationNested,
|
application: ApplicationNested,
|
||||||
writeStream: WriteStream,
|
writeStream: WriteStream,
|
||||||
) => {
|
) => {
|
||||||
const { env, appName } = application;
|
const { env, appName, cleanCache } = application;
|
||||||
const buildAppDirectory = getBuildAppDirectory(application);
|
const buildAppDirectory = getBuildAppDirectory(application);
|
||||||
const envVariables = prepareEnvironmentVariables(
|
const envVariables = prepareEnvironmentVariables(
|
||||||
env,
|
env,
|
||||||
@@ -24,6 +24,10 @@ export const buildPaketo = async (
|
|||||||
"paketobuildpacks/builder-jammy-full",
|
"paketobuildpacks/builder-jammy-full",
|
||||||
];
|
];
|
||||||
|
|
||||||
|
if (cleanCache) {
|
||||||
|
args.push("--clear-cache");
|
||||||
|
}
|
||||||
|
|
||||||
for (const env of envVariables) {
|
for (const env of envVariables) {
|
||||||
args.push("--env", env);
|
args.push("--env", env);
|
||||||
}
|
}
|
||||||
@@ -43,7 +47,7 @@ export const getPaketoCommand = (
|
|||||||
application: ApplicationNested,
|
application: ApplicationNested,
|
||||||
logPath: string,
|
logPath: string,
|
||||||
) => {
|
) => {
|
||||||
const { env, appName } = application;
|
const { env, appName, cleanCache } = application;
|
||||||
|
|
||||||
const buildAppDirectory = getBuildAppDirectory(application);
|
const buildAppDirectory = getBuildAppDirectory(application);
|
||||||
const envVariables = prepareEnvironmentVariables(
|
const envVariables = prepareEnvironmentVariables(
|
||||||
@@ -60,6 +64,10 @@ export const getPaketoCommand = (
|
|||||||
"paketobuildpacks/builder-jammy-full",
|
"paketobuildpacks/builder-jammy-full",
|
||||||
];
|
];
|
||||||
|
|
||||||
|
if (cleanCache) {
|
||||||
|
args.push("--clear-cache");
|
||||||
|
}
|
||||||
|
|
||||||
for (const env of envVariables) {
|
for (const env of envVariables) {
|
||||||
args.push("--env", `'${env}'`);
|
args.push("--env", `'${env}'`);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,12 +4,22 @@ import { prepareEnvironmentVariables } from "../docker/utils";
|
|||||||
import { getBuildAppDirectory } from "../filesystem/directory";
|
import { getBuildAppDirectory } from "../filesystem/directory";
|
||||||
import { spawnAsync } from "../process/spawnAsync";
|
import { spawnAsync } from "../process/spawnAsync";
|
||||||
import { execAsync } from "../process/execAsync";
|
import { execAsync } from "../process/execAsync";
|
||||||
|
import { nanoid } from "nanoid";
|
||||||
|
import { createHash } from "node:crypto";
|
||||||
|
|
||||||
|
const calculateSecretsHash = (envVariables: string[]): string => {
|
||||||
|
const hash = createHash("sha256");
|
||||||
|
for (const env of envVariables.sort()) {
|
||||||
|
hash.update(env);
|
||||||
|
}
|
||||||
|
return hash.digest("hex");
|
||||||
|
};
|
||||||
|
|
||||||
export const buildRailpack = async (
|
export const buildRailpack = async (
|
||||||
application: ApplicationNested,
|
application: ApplicationNested,
|
||||||
writeStream: WriteStream,
|
writeStream: WriteStream,
|
||||||
) => {
|
) => {
|
||||||
const { env, appName } = application;
|
const { env, appName, cleanCache } = application;
|
||||||
const buildAppDirectory = getBuildAppDirectory(application);
|
const buildAppDirectory = getBuildAppDirectory(application);
|
||||||
const envVariables = prepareEnvironmentVariables(
|
const envVariables = prepareEnvironmentVariables(
|
||||||
env,
|
env,
|
||||||
@@ -45,10 +55,22 @@ export const buildRailpack = async (
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Calculate secrets hash for layer invalidation
|
||||||
|
const secretsHash = calculateSecretsHash(envVariables);
|
||||||
|
|
||||||
// Build with BuildKit using the Railpack frontend
|
// Build with BuildKit using the Railpack frontend
|
||||||
|
const cacheKey = cleanCache ? nanoid(10) : undefined;
|
||||||
const buildArgs = [
|
const buildArgs = [
|
||||||
"buildx",
|
"buildx",
|
||||||
"build",
|
"build",
|
||||||
|
...(cacheKey
|
||||||
|
? [
|
||||||
|
"--build-arg",
|
||||||
|
`secrets-hash=${secretsHash}`,
|
||||||
|
"--build-arg",
|
||||||
|
`cache-key=${cacheKey}`,
|
||||||
|
]
|
||||||
|
: []),
|
||||||
"--build-arg",
|
"--build-arg",
|
||||||
"BUILDKIT_SYNTAX=ghcr.io/railwayapp/railpack-frontend:v0.0.55",
|
"BUILDKIT_SYNTAX=ghcr.io/railwayapp/railpack-frontend:v0.0.55",
|
||||||
"-f",
|
"-f",
|
||||||
@@ -92,7 +114,7 @@ export const getRailpackCommand = (
|
|||||||
application: ApplicationNested,
|
application: ApplicationNested,
|
||||||
logPath: string,
|
logPath: string,
|
||||||
) => {
|
) => {
|
||||||
const { env, appName } = application;
|
const { env, appName, cleanCache } = application;
|
||||||
const buildAppDirectory = getBuildAppDirectory(application);
|
const buildAppDirectory = getBuildAppDirectory(application);
|
||||||
const envVariables = prepareEnvironmentVariables(
|
const envVariables = prepareEnvironmentVariables(
|
||||||
env,
|
env,
|
||||||
@@ -113,10 +135,22 @@ export const getRailpackCommand = (
|
|||||||
prepareArgs.push("--env", env);
|
prepareArgs.push("--env", env);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Calculate secrets hash for layer invalidation
|
||||||
|
const secretsHash = calculateSecretsHash(envVariables);
|
||||||
|
|
||||||
|
const cacheKey = cleanCache ? nanoid(10) : undefined;
|
||||||
// Build command
|
// Build command
|
||||||
const buildArgs = [
|
const buildArgs = [
|
||||||
"buildx",
|
"buildx",
|
||||||
"build",
|
"build",
|
||||||
|
...(cacheKey
|
||||||
|
? [
|
||||||
|
"--build-arg",
|
||||||
|
`secrets-hash=${secretsHash}`,
|
||||||
|
"--build-arg",
|
||||||
|
`cache-key=${cacheKey}`,
|
||||||
|
]
|
||||||
|
: []),
|
||||||
"--build-arg",
|
"--build-arg",
|
||||||
"BUILDKIT_SYNTAX=ghcr.io/railwayapp/railpack-frontend:v0.0.55",
|
"BUILDKIT_SYNTAX=ghcr.io/railwayapp/railpack-frontend:v0.0.55",
|
||||||
"-f",
|
"-f",
|
||||||
|
|||||||
Reference in New Issue
Block a user