Compare commits

...

8 Commits

Author SHA1 Message Date
Mauricio Siu
031d0ce315 Update dokploy version to v0.21.3 in package.json 2025-04-03 00:22:57 -06:00
Mauricio Siu
131a1acbbe Merge pull request #1617 from Dokploy/fix/cover-edge-cases-processor-template
fix(templates): add optional chaining to prevent errors when accessin…
2025-04-03 00:22:44 -06:00
Mauricio Siu
9a839de022 feat(templates): add username and email generation using faker 2025-04-03 00:22:29 -06:00
Mauricio Siu
b9de05015f fix(templates): add optional chaining to prevent errors when accessing template properties 2025-04-03 00:17:09 -06:00
Mauricio Siu
0bdaa81263 fix(backups): replace findAdmin with db query to fetch admin by role for cron job initialization 2025-04-02 07:10:19 -06:00
Mauricio Siu
baf36b6fb6 Merge pull request #1608 from Dokploy/fix/move-cron-to-after-migration
Fix/move cron to after migration
2025-04-02 06:58:38 -06:00
Mauricio Siu
d632e83799 Update dokploy version to v0.21.2 in package.json 2025-04-02 06:53:41 -06:00
Mauricio Siu
6f52edd845 fix(backups): ensure initCronJobs is awaited before migration to improve backup reliability 2025-04-02 06:53:32 -06:00
5 changed files with 65 additions and 29 deletions

View File

@@ -307,7 +307,7 @@ export const AddTemplate = ({ projectId, baseUrl }: Props) => {
> >
{templates?.map((template) => ( {templates?.map((template) => (
<div <div
key={template.id} key={template?.id}
className={cn( className={cn(
"flex flex-col border rounded-lg overflow-hidden relative", "flex flex-col border rounded-lg overflow-hidden relative",
viewMode === "icon" && "h-[200px]", viewMode === "icon" && "h-[200px]",
@@ -315,7 +315,7 @@ export const AddTemplate = ({ projectId, baseUrl }: Props) => {
)} )}
> >
<Badge className="absolute top-2 right-2" variant="blue"> <Badge className="absolute top-2 right-2" variant="blue">
{template.version} {template?.version}
</Badge> </Badge>
<div <div
className={cn( className={cn(
@@ -324,21 +324,21 @@ export const AddTemplate = ({ projectId, baseUrl }: Props) => {
)} )}
> >
<img <img
src={`${customBaseUrl || "https://templates.dokploy.com/"}/blueprints/${template.id}/${template.logo}`} src={`${customBaseUrl || "https://templates.dokploy.com/"}/blueprints/${template?.id}/${template?.logo}`}
className={cn( className={cn(
"object-contain", "object-contain",
viewMode === "detailed" ? "size-24" : "size-16", viewMode === "detailed" ? "size-24" : "size-16",
)} )}
alt={template.name} alt={template?.name}
/> />
<div className="flex flex-col items-center gap-2"> <div className="flex flex-col items-center gap-2">
<span className="text-sm font-medium line-clamp-1"> <span className="text-sm font-medium line-clamp-1">
{template.name} {template?.name}
</span> </span>
{viewMode === "detailed" && {viewMode === "detailed" &&
template.tags.length > 0 && ( template?.tags?.length > 0 && (
<div className="flex flex-wrap justify-center gap-1.5"> <div className="flex flex-wrap justify-center gap-1.5">
{template.tags.map((tag) => ( {template?.tags?.map((tag) => (
<Badge <Badge
key={tag} key={tag}
variant="green" variant="green"
@@ -356,7 +356,7 @@ export const AddTemplate = ({ projectId, baseUrl }: Props) => {
{viewMode === "detailed" && ( {viewMode === "detailed" && (
<ScrollArea className="flex-1 p-6"> <ScrollArea className="flex-1 p-6">
<div className="text-sm text-muted-foreground"> <div className="text-sm text-muted-foreground">
{template.description} {template?.description}
</div> </div>
</ScrollArea> </ScrollArea>
)} )}
@@ -372,25 +372,27 @@ export const AddTemplate = ({ projectId, baseUrl }: Props) => {
> >
{viewMode === "detailed" && ( {viewMode === "detailed" && (
<div className="flex gap-2"> <div className="flex gap-2">
<Link {template?.links?.github && (
href={template.links.github}
target="_blank"
className="text-muted-foreground hover:text-foreground transition-colors"
>
<GithubIcon className="size-5" />
</Link>
{template.links.website && (
<Link <Link
href={template.links.website} href={template?.links?.github}
target="_blank"
className="text-muted-foreground hover:text-foreground transition-colors"
>
<GithubIcon className="size-5" />
</Link>
)}
{template?.links?.website && (
<Link
href={template?.links?.website}
target="_blank" target="_blank"
className="text-muted-foreground hover:text-foreground transition-colors" className="text-muted-foreground hover:text-foreground transition-colors"
> >
<Globe className="size-5" /> <Globe className="size-5" />
</Link> </Link>
)} )}
{template.links.docs && ( {template?.links?.docs && (
<Link <Link
href={template.links.docs} href={template?.links?.docs}
target="_blank" target="_blank"
className="text-muted-foreground hover:text-foreground transition-colors" className="text-muted-foreground hover:text-foreground transition-colors"
> >
@@ -419,7 +421,7 @@ export const AddTemplate = ({ projectId, baseUrl }: Props) => {
</AlertDialogTitle> </AlertDialogTitle>
<AlertDialogDescription> <AlertDialogDescription>
This will create an application from the{" "} This will create an application from the{" "}
{template.name} template and add it to your {template?.name} template and add it to your
project. project.
</AlertDialogDescription> </AlertDialogDescription>

View File

@@ -1,6 +1,6 @@
{ {
"name": "dokploy", "name": "dokploy",
"version": "v0.21.1", "version": "v0.21.3",
"private": true, "private": true,
"license": "Apache-2.0", "license": "Apache-2.0",
"type": "module", "type": "module",

View File

@@ -46,8 +46,8 @@ void app.prepare().then(async () => {
await initializeNetwork(); await initializeNetwork();
createDefaultTraefikConfig(); createDefaultTraefikConfig();
createDefaultServerTraefikConfig(); createDefaultServerTraefikConfig();
await initCronJobs();
await migration(); await migration();
await initCronJobs();
await sendDokployRestartNotifications(); await sendDokployRestartNotifications();
} }

View File

@@ -1,3 +1,4 @@
import { faker } from "@faker-js/faker";
import type { Schema } from "./index"; import type { Schema } from "./index";
import { import {
generateBase64, generateBase64,
@@ -70,7 +71,7 @@ function processValue(
schema: Schema, schema: Schema,
): string { ): string {
// First replace utility functions // First replace utility functions
let processedValue = value.replace(/\${([^}]+)}/g, (match, varName) => { let processedValue = value?.replace(/\${([^}]+)}/g, (match, varName) => {
// Handle utility functions // Handle utility functions
if (varName === "domain") { if (varName === "domain") {
return generateRandomDomain(schema); return generateRandomDomain(schema);
@@ -117,6 +118,14 @@ function processValue(
return generateJwt(length); return generateJwt(length);
} }
if (varName === "username") {
return faker.internet.userName().toLowerCase();
}
if (varName === "email") {
return faker.internet.email().toLowerCase();
}
// If not a utility function, try to get from variables // If not a utility function, try to get from variables
return variables[varName] || match; return variables[varName] || match;
}); });
@@ -177,7 +186,14 @@ export function processDomains(
variables: Record<string, string>, variables: Record<string, string>,
schema: Schema, schema: Schema,
): Template["domains"] { ): Template["domains"] {
if (!template?.config?.domains) return []; if (
!template?.config?.domains ||
template.config.domains.length === 0 ||
template.config.domains.every((domain) => !domain.serviceName)
) {
return [];
}
return template?.config?.domains?.map((domain: DomainConfig) => ({ return template?.config?.domains?.map((domain: DomainConfig) => ({
...domain, ...domain,
host: domain.host host: domain.host
@@ -194,7 +210,9 @@ export function processEnvVars(
variables: Record<string, string>, variables: Record<string, string>,
schema: Schema, schema: Schema,
): Template["envs"] { ): Template["envs"] {
if (!template?.config?.env) return []; if (!template?.config?.env || Object.keys(template.config.env).length === 0) {
return [];
}
// Handle array of env vars // Handle array of env vars
if (Array.isArray(template.config.env)) { if (Array.isArray(template.config.env)) {
@@ -233,7 +251,13 @@ export function processMounts(
variables: Record<string, string>, variables: Record<string, string>,
schema: Schema, schema: Schema,
): Template["mounts"] { ): Template["mounts"] {
if (!template?.config?.mounts) return []; if (
!template?.config?.mounts ||
template.config.mounts.length === 0 ||
template.config.mounts.every((mount) => !mount.filePath && !mount.content)
) {
return [];
}
return template?.config?.mounts?.map((mount: MountConfig) => ({ return template?.config?.mounts?.map((mount: MountConfig) => ({
filePath: processValue(mount.filePath, variables, schema), filePath: processValue(mount.filePath, variables, schema),

View File

@@ -2,7 +2,6 @@ import path from "node:path";
import { getAllServers } from "@dokploy/server/services/server"; import { getAllServers } from "@dokploy/server/services/server";
import { scheduleJob } from "node-schedule"; import { scheduleJob } from "node-schedule";
import { db } from "../../db/index"; import { db } from "../../db/index";
import { findAdmin } from "../../services/admin";
import { import {
cleanUpDockerBuilder, cleanUpDockerBuilder,
cleanUpSystemPrune, cleanUpSystemPrune,
@@ -14,13 +13,24 @@ import { getS3Credentials, scheduleBackup } from "./utils";
import type { BackupSchedule } from "@dokploy/server/services/backup"; import type { BackupSchedule } from "@dokploy/server/services/backup";
import { startLogCleanup } from "../access-log/handler"; import { startLogCleanup } from "../access-log/handler";
import { member } from "@dokploy/server/db/schema";
import { eq } from "drizzle-orm";
export const initCronJobs = async () => { export const initCronJobs = async () => {
console.log("Setting up cron jobs...."); console.log("Setting up cron jobs....");
const admin = await findAdmin(); const admin = await db.query.member.findFirst({
where: eq(member.role, "owner"),
with: {
user: true,
},
});
if (admin?.user.enableDockerCleanup) { if (!admin) {
return;
}
if (admin.user.enableDockerCleanup) {
scheduleJob("docker-cleanup", "0 0 * * *", async () => { scheduleJob("docker-cleanup", "0 0 * * *", async () => {
console.log( console.log(
`Docker Cleanup ${new Date().toLocaleString()}] Running docker cleanup`, `Docker Cleanup ${new Date().toLocaleString()}] Running docker cleanup`,