mirror of
https://github.com/Dokploy/dokploy
synced 2025-06-26 18:27:59 +00:00
refactor: add latestVersion information to update data
This commit is contained in:
@@ -20,16 +20,16 @@ export const UpdateServer = () => {
|
|||||||
const [isUpdateAvailable, setIsUpdateAvailable] = useState<null | boolean>(
|
const [isUpdateAvailable, setIsUpdateAvailable] = useState<null | boolean>(
|
||||||
null,
|
null,
|
||||||
);
|
);
|
||||||
const { mutateAsync: checkForUpdate, isLoading } =
|
const { mutateAsync: getUpdateData, isLoading } =
|
||||||
api.settings.checkForUpdate.useMutation();
|
api.settings.getUpdateData.useMutation();
|
||||||
const [isOpen, setIsOpen] = useState(false);
|
const [isOpen, setIsOpen] = useState(false);
|
||||||
|
|
||||||
const handleCheckUpdates = async () => {
|
const handleCheckUpdates = async () => {
|
||||||
try {
|
try {
|
||||||
const updateAvailable = await checkForUpdate();
|
const { updateAvailable, latestVersion } = await getUpdateData();
|
||||||
setIsUpdateAvailable(updateAvailable);
|
setIsUpdateAvailable(updateAvailable);
|
||||||
if (updateAvailable) {
|
if (updateAvailable) {
|
||||||
toast.success("Update is available!");
|
toast.success(`${latestVersion} update is available!`);
|
||||||
} else {
|
} else {
|
||||||
toast.info("No updates available");
|
toast.info("No updates available");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,8 +34,8 @@ export const Navbar = () => {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
const { mutateAsync } = api.auth.logout.useMutation();
|
const { mutateAsync } = api.auth.logout.useMutation();
|
||||||
const { mutateAsync: checkForUpdate } =
|
const { mutateAsync: getUpdateData } =
|
||||||
api.settings.checkForUpdate.useMutation();
|
api.settings.getUpdateData.useMutation();
|
||||||
|
|
||||||
const checkUpdatesIntervalRef = useRef<null | NodeJS.Timeout>(null);
|
const checkUpdatesIntervalRef = useRef<null | NodeJS.Timeout>(null);
|
||||||
|
|
||||||
@@ -58,7 +58,7 @@ export const Navbar = () => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const updateAvailable = await checkForUpdate();
|
const { updateAvailable } = await getUpdateData();
|
||||||
|
|
||||||
if (updateAvailable) {
|
if (updateAvailable) {
|
||||||
// Stop interval when update is available
|
// Stop interval when update is available
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ import {
|
|||||||
stopService,
|
stopService,
|
||||||
stopServiceRemote,
|
stopServiceRemote,
|
||||||
updateAdmin,
|
updateAdmin,
|
||||||
checkIsUpdateAvailable,
|
getUpdateData,
|
||||||
updateLetsEncryptEmail,
|
updateLetsEncryptEmail,
|
||||||
updateServerById,
|
updateServerById,
|
||||||
updateServerTraefik,
|
updateServerTraefik,
|
||||||
@@ -343,12 +343,12 @@ export const settingsRouter = createTRPCRouter({
|
|||||||
writeConfig("middlewares", input.traefikConfig);
|
writeConfig("middlewares", input.traefikConfig);
|
||||||
return true;
|
return true;
|
||||||
}),
|
}),
|
||||||
checkForUpdate: adminProcedure.mutation(async () => {
|
getUpdateData: adminProcedure.mutation(async () => {
|
||||||
if (IS_CLOUD) {
|
if (IS_CLOUD) {
|
||||||
return true;
|
return { latestVersion: null, updateAvailable: false };
|
||||||
}
|
}
|
||||||
|
|
||||||
return await checkIsUpdateAvailable();
|
return await getUpdateData();
|
||||||
}),
|
}),
|
||||||
updateServer: adminProcedure.mutation(async () => {
|
updateServer: adminProcedure.mutation(async () => {
|
||||||
if (IS_CLOUD) {
|
if (IS_CLOUD) {
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import { readdirSync } from "node:fs";
|
import { readdirSync } from "node:fs";
|
||||||
import { join } from "node:path";
|
import { join } from "node:path";
|
||||||
import { docker } from "@dokploy/server/constants";
|
import { docker } from "@dokploy/server/constants";
|
||||||
import { getServiceContainer } from "@dokploy/server/utils/docker/utils";
|
|
||||||
import { execAsyncRemote } from "@dokploy/server/utils/process/execAsync";
|
import { execAsyncRemote } from "@dokploy/server/utils/process/execAsync";
|
||||||
import { spawnAsync } from "../utils/process/spawnAsync";
|
import { spawnAsync } from "../utils/process/spawnAsync";
|
||||||
// import packageInfo from "../../../package.json";
|
// import packageInfo from "../../../package.json";
|
||||||
@@ -11,8 +10,11 @@ export const getDokployImageTag = () => {
|
|||||||
return process.env.RELEASE_TAG || "latest";
|
return process.env.RELEASE_TAG || "latest";
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Checks if server update is available by comparing current image's digest against digest for provided image tag via Docker hub API */
|
/** Returns latest version number and information whether server update is available by comparing current image's digest against digest for provided image tag via Docker hub API. */
|
||||||
export const checkIsUpdateAvailable = async () => {
|
export const getUpdateData = async (): Promise<{
|
||||||
|
latestVersion: string | null;
|
||||||
|
updateAvailable: boolean;
|
||||||
|
}> => {
|
||||||
const commandResult = await spawnAsync("docker", [
|
const commandResult = await spawnAsync("docker", [
|
||||||
"inspect",
|
"inspect",
|
||||||
"--format={{index .RepoDigests 0}}",
|
"--format={{index .RepoDigests 0}}",
|
||||||
@@ -21,16 +23,35 @@ export const checkIsUpdateAvailable = async () => {
|
|||||||
|
|
||||||
const currentDigest = commandResult.toString().trim().split("@")[1];
|
const currentDigest = commandResult.toString().trim().split("@")[1];
|
||||||
|
|
||||||
const url = `https://hub.docker.com/v2/repositories/dokploy/dokploy/tags/${getDokployImageTag()}`;
|
const url = "https://hub.docker.com/v2/repositories/dokploy/dokploy/tags";
|
||||||
const response = await fetch(url, {
|
const response = await fetch(url, {
|
||||||
method: "GET",
|
method: "GET",
|
||||||
headers: { "Content-Type": "application/json" },
|
headers: { "Content-Type": "application/json" },
|
||||||
});
|
});
|
||||||
|
|
||||||
const data = (await response.json()) as { digest: string };
|
const data = (await response.json()) as {
|
||||||
const { digest } = data;
|
results: [{ digest: string; name: string }];
|
||||||
|
};
|
||||||
|
const { results } = data;
|
||||||
|
const latestTagDigest = results.find((t) => t.name === "latest")?.digest;
|
||||||
|
|
||||||
return digest !== currentDigest;
|
if (!latestTagDigest) {
|
||||||
|
return { latestVersion: null, updateAvailable: false };
|
||||||
|
}
|
||||||
|
|
||||||
|
const versionedTag = results.find(
|
||||||
|
(t) => t.digest === latestTagDigest && t.name.startsWith("v"),
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!versionedTag) {
|
||||||
|
return { latestVersion: null, updateAvailable: false };
|
||||||
|
}
|
||||||
|
|
||||||
|
const { name: latestVersion, digest } = versionedTag;
|
||||||
|
|
||||||
|
const updateAvailable = digest !== currentDigest;
|
||||||
|
|
||||||
|
return { latestVersion, updateAvailable };
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getDokployImage = () => {
|
export const getDokployImage = () => {
|
||||||
|
|||||||
Reference in New Issue
Block a user