diff --git a/internal/ota/logger.go b/internal/ota/logger.go deleted file mode 100644 index a13036de..00000000 --- a/internal/ota/logger.go +++ /dev/null @@ -1,5 +0,0 @@ -package ota - -import "github.com/jetkvm/kvm/internal/logging" - -var logger = logging.GetSubsystemLogger("ota") diff --git a/internal/ota/ota.go b/internal/ota/ota.go index 366ea922..9e40e840 100644 --- a/internal/ota/ota.go +++ b/internal/ota/ota.go @@ -6,6 +6,7 @@ import ( "fmt" "net/http" "net/url" + "slices" "time" "github.com/Masterminds/semver/v3" @@ -59,6 +60,10 @@ func (s *State) fetchUpdateMetadata(ctx context.Context, params UpdateParams) (* return nil, fmt.Errorf("error getting update URL: %w", err) } + s.l.Trace(). + Str("url", url). + Msg("fetching update metadata") + req, err := http.NewRequestWithContext(ctx, "GET", url, nil) if err != nil { return nil, fmt.Errorf("error creating request: %w", err) @@ -107,6 +112,16 @@ func (s *State) doUpdate(ctx context.Context, params UpdateParams) error { return fmt.Errorf("update already in progress") } + if len(params.Components) == 0 { + params.Components = []string{"app", "system"} + } + shouldUpdateApp := slices.Contains(params.Components, "app") + shouldUpdateSystem := slices.Contains(params.Components, "system") + + if !shouldUpdateApp && !shouldUpdateSystem { + return fmt.Errorf("no components to update") + } + if !params.CheckOnly { s.updating = true s.triggerStateUpdate() @@ -128,12 +143,12 @@ func (s *State) doUpdate(ctx context.Context, params UpdateParams) error { return nil } - if appUpdate.available || appUpdate.downgradeAvailable { + if shouldUpdateApp && (appUpdate.available || appUpdate.downgradeAvailable) { appUpdate.pending = true s.triggerComponentUpdateState("app", appUpdate) } - if systemUpdate.available || systemUpdate.downgradeAvailable { + if shouldUpdateSystem && (systemUpdate.available || systemUpdate.downgradeAvailable) { systemUpdate.pending = true s.triggerComponentUpdateState("system", systemUpdate) } @@ -177,11 +192,12 @@ func (s *State) doUpdate(ctx context.Context, params UpdateParams) error { // UpdateParams represents the parameters for the update type UpdateParams struct { - DeviceID string `json:"deviceID"` - AppTargetVersion string `json:"appTargetVersion"` - SystemTargetVersion string `json:"systemTargetVersion"` - IncludePreRelease bool `json:"includePreRelease"` - CheckOnly bool `json:"checkOnly"` + DeviceID string `json:"deviceID"` + AppTargetVersion string `json:"appTargetVersion"` + SystemTargetVersion string `json:"systemTargetVersion"` + Components []string `json:"components,omitempty"` + IncludePreRelease bool `json:"includePreRelease"` + CheckOnly bool `json:"checkOnly"` } func (s *State) getUpdateStatus( diff --git a/internal/ota/state.go b/internal/ota/state.go index 9d9b8c01..0406b926 100644 --- a/internal/ota/state.go +++ b/internal/ota/state.go @@ -62,7 +62,7 @@ type componentUpdateStatus struct { verifiedAt time.Time updateProgress float32 updatedAt time.Time - dependsOn []string + dependsOn []string //nolint:unused } // RPCState represents the current OTA state for the RPC API diff --git a/internal/ota/sys.go b/internal/ota/sys.go index 575cf634..465b9a4d 100644 --- a/internal/ota/sys.go +++ b/internal/ota/sys.go @@ -84,6 +84,8 @@ func (s *State) updateSystem(ctx context.Context, systemUpdate *componentUpdateS return s.componentUpdateError("Error executing rk_ota command", err, &rkLogger) } rkLogger.Info().Msg("rk_ota success") + + s.rebootNeeded = true systemUpdate.updateProgress = 1 systemUpdate.updatedAt = verifyFinished s.triggerComponentUpdateState("system", systemUpdate) diff --git a/ota.go b/ota.go index 921cd353..dd761bdc 100644 --- a/ota.go +++ b/ota.go @@ -137,6 +137,7 @@ func rpcGetLocalVersion() (*ota.LocalMetadata, error) { type tryUpdateComponents struct { AppTargetVersion string `json:"app"` SystemTargetVersion string `json:"system"` + Components string `json:"components,omitempty"` // components is a comma-separated list of components to update } func rpcTryUpdate() error { @@ -155,17 +156,18 @@ func rpcTryUpdateComponents(components tryUpdateComponents, includePreRelease bo logger.Info().Interface("components", components).Msg("components") - if components.AppTargetVersion != "" { - updateParams.AppTargetVersion = components.AppTargetVersion - if err := otaState.SetTargetVersion("app", components.AppTargetVersion); err != nil { - return fmt.Errorf("failed to set app target version: %w", err) - } + updateParams.AppTargetVersion = components.AppTargetVersion + if err := otaState.SetTargetVersion("app", components.AppTargetVersion); err != nil { + return fmt.Errorf("failed to set app target version: %w", err) } - if components.SystemTargetVersion != "" { - updateParams.SystemTargetVersion = components.SystemTargetVersion - if err := otaState.SetTargetVersion("system", components.SystemTargetVersion); err != nil { - return fmt.Errorf("failed to set system target version: %w", err) - } + + updateParams.SystemTargetVersion = components.SystemTargetVersion + if err := otaState.SetTargetVersion("system", components.SystemTargetVersion); err != nil { + return fmt.Errorf("failed to set system target version: %w", err) + } + + if components.Components != "" { + updateParams.Components = strings.Split(components.Components, ",") } go func() { diff --git a/ui/src/hooks/useVersion.tsx b/ui/src/hooks/useVersion.tsx index 8e24116b..64b0c617 100644 --- a/ui/src/hooks/useVersion.tsx +++ b/ui/src/hooks/useVersion.tsx @@ -1,11 +1,11 @@ import { useCallback, useMemo } from "react"; +import semver from "semver"; import { useDeviceStore } from "@/hooks/stores"; import { JsonRpcError, RpcMethodNotFound } from "@/hooks/useJsonRpc"; import { getUpdateStatus, getLocalVersion as getLocalVersionRpc } from "@/utils/jsonrpc"; import notifications from "@/notifications"; import { m } from "@localizations/messages.js"; -import semver from "semver"; export interface VersionInfo { appVersion: string; diff --git a/ui/src/routes/devices.$id.settings.advanced.tsx b/ui/src/routes/devices.$id.settings.advanced.tsx index b90b874c..39fe73d3 100644 --- a/ui/src/routes/devices.$id.settings.advanced.tsx +++ b/ui/src/routes/devices.$id.settings.advanced.tsx @@ -197,10 +197,14 @@ export default function SettingsAdvancedRoute() { ); return; } + const pageParams = new URLSearchParams(); + pageParams.set("downgrade", "true"); + pageParams.set("components", updateTarget == "both" ? "app,system" : updateTarget); + // Navigate to update page - navigateTo("/settings/general/update"); + navigateTo(`/settings/general/update?${pageParams.toString()}`); }); - }, [appVersion, systemVersion, devChannel, send, navigateTo]); + }, [updateTarget,appVersion, systemVersion, devChannel, send, navigateTo]); return (