Skip to content

Commit 329ad02

Browse files
committed
fix: should return error if version is not available
1 parent 252dcba commit 329ad02

File tree

5 files changed

+61
-9
lines changed

5 files changed

+61
-9
lines changed

internal/ota/errors.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package ota
2+
3+
import "errors"
4+
5+
var (
6+
// ErrVersionNotFound is returned when the specified version is not found
7+
ErrVersionNotFound = errors.New("specified version not found")
8+
)

internal/ota/ota.go

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package ota
33
import (
44
"context"
55
"encoding/json"
6+
"errors"
67
"fmt"
78
"net/http"
89
"net/url"
@@ -23,12 +24,14 @@ func (s *State) GetReleaseAPIEndpoint() string {
2324
}
2425

2526
// getUpdateURL returns the update URL for the given parameters
26-
func (s *State) getUpdateURL(params UpdateParams) (string, error) {
27+
func (s *State) getUpdateURL(params UpdateParams) (string, error, bool) {
2728
updateURL, err := url.Parse(s.releaseAPIEndpoint)
2829
if err != nil {
29-
return "", fmt.Errorf("error parsing update metadata URL: %w", err)
30+
return "", fmt.Errorf("error parsing update metadata URL: %w", err), false
3031
}
3132

33+
isCustomVersion := false
34+
3235
appTargetVersion := s.GetTargetVersion("app")
3336
if appTargetVersion != "" && params.AppTargetVersion == "" {
3437
params.AppTargetVersion = appTargetVersion
@@ -43,19 +46,21 @@ func (s *State) getUpdateURL(params UpdateParams) (string, error) {
4346
query.Set("prerelease", fmt.Sprintf("%v", params.IncludePreRelease))
4447
if params.AppTargetVersion != "" {
4548
query.Set("appVersion", params.AppTargetVersion)
49+
isCustomVersion = true
4650
}
4751
if params.SystemTargetVersion != "" {
4852
query.Set("systemVersion", params.SystemTargetVersion)
53+
isCustomVersion = true
4954
}
5055
updateURL.RawQuery = query.Encode()
5156

52-
return updateURL.String(), nil
57+
return updateURL.String(), nil, isCustomVersion
5358
}
5459

5560
func (s *State) fetchUpdateMetadata(ctx context.Context, params UpdateParams) (*UpdateMetadata, error) {
5661
metadata := &UpdateMetadata{}
5762

58-
url, err := s.getUpdateURL(params)
63+
url, err, isCustomVersion := s.getUpdateURL(params)
5964
if err != nil {
6065
return nil, fmt.Errorf("error getting update URL: %w", err)
6166
}
@@ -77,6 +82,10 @@ func (s *State) fetchUpdateMetadata(ctx context.Context, params UpdateParams) (*
7782
}
7883
defer resp.Body.Close()
7984

85+
if isCustomVersion && resp.StatusCode == http.StatusNotFound {
86+
return nil, ErrVersionNotFound
87+
}
88+
8089
if resp.StatusCode != http.StatusOK {
8190
return nil, fmt.Errorf("unexpected status code: %d", resp.StatusCode)
8291
}
@@ -189,7 +198,7 @@ func (s *State) doUpdate(ctx context.Context, params UpdateParams) error {
189198

190199
postRebootAction := &PostRebootAction{
191200
HealthCheck: "/device/status",
192-
RedirectUrl: redirectUrl,
201+
RedirectTo: redirectUrl,
193202
}
194203

195204
if err := s.reboot(true, postRebootAction, 10*time.Second); err != nil {
@@ -241,7 +250,11 @@ func (s *State) getUpdateStatus(
241250
// Get remote metadata
242251
remoteMetadata, err := s.fetchUpdateMetadata(ctx, params)
243252
if err != nil {
244-
err = fmt.Errorf("error checking for updates: %w", err)
253+
if err == ErrVersionNotFound || errors.Unwrap(err) == ErrVersionNotFound {
254+
err = ErrVersionNotFound
255+
} else {
256+
err = fmt.Errorf("error checking for updates: %w", err)
257+
}
245258
return
246259
}
247260
appUpdate.url = remoteMetadata.AppURL

ota.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"net/http"
77
"os"
88
"strings"
9+
"time"
910

1011
"github.com/Masterminds/semver/v3"
1112
"github.com/jetkvm/kvm/internal/ota"
@@ -158,11 +159,15 @@ func rpcTryUpdateComponents(components tryUpdateComponents, includePreRelease bo
158159

159160
logger.Info().Interface("components", components).Msg("components")
160161

162+
currentAppTargetVersion := otaState.GetTargetVersion("app")
163+
appTargetVersionChanged := currentAppTargetVersion != components.AppTargetVersion
161164
updateParams.AppTargetVersion = components.AppTargetVersion
162165
if err := otaState.SetTargetVersion("app", components.AppTargetVersion); err != nil {
163166
return fmt.Errorf("failed to set app target version: %w", err)
164167
}
165168

169+
currentSystemTargetVersion := otaState.GetTargetVersion("system")
170+
systemTargetVersionChanged := currentSystemTargetVersion != components.SystemTargetVersion
166171
updateParams.SystemTargetVersion = components.SystemTargetVersion
167172
if err := otaState.SetTargetVersion("system", components.SystemTargetVersion); err != nil {
168173
return fmt.Errorf("failed to set system target version: %w", err)
@@ -172,6 +177,32 @@ func rpcTryUpdateComponents(components tryUpdateComponents, includePreRelease bo
172177
updateParams.Components = strings.Split(components.Components, ",")
173178
}
174179

180+
// if it's a check only update, we don't need to try to update, we just need to check if the version is available
181+
// and return the error immediately then revert the previous target versions
182+
if checkOnly {
183+
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
184+
defer cancel()
185+
186+
_, err := otaState.GetUpdateStatus(ctx, updateParams)
187+
if err == nil {
188+
return nil
189+
}
190+
191+
// revert the previous target versions
192+
if appTargetVersionChanged {
193+
if err := otaState.SetTargetVersion("app", currentAppTargetVersion); err != nil {
194+
return fmt.Errorf("failed to revert app target version: %w", err)
195+
}
196+
}
197+
if systemTargetVersionChanged {
198+
if err := otaState.SetTargetVersion("system", currentSystemTargetVersion); err != nil {
199+
return fmt.Errorf("failed to revert system target version: %w", err)
200+
}
201+
}
202+
203+
return err
204+
}
205+
175206
go func() {
176207
err := otaState.TryUpdate(context.Background(), updateParams)
177208
if err != nil {

ui/src/hooks/useVersion.tsx

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
import { useCallback, useMemo } from "react";
2-
import semver from "semver";
1+
import { useCallback } from "react";
32

43
import { useDeviceStore } from "@/hooks/stores";
54
import { JsonRpcError, RpcMethodNotFound } from "@/hooks/useJsonRpc";
@@ -69,6 +68,5 @@ export function useVersion() {
6968
getLocalVersion,
7069
appVersion,
7170
systemVersion,
72-
isOnDevVersion,
7371
};
7472
}

ui/src/utils/jsonrpc.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,9 @@ export interface SystemVersionInfo {
220220
local: VersionInfo;
221221
remote?: VersionInfo;
222222
systemUpdateAvailable: boolean;
223+
systemDowngradeAvailable: boolean;
223224
appUpdateAvailable: boolean;
225+
appDowngradeAvailable: boolean;
224226
error?: string;
225227
}
226228

0 commit comments

Comments
 (0)