diff --git a/apps/dashboard/src/@3rdweb-sdk/react/hooks/useEngine.ts b/apps/dashboard/src/@3rdweb-sdk/react/hooks/useEngine.ts index f7ceed81d11..549e3772aba 100644 --- a/apps/dashboard/src/@3rdweb-sdk/react/hooks/useEngine.ts +++ b/apps/dashboard/src/@3rdweb-sdk/react/hooks/useEngine.ts @@ -18,7 +18,6 @@ export type EngineInstance = { name: string; url: string; lastAccessedAt: string; - cloudDeployedAt?: string; status: | "active" | "pending" @@ -26,6 +25,7 @@ export type EngineInstance = { | "deploying" | "paymentFailed" | "deploymentFailed"; + deploymentId?: string; }; // Not checking for null token because the token is required the tanstack useQuery hook @@ -189,23 +189,26 @@ export function useEngineLatestVersion() { interface UpdateVersionInput { engineId: string; + serverVersion: string; } -export function useEngineUpdateVersion() { +export function useEngineUpdateServerVersion() { return useMutation({ mutationFn: async (input: UpdateVersionInput) => { invariant(input.engineId, "engineId is required"); - const res = await fetch(`${THIRDWEB_API_HOST}/v1/engine/update-version`, { - method: "POST", - - headers: { - "Content-Type": "application/json", + const res = await fetch( + `${THIRDWEB_API_HOST}/v2/engine/${input.engineId}/infrastructure`, + { + method: "PUT", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + serverVersion: input.serverVersion, + }), }, - body: JSON.stringify({ - engineId: input.engineId, - }), - }); + ); // we never use the response body res.body?.cancel(); if (!res.ok) { diff --git a/apps/dashboard/src/components/engine/badges/version.tsx b/apps/dashboard/src/components/engine/badges/version.tsx index 10c84f7e375..8a83dd86641 100644 --- a/apps/dashboard/src/components/engine/badges/version.tsx +++ b/apps/dashboard/src/components/engine/badges/version.tsx @@ -4,7 +4,7 @@ import { type EngineInstance, useEngineLatestVersion, useEngineSystemHealth, - useEngineUpdateVersion, + useEngineUpdateServerVersion, } from "@3rdweb-sdk/react/hooks/useEngine"; import { CircleArrowDownIcon, CloudDownloadIcon } from "lucide-react"; import { useState } from "react"; @@ -30,15 +30,15 @@ export const EngineVersionBadge = ({ const latestVersionQuery = useEngineLatestVersion(); const [isModalOpen, setModalOpen] = useState(false); - const current = healthQuery.data?.engineVersion ?? "..."; - const latest = latestVersionQuery.data ?? "..."; - const isStale = current !== latest; + const currentVersion = healthQuery.data?.engineVersion ?? "..."; + const latestVersion = latestVersionQuery.data; + const isStale = latestVersion && currentVersion !== latestVersion; if (!isStale) { return ( ); @@ -57,7 +57,7 @@ export const EngineVersionBadge = ({ className="relative" onClick={() => setModalOpen(true)} > - {current} + {currentVersion} {/* Notification Dot */} @@ -66,12 +66,14 @@ export const EngineVersionBadge = ({ - + {latestVersion && ( + + )} ); }; @@ -79,13 +81,13 @@ export const EngineVersionBadge = ({ const UpdateVersionModal = (props: { open: boolean; onOpenChange: (open: boolean) => void; - latest: string; + latestVersion: string; instance: EngineInstance; }) => { - const { open, onOpenChange, latest, instance } = props; - const updateEngine = useEngineUpdateVersion(); + const { open, onOpenChange, latestVersion, instance } = props; + const updateEngineServerMutation = useEngineUpdateServerVersion(); - if (!instance.cloudDeployedAt) { + if (!instance.deploymentId) { // For self-hosted, show a prompt to the Github release page. return ( @@ -95,10 +97,10 @@ const UpdateVersionModal = (props: { > - Update your self-hosted Engine to {latest} + Update your self-hosted Engine to {latestVersion} - View the changelog in the + View the{" "} - Engine Github repository + latest changelog + . @@ -117,11 +120,13 @@ const UpdateVersionModal = (props: { const onClick = async () => { try { - const promise = updateEngine.mutateAsync({ engineId: instance.id }); + const promise = updateEngineServerMutation.mutateAsync({ + engineId: instance.id, + serverVersion: latestVersion, + }); toast.promise(promise, { - success: - "Submitted a request to update your Engine instance. Please allow 1-2 business days for this process.", - error: "Unexpected error updating your Engine instance.", + success: `Upgrading your Engine to ${latestVersion}. Please confirm after a few minutes.`, + error: "Unexpected error updating your Engine.", }); await promise; } finally { @@ -136,7 +141,12 @@ const UpdateVersionModal = (props: { dialogOverlayClassName="z-[10000]" > - Update Engine to {latest}? + Update Engine to {latestVersion}? + + + It is recommended to pause traffic to Engine before performing this + upgrade. There is < 1 minute of expected downtime. + @@ -153,7 +163,7 @@ const UpdateVersionModal = (props: { variant="primary" className="gap-2" > - {updateEngine.isPending ? ( + {updateEngineServerMutation.isPending ? ( ) : ( diff --git a/apps/dashboard/src/components/engine/configuration/ip-allowlist.tsx b/apps/dashboard/src/components/engine/configuration/ip-allowlist.tsx index 1890e6e460d..632ffcca19f 100644 --- a/apps/dashboard/src/components/engine/configuration/ip-allowlist.tsx +++ b/apps/dashboard/src/components/engine/configuration/ip-allowlist.tsx @@ -87,7 +87,7 @@ export const EngineIpAllowlistConfig: React.FC<