chore: always return local version if update check fails (#485)

This commit is contained in:
Aveline 2025-05-20 14:57:57 +02:00 committed by GitHub
parent 66fbda864a
commit 860327bfcd
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 51 additions and 35 deletions

View File

@ -266,8 +266,13 @@ func rpcSetDevChannelState(enabled bool) error {
func rpcGetUpdateStatus() (*UpdateStatus, error) { func rpcGetUpdateStatus() (*UpdateStatus, error) {
includePreRelease := config.IncludePreRelease includePreRelease := config.IncludePreRelease
updateStatus, err := GetUpdateStatus(context.Background(), GetDeviceID(), 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 { 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 return updateStatus, nil

40
ota.go
View File

@ -41,6 +41,9 @@ type UpdateStatus struct {
Remote *UpdateMetadata `json:"remote"` Remote *UpdateMetadata `json:"remote"`
SystemUpdateAvailable bool `json:"systemUpdateAvailable"` SystemUpdateAvailable bool `json:"systemUpdateAvailable"`
AppUpdateAvailable bool `json:"appUpdateAvailable"` AppUpdateAvailable bool `json:"appUpdateAvailable"`
// for backwards compatibility
Error string `json:"error,omitempty"`
} }
const UpdateMetadataUrl = "https://api.jetkvm.com/releases" 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) { func GetUpdateStatus(ctx context.Context, deviceId string, includePreRelease bool) (*UpdateStatus, error) {
updateStatus := &UpdateStatus{}
// Get local versions // Get local versions
systemVersionLocal, appVersionLocal, err := GetLocalVersion() systemVersionLocal, appVersionLocal, err := GetLocalVersion()
if err != nil { 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 // Get remote metadata
remoteMetadata, err := fetchUpdateMetadata(ctx, deviceId, includePreRelease) remoteMetadata, err := fetchUpdateMetadata(ctx, deviceId, includePreRelease)
if err != nil { if err != nil {
return nil, fmt.Errorf("error checking for updates: %w", err) return updateStatus, fmt.Errorf("error checking for updates: %w", err)
}
// Build local UpdateMetadata
localMetadata := &LocalMetadata{
AppVersion: appVersionLocal.String(),
SystemVersion: systemVersionLocal.String(),
} }
updateStatus.Remote = remoteMetadata
// Get remote versions
systemVersionRemote, err := semver.NewVersion(remoteMetadata.SystemVersion) systemVersionRemote, err := semver.NewVersion(remoteMetadata.SystemVersion)
if err != nil { 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) appVersionRemote, err := semver.NewVersion(remoteMetadata.AppVersion)
if err != nil { 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) updateStatus.SystemUpdateAvailable = systemVersionRemote.GreaterThan(systemVersionLocal)
appUpdateAvailable := appVersionRemote.GreaterThan(appVersionLocal) updateStatus.AppUpdateAvailable = appVersionRemote.GreaterThan(appVersionLocal)
// Handle pre-release updates // Handle pre-release updates
isRemoteSystemPreRelease := systemVersionRemote.Prerelease() != "" isRemoteSystemPreRelease := systemVersionRemote.Prerelease() != ""
isRemoteAppPreRelease := appVersionRemote.Prerelease() != "" isRemoteAppPreRelease := appVersionRemote.Prerelease() != ""
if isRemoteSystemPreRelease && !includePreRelease { if isRemoteSystemPreRelease && !includePreRelease {
systemUpdateAvailable = false updateStatus.SystemUpdateAvailable = false
} }
if isRemoteAppPreRelease && !includePreRelease { if isRemoteAppPreRelease && !includePreRelease {
appUpdateAvailable = false updateStatus.AppUpdateAvailable = false
}
updateStatus := &UpdateStatus{
Local: localMetadata,
Remote: remoteMetadata,
SystemUpdateAvailable: systemUpdateAvailable,
AppUpdateAvailable: appUpdateAvailable,
} }
return updateStatus, nil return updateStatus, nil

View File

@ -43,9 +43,10 @@ export default function SettingsGeneralUpdateRoute() {
export interface SystemVersionInfo { export interface SystemVersionInfo {
local: { appVersion: string; systemVersion: string }; local: { appVersion: string; systemVersion: string };
remote: { appVersion: string; systemVersion: string }; remote?: { appVersion: string; systemVersion: string };
systemUpdateAvailable: boolean; systemUpdateAvailable: boolean;
appUpdateAvailable: boolean; appUpdateAvailable: boolean;
error?: string;
} }
export function Dialog({ export function Dialog({
@ -142,13 +143,19 @@ function LoadingState({
return new Promise<SystemVersionInfo>((resolve, reject) => { return new Promise<SystemVersionInfo>((resolve, reject) => {
send("getUpdateStatus", {}, async resp => { send("getUpdateStatus", {}, async resp => {
if ("error" in 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")); reject(new Error("Failed to check for updates"));
} else { } else {
const result = resp.result as SystemVersionInfo; const result = resp.result as SystemVersionInfo;
setAppVersion(result.local.appVersion); setAppVersion(result.local.appVersion);
setSystemVersion(result.local.systemVersion); 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( console.log(
`For ${type}:\n` + `For ${type}:\n` +
` Download Progress: ${downloadProgress}% (${otaState[`${type}DownloadProgress`]})\n` + ` Download Progress: ${downloadProgress}% (${otaState[`${type}DownloadProgress`]})\n` +
` Update Progress: ${updateProgress}% (${otaState[`${type}UpdateProgress`]})\n` + ` Update Progress: ${updateProgress}% (${otaState[`${type}UpdateProgress`]})\n` +
` Verification Progress: ${verificationProgress}% (${otaState[`${type}VerificationProgress`]})`, ` Verification Progress: ${verificationProgress}% (${otaState[`${type}VerificationProgress`]})`,
); );
if (type === "app") { if (type === "app") {
@ -442,13 +449,14 @@ function UpdateAvailableState({
{versionInfo?.systemUpdateAvailable ? ( {versionInfo?.systemUpdateAvailable ? (
<> <>
<span className="font-semibold">System:</span>{" "} <span className="font-semibold">System:</span>{" "}
{versionInfo?.remote.systemVersion} {versionInfo?.remote?.systemVersion}
<br /> <br />
</> </>
) : null} ) : null}
{versionInfo?.appUpdateAvailable ? ( {versionInfo?.appUpdateAvailable ? (
<> <>
<span className="font-semibold">App:</span> {versionInfo?.remote.appVersion} <span className="font-semibold">App:</span>{" "}
{versionInfo?.remote?.appVersion}
</> </>
) : null} ) : null}
</p> </p>

View File

@ -703,12 +703,17 @@ export default function KvmIdRoute() {
send("getUpdateStatus", {}, async resp => { send("getUpdateStatus", {}, async resp => {
if ("error" in resp) { if ("error" in resp) {
notifications.error("Failed to get device version"); notifications.error(`Failed to get device version: ${resp.error}`);
} else { return
const result = resp.result as SystemVersionInfo;
setAppVersion(result.local.appVersion);
setSystemVersion(result.local.systemVersion);
} }
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]); }, [appVersion, send, setAppVersion, setSystemVersion]);