From a941efb1ffb9e3137cf4a36071c8876d9e0911ba Mon Sep 17 00:00:00 2001 From: Nicholas Penree Date: Tue, 17 Dec 2024 23:10:19 -0500 Subject: [PATCH 01/12] feat(certs): show expiration and chain details --- .../certificates/show-certificates.tsx | 195 ++++++++++++++++-- 1 file changed, 179 insertions(+), 16 deletions(-) diff --git a/apps/dokploy/components/dashboard/settings/certificates/show-certificates.tsx b/apps/dokploy/components/dashboard/settings/certificates/show-certificates.tsx index 69b1a3323..ccc16f3eb 100644 --- a/apps/dokploy/components/dashboard/settings/certificates/show-certificates.tsx +++ b/apps/dokploy/components/dashboard/settings/certificates/show-certificates.tsx @@ -6,13 +6,144 @@ import { CardTitle, } from "@/components/ui/card"; import { api } from "@/utils/api"; -import { ShieldCheck } from "lucide-react"; +import { AlertCircle, Link, ShieldCheck } from "lucide-react"; import { AddCertificate } from "./add-certificate"; import { DeleteCertificate } from "./delete-certificate"; export const ShowCertificates = () => { const { data } = api.certificates.all.useQuery(); + const extractExpirationDate = (certData: string): Date | null => { + try { + const match = certData.match( + /-----BEGIN CERTIFICATE-----\s*([^-]+)\s*-----END CERTIFICATE-----/, + ); + if (!match?.[1]) return null; + + const base64Cert = match[1].replace(/\s/g, ""); + const binaryStr = window.atob(base64Cert); + const bytes = new Uint8Array(binaryStr.length); + + for (let i = 0; i < binaryStr.length; i++) { + bytes[i] = binaryStr.charCodeAt(i); + } + + let dateFound = 0; + for (let i = 0; i < bytes.length - 2; i++) { + if (bytes[i] === 0x17 || bytes[i] === 0x18) { + const dateType = bytes[i]; + const dateLength = bytes[i + 1]; + if (typeof dateLength === "undefined") continue; + + if (dateFound === 0) { + dateFound++; + i += dateLength + 1; + continue; + } + + let dateStr = ""; + for (let j = 0; j < dateLength; j++) { + const charCode = bytes[i + 2 + j]; + if (typeof charCode === "undefined") continue; + dateStr += String.fromCharCode(charCode); + } + + if (dateType === 0x17) { + // UTCTime (YYMMDDhhmmssZ) + const year = Number.parseInt(dateStr.slice(0, 2)); + const fullYear = year >= 50 ? 1900 + year : 2000 + year; + return new Date( + Date.UTC( + fullYear, + Number.parseInt(dateStr.slice(2, 4)) - 1, + Number.parseInt(dateStr.slice(4, 6)), + Number.parseInt(dateStr.slice(6, 8)), + Number.parseInt(dateStr.slice(8, 10)), + Number.parseInt(dateStr.slice(10, 12)), + ), + ); + } + + // GeneralizedTime (YYYYMMDDhhmmssZ) + return new Date( + Date.UTC( + Number.parseInt(dateStr.slice(0, 4)), + Number.parseInt(dateStr.slice(4, 6)) - 1, + Number.parseInt(dateStr.slice(6, 8)), + Number.parseInt(dateStr.slice(8, 10)), + Number.parseInt(dateStr.slice(10, 12)), + Number.parseInt(dateStr.slice(12, 14)), + ), + ); + } + } + return null; + } catch (error) { + console.error("Error parsing certificate:", error); + return null; + } + }; + + const getExpirationStatus = (certData: string) => { + const expirationDate = extractExpirationDate(certData); + + if (!expirationDate) + return { + status: "unknown" as const, + className: "text-muted-foreground", + message: "Could not determine expiration", + }; + + const now = new Date(); + const daysUntilExpiration = Math.ceil( + (expirationDate.getTime() - now.getTime()) / (1000 * 60 * 60 * 24), + ); + + if (daysUntilExpiration < 0) { + return { + status: "expired" as const, + className: "text-red-500", + message: `Expired on ${expirationDate.toLocaleDateString([], { + year: "numeric", + month: "long", + day: "numeric", + })}`, + }; + } + + if (daysUntilExpiration <= 30) { + return { + status: "warning" as const, + className: "text-yellow-500", + message: `Expires in ${daysUntilExpiration} days`, + }; + } + + return { + status: "valid" as const, + className: "text-muted-foreground", + message: `Expires ${expirationDate.toLocaleDateString([], { + year: "numeric", + month: "long", + day: "numeric", + })}`, + }; + }; + + const getCertificateChainInfo = (certData: string) => { + const certCount = (certData.match(/-----BEGIN CERTIFICATE-----/g) || []) + .length; + return certCount > 1 + ? { + isChain: true, + count: certCount, + } + : { + isChain: false, + count: 1, + }; + }; + return (
@@ -23,7 +154,7 @@ export const ShowCertificates = () => { - {data?.length === 0 ? ( + {!data?.length ? (
@@ -35,21 +166,53 @@ export const ShowCertificates = () => { ) : (
- {data?.map((destination, index) => ( -
- - {index + 1}. {destination.name} - -
- + {data.map((certificate, index) => { + const expiration = getExpirationStatus( + certificate.certificateData, + ); + const chainInfo = getCertificateChainInfo( + certificate.certificateData, + ); + return ( +
+
+
+ + {index + 1}. {certificate.name} + + {chainInfo.isChain && ( +
+ + + Chain ({chainInfo.count}) + +
+ )} +
+ +
+
+ {expiration.status !== "valid" && ( + + )} + {expiration.message} + {certificate.autoRenew && + expiration.status !== "valid" && ( + + (Auto-renewal enabled) + + )} +
-
- ))} + ); + })}
From 651e81ce6d4559a5fb07e385b0cae0a5b9a0098b Mon Sep 17 00:00:00 2001 From: Dominik Koch Date: Thu, 19 Dec 2024 11:22:58 +0100 Subject: [PATCH 02/12] feat(plausible): bump to 2.1.4 --- apps/dokploy/templates/plausible/docker-compose.yml | 2 +- apps/dokploy/templates/templates.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/dokploy/templates/plausible/docker-compose.yml b/apps/dokploy/templates/plausible/docker-compose.yml index 62ce5ece4..bb267f65c 100644 --- a/apps/dokploy/templates/plausible/docker-compose.yml +++ b/apps/dokploy/templates/plausible/docker-compose.yml @@ -26,7 +26,7 @@ services: hard: 262144 plausible: - image: ghcr.io/plausible/community-edition:v2.1.0 + image: ghcr.io/plausible/community-edition:v2.1.4 restart: always command: sh -c "sleep 10 && /entrypoint.sh db createdb && /entrypoint.sh db migrate && /entrypoint.sh run" depends_on: diff --git a/apps/dokploy/templates/templates.ts b/apps/dokploy/templates/templates.ts index f0d926d8f..917184c5d 100644 --- a/apps/dokploy/templates/templates.ts +++ b/apps/dokploy/templates/templates.ts @@ -34,7 +34,7 @@ export const templates: TemplateData[] = [ { id: "plausible", name: "Plausible", - version: "v2.1.0", + version: "v2.1.4", description: "Plausible is a open source, self-hosted web analytics platform that lets you track website traffic and user behavior.", logo: "plausible.svg", From e05d01788f19729ddca7d0ac40416ae0197625b3 Mon Sep 17 00:00:00 2001 From: usopp Date: Fri, 20 Dec 2024 00:11:48 +0100 Subject: [PATCH 03/12] style(notifications): better notification item style --- .../notifications/delete-notification.tsx | 11 ++- .../notifications/show-notifications.tsx | 90 ++++++++++--------- .../notifications/update-notification.tsx | 8 +- 3 files changed, 63 insertions(+), 46 deletions(-) diff --git a/apps/dokploy/components/dashboard/settings/notifications/delete-notification.tsx b/apps/dokploy/components/dashboard/settings/notifications/delete-notification.tsx index 468db8510..4bb197b29 100644 --- a/apps/dokploy/components/dashboard/settings/notifications/delete-notification.tsx +++ b/apps/dokploy/components/dashboard/settings/notifications/delete-notification.tsx @@ -11,7 +11,7 @@ import { } from "@/components/ui/alert-dialog"; import { Button } from "@/components/ui/button"; import { api } from "@/utils/api"; -import { TrashIcon } from "lucide-react"; +import { Trash2 } from "lucide-react"; import React from "react"; import { toast } from "sonner"; @@ -24,8 +24,13 @@ export const DeleteNotification = ({ notificationId }: Props) => { return ( - diff --git a/apps/dokploy/components/dashboard/settings/notifications/show-notifications.tsx b/apps/dokploy/components/dashboard/settings/notifications/show-notifications.tsx index c22f7b720..d742500f2 100644 --- a/apps/dokploy/components/dashboard/settings/notifications/show-notifications.tsx +++ b/apps/dokploy/components/dashboard/settings/notifications/show-notifications.tsx @@ -40,48 +40,58 @@ export const ShowNotifications = () => {
) : (
-
- {data?.map((notification, index) => ( -
-
- {notification.notificationType === "slack" && ( - - )} - {notification.notificationType === "telegram" && ( - - )} - {notification.notificationType === "discord" && ( - - )} - {notification.notificationType === "email" && ( - - )} - - {notification.name} - -
- -
- - -
-
- ))} -
-
- +
+ {data?.map((notification, index) => ( +
+
+ {notification.notificationType === "slack" && ( +
+ +
+ )} + {notification.notificationType === "telegram" && ( +
+ +
+ )} + {notification.notificationType === "discord" && ( +
+ +
+ )} + {notification.notificationType === "email" && ( +
+ +
+ )} +
+ + {notification.name} + + + {notification.notificationType[0].toUpperCase() + notification.notificationType.slice(1)} notification + +
+
+
+ + +
+ ))}
+ +
+ +
+
)} diff --git a/apps/dokploy/components/dashboard/settings/notifications/update-notification.tsx b/apps/dokploy/components/dashboard/settings/notifications/update-notification.tsx index 9bdf35f14..cfa2e0bab 100644 --- a/apps/dokploy/components/dashboard/settings/notifications/update-notification.tsx +++ b/apps/dokploy/components/dashboard/settings/notifications/update-notification.tsx @@ -26,7 +26,7 @@ import { Input } from "@/components/ui/input"; import { Switch } from "@/components/ui/switch"; import { api } from "@/utils/api"; import { zodResolver } from "@hookform/resolvers/zod"; -import { Mail, PenBoxIcon } from "lucide-react"; +import { Mail, Pen } from "lucide-react"; import { useEffect, useState } from "react"; import { FieldErrors, useFieldArray, useForm } from "react-hook-form"; import { toast } from "sonner"; @@ -218,8 +218,10 @@ export const UpdateNotification = ({ notificationId }: Props) => { return ( - From 77336a21f9889588b0b99f63c1b95afa4d726512 Mon Sep 17 00:00:00 2001 From: usopp Date: Fri, 20 Dec 2024 00:21:51 +0100 Subject: [PATCH 04/12] chore: lint --- .../dashboard/settings/notifications/show-notifications.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/dokploy/components/dashboard/settings/notifications/show-notifications.tsx b/apps/dokploy/components/dashboard/settings/notifications/show-notifications.tsx index d742500f2..28aeb8c05 100644 --- a/apps/dokploy/components/dashboard/settings/notifications/show-notifications.tsx +++ b/apps/dokploy/components/dashboard/settings/notifications/show-notifications.tsx @@ -72,7 +72,7 @@ export const ShowNotifications = () => { {notification.name} - {notification.notificationType[0].toUpperCase() + notification.notificationType.slice(1)} notification + {notification.notificationType && notification.notificationType[0].toUpperCase() + notification.notificationType.slice(1)} notification
From ed8be62ff30dcaeeea34ec815e15f74e45fa46a4 Mon Sep 17 00:00:00 2001 From: usopp Date: Fri, 20 Dec 2024 00:24:44 +0100 Subject: [PATCH 05/12] chore: lint --- .../dashboard/settings/notifications/show-notifications.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/dokploy/components/dashboard/settings/notifications/show-notifications.tsx b/apps/dokploy/components/dashboard/settings/notifications/show-notifications.tsx index 28aeb8c05..10ea7304e 100644 --- a/apps/dokploy/components/dashboard/settings/notifications/show-notifications.tsx +++ b/apps/dokploy/components/dashboard/settings/notifications/show-notifications.tsx @@ -72,7 +72,7 @@ export const ShowNotifications = () => { {notification.name} - {notification.notificationType && notification.notificationType[0].toUpperCase() + notification.notificationType.slice(1)} notification + {notification.notificationType?.[0]?.toUpperCase() + notification.notificationType?.slice(1)} notification
From bf2551b0f613e1fe2186c88c011ec3da80eb29fc Mon Sep 17 00:00:00 2001 From: 190km Date: Fri, 20 Dec 2024 00:54:32 +0100 Subject: [PATCH 06/12] fix(settings/profile): fixed password changing --- apps/dokploy/server/api/routers/auth.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/dokploy/server/api/routers/auth.ts b/apps/dokploy/server/api/routers/auth.ts index ef9db4da2..cad77927c 100644 --- a/apps/dokploy/server/api/routers/auth.ts +++ b/apps/dokploy/server/api/routers/auth.ts @@ -188,9 +188,9 @@ export const authRouter = createTRPCRouter({ .mutation(async ({ ctx, input }) => { const currentAuth = await findAuthByEmail(ctx.user.email); - if (input.password) { + if (input.currentPassword) { const correctPassword = bcrypt.compareSync( - input.password, + input.currentPassword, currentAuth?.password || "", ); if (!correctPassword) { From fdfa92753252af5b828d6785f9dd2fe382927599 Mon Sep 17 00:00:00 2001 From: 190km Date: Fri, 20 Dec 2024 01:00:16 +0100 Subject: [PATCH 07/12] feat(settings/profile): reset password form after validating password change --- .../components/dashboard/settings/profile/profile-form.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/dokploy/components/dashboard/settings/profile/profile-form.tsx b/apps/dokploy/components/dashboard/settings/profile/profile-form.tsx index 65ccff0e3..1141397f9 100644 --- a/apps/dokploy/components/dashboard/settings/profile/profile-form.tsx +++ b/apps/dokploy/components/dashboard/settings/profile/profile-form.tsx @@ -104,6 +104,7 @@ export const ProfileForm = () => { .then(async () => { await refetch(); toast.success("Profile Updated"); + form.reset(); }) .catch(() => { toast.error("Error to Update the profile"); From 788771c5eb74cda95d2e490dfe981ed56cd1e63c Mon Sep 17 00:00:00 2001 From: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com> Date: Fri, 20 Dec 2024 23:16:38 -0600 Subject: [PATCH 08/12] refactor: add password in validation --- apps/dokploy/server/api/routers/auth.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/dokploy/server/api/routers/auth.ts b/apps/dokploy/server/api/routers/auth.ts index cad77927c..f0d3b495b 100644 --- a/apps/dokploy/server/api/routers/auth.ts +++ b/apps/dokploy/server/api/routers/auth.ts @@ -188,9 +188,9 @@ export const authRouter = createTRPCRouter({ .mutation(async ({ ctx, input }) => { const currentAuth = await findAuthByEmail(ctx.user.email); - if (input.currentPassword) { + if (input.currentPassword || input.password) { const correctPassword = bcrypt.compareSync( - input.currentPassword, + input.currentPassword || "", currentAuth?.password || "", ); if (!correctPassword) { From 1aae523a0bf8eea4ce7ede4a31bb258801cf9dac Mon Sep 17 00:00:00 2001 From: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com> Date: Sat, 21 Dec 2024 01:53:39 -0600 Subject: [PATCH 09/12] refactor: add missing verifyToken --- apps/dokploy/server/api/routers/auth.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/apps/dokploy/server/api/routers/auth.ts b/apps/dokploy/server/api/routers/auth.ts index f0d3b495b..a1345cca3 100644 --- a/apps/dokploy/server/api/routers/auth.ts +++ b/apps/dokploy/server/api/routers/auth.ts @@ -268,7 +268,9 @@ export const authRouter = createTRPCRouter({ return auth; }), - + verifyToken: protectedProcedure.mutation(async () => { + return true; + }), one: adminProcedure.input(apiFindOneAuth).query(async ({ input }) => { const auth = await findAuthById(input.id); return auth; From 7a8bb8f71d9a1bf7f78c7041a0248c6e2a0ea382 Mon Sep 17 00:00:00 2001 From: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com> Date: Sat, 21 Dec 2024 02:45:58 -0600 Subject: [PATCH 10/12] fix: add missing notifications in cron jobs --- apps/dokploy/server/api/routers/settings.ts | 4 +- packages/server/src/utils/backups/index.ts | 140 ++++++++++++++++---- 2 files changed, 116 insertions(+), 28 deletions(-) diff --git a/apps/dokploy/server/api/routers/settings.ts b/apps/dokploy/server/api/routers/settings.ts index 7c777b170..e6469224b 100644 --- a/apps/dokploy/server/api/routers/settings.ts +++ b/apps/dokploy/server/api/routers/settings.ts @@ -267,11 +267,11 @@ export const settingsRouter = createTRPCRouter({ message: "You are not authorized to access this admin", }); } - await updateAdmin(ctx.user.authId, { + const adminUpdated = await updateAdmin(ctx.user.authId, { enableDockerCleanup: input.enableDockerCleanup, }); - if (admin.enableDockerCleanup) { + if (adminUpdated?.enableDockerCleanup) { scheduleJob("docker-cleanup", "0 0 * * *", async () => { console.log( `Docker Cleanup ${new Date().toLocaleString()}] Running...`, diff --git a/packages/server/src/utils/backups/index.ts b/packages/server/src/utils/backups/index.ts index b16192538..797feb383 100644 --- a/packages/server/src/utils/backups/index.ts +++ b/packages/server/src/utils/backups/index.ts @@ -11,6 +11,8 @@ import { runMariadbBackup } from "./mariadb"; import { runMongoBackup } from "./mongo"; import { runMySqlBackup } from "./mysql"; import { runPostgresBackup } from "./postgres"; +import { sendDockerCleanupNotifications } from "../notifications/docker-cleanup"; +import { sendDatabaseBackupNotifications } from "../notifications/database-backup"; export const initCronJobs = async () => { console.log("Setting up cron jobs...."); @@ -25,14 +27,15 @@ export const initCronJobs = async () => { await cleanUpUnusedImages(); await cleanUpDockerBuilder(); await cleanUpSystemPrune(); + await sendDockerCleanupNotifications(admin.adminId); }); } const servers = await getAllServers(); for (const server of servers) { - const { appName, serverId } = server; - if (serverId) { + const { appName, serverId, enableDockerCleanup } = server; + if (enableDockerCleanup) { scheduleJob(serverId, "0 0 * * *", async () => { console.log( `SERVER-BACKUP[${new Date().toLocaleString()}] Running Cleanup ${appName}`, @@ -40,12 +43,17 @@ export const initCronJobs = async () => { await cleanUpUnusedImages(serverId); await cleanUpDockerBuilder(serverId); await cleanUpSystemPrune(serverId); + await sendDockerCleanupNotifications( + admin.adminId, + `Docker cleanup for Server ${appName}`, + ); }); } } const pgs = await db.query.postgres.findMany({ with: { + project: true, backups: { with: { destination: true, @@ -61,18 +69,39 @@ export const initCronJobs = async () => { for (const backup of pg.backups) { const { schedule, backupId, enabled } = backup; if (enabled) { - scheduleJob(backupId, schedule, async () => { - console.log( - `PG-SERVER[${new Date().toLocaleString()}] Running Backup ${backupId}`, - ); - runPostgresBackup(pg, backup); - }); + try { + scheduleJob(backupId, schedule, async () => { + console.log( + `PG-SERVER[${new Date().toLocaleString()}] Running Backup ${backupId}`, + ); + runPostgresBackup(pg, backup); + }); + + await sendDatabaseBackupNotifications({ + applicationName: pg.name, + projectName: pg.project.name, + databaseType: "postgres", + type: "success", + adminId: pg.project.adminId, + }); + } catch (error) { + await sendDatabaseBackupNotifications({ + applicationName: pg.name, + projectName: pg.project.name, + databaseType: "postgres", + type: "error", + // @ts-ignore + errorMessage: error?.message || "Error message not provided", + adminId: pg.project.adminId, + }); + } } } } const mariadbs = await db.query.mariadb.findMany({ with: { + project: true, backups: { with: { destination: true, @@ -89,18 +118,38 @@ export const initCronJobs = async () => { for (const backup of maria.backups) { const { schedule, backupId, enabled } = backup; if (enabled) { - scheduleJob(backupId, schedule, async () => { - console.log( - `MARIADB-SERVER[${new Date().toLocaleString()}] Running Backup ${backupId}`, - ); - await runMariadbBackup(maria, backup); - }); + try { + scheduleJob(backupId, schedule, async () => { + console.log( + `MARIADB-SERVER[${new Date().toLocaleString()}] Running Backup ${backupId}`, + ); + await runMariadbBackup(maria, backup); + }); + await sendDatabaseBackupNotifications({ + applicationName: maria.name, + projectName: maria.project.name, + databaseType: "mariadb", + type: "success", + adminId: maria.project.adminId, + }); + } catch (error) { + await sendDatabaseBackupNotifications({ + applicationName: maria.name, + projectName: maria.project.name, + databaseType: "mariadb", + type: "error", + // @ts-ignore + errorMessage: error?.message || "Error message not provided", + adminId: maria.project.adminId, + }); + } } } } const mongodbs = await db.query.mongo.findMany({ with: { + project: true, backups: { with: { destination: true, @@ -117,18 +166,38 @@ export const initCronJobs = async () => { for (const backup of mongo.backups) { const { schedule, backupId, enabled } = backup; if (enabled) { - scheduleJob(backupId, schedule, async () => { - console.log( - `MONGO-SERVER[${new Date().toLocaleString()}] Running Backup ${backupId}`, - ); - await runMongoBackup(mongo, backup); - }); + try { + scheduleJob(backupId, schedule, async () => { + console.log( + `MONGO-SERVER[${new Date().toLocaleString()}] Running Backup ${backupId}`, + ); + await runMongoBackup(mongo, backup); + }); + await sendDatabaseBackupNotifications({ + applicationName: mongo.name, + projectName: mongo.project.name, + databaseType: "mongodb", + type: "success", + adminId: mongo.project.adminId, + }); + } catch (error) { + await sendDatabaseBackupNotifications({ + applicationName: mongo.name, + projectName: mongo.project.name, + databaseType: "mongodb", + type: "error", + // @ts-ignore + errorMessage: error?.message || "Error message not provided", + adminId: mongo.project.adminId, + }); + } } } } const mysqls = await db.query.mysql.findMany({ with: { + project: true, backups: { with: { destination: true, @@ -145,12 +214,31 @@ export const initCronJobs = async () => { for (const backup of mysql.backups) { const { schedule, backupId, enabled } = backup; if (enabled) { - scheduleJob(backupId, schedule, async () => { - console.log( - `MYSQL-SERVER[${new Date().toLocaleString()}] Running Backup ${backupId}`, - ); - await runMySqlBackup(mysql, backup); - }); + try { + scheduleJob(backupId, schedule, async () => { + console.log( + `MYSQL-SERVER[${new Date().toLocaleString()}] Running Backup ${backupId}`, + ); + await runMySqlBackup(mysql, backup); + }); + await sendDatabaseBackupNotifications({ + applicationName: mysql.name, + projectName: mysql.project.name, + databaseType: "mysql", + type: "success", + adminId: mysql.project.adminId, + }); + } catch (error) { + await sendDatabaseBackupNotifications({ + applicationName: mysql.name, + projectName: mysql.project.name, + databaseType: "mysql", + type: "error", + // @ts-ignore + errorMessage: error?.message || "Error message not provided", + adminId: mysql.project.adminId, + }); + } } } } From 6c9b12cee904072e6a46d41b9fc3054ac4b79d21 Mon Sep 17 00:00:00 2001 From: UndefinedPony Date: Sat, 21 Dec 2024 18:33:22 +0100 Subject: [PATCH 11/12] refactor: use dynamic tag for comparing latest tag digest --- packages/server/src/services/settings.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/server/src/services/settings.ts b/packages/server/src/services/settings.ts index 0d2ec9671..0ab9744e5 100644 --- a/packages/server/src/services/settings.ts +++ b/packages/server/src/services/settings.ts @@ -72,7 +72,9 @@ export const getUpdateData = async (): Promise => { results: [{ digest: string; name: string }]; }; const { results } = data; - const latestTagDigest = results.find((t) => t.name === "latest")?.digest; + const latestTagDigest = results.find( + (t) => t.name === getDokployImageTag(), + )?.digest; if (!latestTagDigest) { return DEFAULT_UPDATE_DATA; From 18e89df9a590b92f76db28ec6a752cefcaa1375e Mon Sep 17 00:00:00 2001 From: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com> Date: Sat, 21 Dec 2024 12:45:14 -0600 Subject: [PATCH 12/12] Update apps/dokploy/components/layouts/navbar.tsx --- apps/dokploy/components/layouts/navbar.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/dokploy/components/layouts/navbar.tsx b/apps/dokploy/components/layouts/navbar.tsx index 3d17b3e92..a8eb4574a 100644 --- a/apps/dokploy/components/layouts/navbar.tsx +++ b/apps/dokploy/components/layouts/navbar.tsx @@ -18,7 +18,7 @@ import { buttonVariants } from "../ui/button"; import { useEffect, useRef, useState } from "react"; import { UpdateWebServer } from "../dashboard/settings/web-server/update-webserver"; -const AUTO_CHECK_UPDATES_INTERVAL_MINUTES = 15; +const AUTO_CHECK_UPDATES_INTERVAL_MINUTES = 5; export const Navbar = () => { const [isUpdateAvailable, setIsUpdateAvailable] = useState(false);