From 860327bfcd7bc7dc2c00f2ba2f4ada745e6c0bba Mon Sep 17 00:00:00 2001 From: Aveline <352441+ym@users.noreply.github.com> Date: Tue, 20 May 2025 14:57:57 +0200 Subject: [PATCH] chore: always return local version if update check fails (#485) --- jsonrpc.go | 7 +++- ota.go | 40 +++++++++---------- .../devices.$id.settings.general.update.tsx | 24 +++++++---- ui/src/routes/devices.$id.tsx | 15 ++++--- 4 files changed, 51 insertions(+), 35 deletions(-) diff --git a/jsonrpc.go b/jsonrpc.go index db9b680..ca9cd34 100644 --- a/jsonrpc.go +++ b/jsonrpc.go @@ -266,8 +266,13 @@ func rpcSetDevChannelState(enabled bool) error { func rpcGetUpdateStatus() (*UpdateStatus, error) { includePreRelease := config.IncludePreRelease updateStatus, err := GetUpdateStatus(context.Background(), GetDeviceID(), includePreRelease) + // to ensure backwards compatibility, + // if there's an error, we won't return an error, but we will set the error field if err != nil { - return nil, fmt.Errorf("error checking for updates: %w", err) + if updateStatus == nil { + return nil, fmt.Errorf("error checking for updates: %w", err) + } + updateStatus.Error = err.Error() } return updateStatus, nil diff --git a/ota.go b/ota.go index 0559978..cf97cc0 100644 --- a/ota.go +++ b/ota.go @@ -41,6 +41,9 @@ type UpdateStatus struct { Remote *UpdateMetadata `json:"remote"` SystemUpdateAvailable bool `json:"systemUpdateAvailable"` AppUpdateAvailable bool `json:"appUpdateAvailable"` + + // for backwards compatibility + Error string `json:"error,omitempty"` } const UpdateMetadataUrl = "https://api.jetkvm.com/releases" @@ -489,52 +492,47 @@ func TryUpdate(ctx context.Context, deviceId string, includePreRelease bool) err } func GetUpdateStatus(ctx context.Context, deviceId string, includePreRelease bool) (*UpdateStatus, error) { + updateStatus := &UpdateStatus{} + // Get local versions systemVersionLocal, appVersionLocal, err := GetLocalVersion() if err != nil { - return nil, fmt.Errorf("error getting local version: %w", err) + return updateStatus, fmt.Errorf("error getting local version: %w", err) + } + updateStatus.Local = &LocalMetadata{ + AppVersion: appVersionLocal.String(), + SystemVersion: systemVersionLocal.String(), } // Get remote metadata remoteMetadata, err := fetchUpdateMetadata(ctx, deviceId, includePreRelease) if err != nil { - return nil, fmt.Errorf("error checking for updates: %w", err) - } - - // Build local UpdateMetadata - localMetadata := &LocalMetadata{ - AppVersion: appVersionLocal.String(), - SystemVersion: systemVersionLocal.String(), + return updateStatus, fmt.Errorf("error checking for updates: %w", err) } + updateStatus.Remote = remoteMetadata + // Get remote versions systemVersionRemote, err := semver.NewVersion(remoteMetadata.SystemVersion) if err != nil { - return nil, fmt.Errorf("error parsing remote system version: %w", err) + return updateStatus, fmt.Errorf("error parsing remote system version: %w", err) } appVersionRemote, err := semver.NewVersion(remoteMetadata.AppVersion) if err != nil { - return nil, fmt.Errorf("error parsing remote app version: %w, %s", err, remoteMetadata.AppVersion) + return updateStatus, fmt.Errorf("error parsing remote app version: %w, %s", err, remoteMetadata.AppVersion) } - systemUpdateAvailable := systemVersionRemote.GreaterThan(systemVersionLocal) - appUpdateAvailable := appVersionRemote.GreaterThan(appVersionLocal) + updateStatus.SystemUpdateAvailable = systemVersionRemote.GreaterThan(systemVersionLocal) + updateStatus.AppUpdateAvailable = appVersionRemote.GreaterThan(appVersionLocal) // Handle pre-release updates isRemoteSystemPreRelease := systemVersionRemote.Prerelease() != "" isRemoteAppPreRelease := appVersionRemote.Prerelease() != "" if isRemoteSystemPreRelease && !includePreRelease { - systemUpdateAvailable = false + updateStatus.SystemUpdateAvailable = false } if isRemoteAppPreRelease && !includePreRelease { - appUpdateAvailable = false - } - - updateStatus := &UpdateStatus{ - Local: localMetadata, - Remote: remoteMetadata, - SystemUpdateAvailable: systemUpdateAvailable, - AppUpdateAvailable: appUpdateAvailable, + updateStatus.AppUpdateAvailable = false } return updateStatus, nil diff --git a/ui/src/routes/devices.$id.settings.general.update.tsx b/ui/src/routes/devices.$id.settings.general.update.tsx index c62b784..7c41449 100644 --- a/ui/src/routes/devices.$id.settings.general.update.tsx +++ b/ui/src/routes/devices.$id.settings.general.update.tsx @@ -43,9 +43,10 @@ export default function SettingsGeneralUpdateRoute() { export interface SystemVersionInfo { local: { appVersion: string; systemVersion: string }; - remote: { appVersion: string; systemVersion: string }; + remote?: { appVersion: string; systemVersion: string }; systemUpdateAvailable: boolean; appUpdateAvailable: boolean; + error?: string; } export function Dialog({ @@ -142,13 +143,19 @@ function LoadingState({ return new Promise((resolve, reject) => { send("getUpdateStatus", {}, async resp => { if ("error" in resp) { - notifications.error("Failed to check for updates"); + notifications.error(`Failed to check for updates: ${resp.error}`); reject(new Error("Failed to check for updates")); } else { const result = resp.result as SystemVersionInfo; setAppVersion(result.local.appVersion); setSystemVersion(result.local.systemVersion); - resolve(result); + + if (result.error) { + notifications.error(`Failed to check for updates: ${result.error}`); + reject(new Error("Failed to check for updates")); + } else { + resolve(result); + } } }); }); @@ -235,9 +242,9 @@ function UpdatingDeviceState({ console.log( `For ${type}:\n` + - ` Download Progress: ${downloadProgress}% (${otaState[`${type}DownloadProgress`]})\n` + - ` Update Progress: ${updateProgress}% (${otaState[`${type}UpdateProgress`]})\n` + - ` Verification Progress: ${verificationProgress}% (${otaState[`${type}VerificationProgress`]})`, + ` Download Progress: ${downloadProgress}% (${otaState[`${type}DownloadProgress`]})\n` + + ` Update Progress: ${updateProgress}% (${otaState[`${type}UpdateProgress`]})\n` + + ` Verification Progress: ${verificationProgress}% (${otaState[`${type}VerificationProgress`]})`, ); if (type === "app") { @@ -442,13 +449,14 @@ function UpdateAvailableState({ {versionInfo?.systemUpdateAvailable ? ( <> System:{" "} - {versionInfo?.remote.systemVersion} + {versionInfo?.remote?.systemVersion}
) : null} {versionInfo?.appUpdateAvailable ? ( <> - App: {versionInfo?.remote.appVersion} + App:{" "} + {versionInfo?.remote?.appVersion} ) : null}

diff --git a/ui/src/routes/devices.$id.tsx b/ui/src/routes/devices.$id.tsx index 7361876..d35915b 100644 --- a/ui/src/routes/devices.$id.tsx +++ b/ui/src/routes/devices.$id.tsx @@ -703,12 +703,17 @@ export default function KvmIdRoute() { send("getUpdateStatus", {}, async resp => { if ("error" in resp) { - notifications.error("Failed to get device version"); - } else { - const result = resp.result as SystemVersionInfo; - setAppVersion(result.local.appVersion); - setSystemVersion(result.local.systemVersion); + notifications.error(`Failed to get device version: ${resp.error}`); + return } + + const result = resp.result as SystemVersionInfo; + if (result.error) { + notifications.error(`Failed to get device version: ${result.error}`); + } + + setAppVersion(result.local.appVersion); + setSystemVersion(result.local.systemVersion); }); }, [appVersion, send, setAppVersion, setSystemVersion]);