Skip to content

Commit 9de79f3

Browse files
committed
add check for major relese update
1 parent 5be93c5 commit 9de79f3

File tree

7 files changed

+87
-36
lines changed

7 files changed

+87
-36
lines changed

cmd/arduino-app-cli/system/system.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ func NewSystemCmd(cfg config.Configuration) *cobra.Command {
4242
}
4343

4444
cmd.AddCommand(newDownloadImageCmd(cfg))
45-
cmd.AddCommand(newUpdateCmd())
45+
cmd.AddCommand(newUpdateCmd(cfg))
4646
cmd.AddCommand(newCleanUpCmd(cfg, servicelocator.GetDockerClient()))
4747
cmd.AddCommand(newNetworkModeCmd())
4848
cmd.AddCommand(newKeyboardSetCmd())
@@ -64,7 +64,7 @@ func newDownloadImageCmd(cfg config.Configuration) *cobra.Command {
6464
return cmd
6565
}
6666

67-
func newUpdateCmd() *cobra.Command {
67+
func newUpdateCmd(cfg config.Configuration) *cobra.Command {
6868
var onlyArduino bool
6969
var forceYes bool
7070
cmd := &cobra.Command{
@@ -76,7 +76,7 @@ func newUpdateCmd() *cobra.Command {
7676

7777
updater := getUpdater()
7878

79-
pkgs, err := updater.ListUpgradablePackages(cmd.Context(), filterFunc)
79+
pkgs, err := updater.ListUpgradablePackages(cfg, cmd.Context(), filterFunc)
8080
if err != nil {
8181
return err
8282
}

internal/api/api.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,9 +63,9 @@ func NewHTTPRouter(
6363
mux.Handle("PUT /v1/properties/{key}", handlers.HandlePropertyUpsert(cfg))
6464
mux.Handle("DELETE /v1/properties/{key}", handlers.HandlePropertyDelete(cfg))
6565

66-
mux.Handle("GET /v1/system/update/check", handlers.HandleCheckUpgradable(updater))
66+
mux.Handle("GET /v1/system/update/check", handlers.HandleCheckUpgradable(cfg, updater))
6767
mux.Handle("GET /v1/system/update/events", handlers.HandleUpdateEvents(updater))
68-
mux.Handle("PUT /v1/system/update/apply", handlers.HandleUpdateApply(updater))
68+
mux.Handle("PUT /v1/system/update/apply", handlers.HandleUpdateApply(cfg, updater))
6969
mux.Handle("GET /v1/system/resources", handlers.HandleSystemResources())
7070

7171
mux.Handle("GET /v1/models", handlers.HandleModelsList(modelsIndex))

internal/api/handlers/update.go

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,12 @@ import (
2323
"log/slog"
2424

2525
"github.com/arduino/arduino-app-cli/internal/api/models"
26+
"github.com/arduino/arduino-app-cli/internal/orchestrator/config"
2627
"github.com/arduino/arduino-app-cli/internal/render"
2728
"github.com/arduino/arduino-app-cli/internal/update"
2829
)
2930

30-
func HandleCheckUpgradable(updater *update.Manager) http.HandlerFunc {
31+
func HandleCheckUpgradable(cfg config.Configuration, updater *update.Manager) http.HandlerFunc {
3132
return func(w http.ResponseWriter, r *http.Request) {
3233
queryParams := r.URL.Query()
3334

@@ -41,7 +42,7 @@ func HandleCheckUpgradable(updater *update.Manager) http.HandlerFunc {
4142
filterFunc = update.MatchArduinoPackage
4243
}
4344

44-
pkgs, err := updater.ListUpgradablePackages(r.Context(), filterFunc)
45+
pkgs, err := updater.ListUpgradablePackages(cfg, r.Context(), filterFunc)
4546
if err != nil {
4647
if errors.Is(err, update.ErrOperationAlreadyInProgress) {
4748
render.EncodeResponse(w, http.StatusConflict, models.ErrorResponse{Details: err.Error()})
@@ -64,7 +65,7 @@ type UpdateCheckResult struct {
6465
Packages []update.UpgradablePackage `json:"updates"`
6566
}
6667

67-
func HandleUpdateApply(updater *update.Manager) http.HandlerFunc {
68+
func HandleUpdateApply(cfg config.Configuration, updater *update.Manager) http.HandlerFunc {
6869
return func(w http.ResponseWriter, r *http.Request) {
6970
queryParams := r.URL.Query()
7071
onlyArduinoPackages := false
@@ -77,7 +78,7 @@ func HandleUpdateApply(updater *update.Manager) http.HandlerFunc {
7778
filterFunc = update.MatchArduinoPackage
7879
}
7980

80-
pkgs, err := updater.ListUpgradablePackages(r.Context(), filterFunc)
81+
pkgs, err := updater.ListUpgradablePackages(cfg, r.Context(), filterFunc)
8182
if err != nil {
8283
if errors.Is(err, update.ErrOperationAlreadyInProgress) {
8384
render.EncodeResponse(w, http.StatusConflict, models.ErrorResponse{Details: err.Error()})

internal/orchestrator/config/config.go

Lines changed: 27 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -31,15 +31,16 @@ import (
3131
var runnerVersion = "0.5.0"
3232

3333
type Configuration struct {
34-
appsDir *paths.Path
35-
dataDir *paths.Path
36-
routerSocketPath *paths.Path
37-
customEIModelsDir *paths.Path
38-
PythonImage string
39-
UsedPythonImageTag string
40-
RunnerVersion string
41-
AllowRoot bool
42-
LibrariesAPIURL *url.URL
34+
appsDir *paths.Path
35+
dataDir *paths.Path
36+
routerSocketPath *paths.Path
37+
customEIModelsDir *paths.Path
38+
PythonImage string
39+
UsedPythonImageTag string
40+
RunnerVersion string
41+
AllowRoot bool
42+
LibrariesAPIURL *url.URL
43+
MaxAllowedMajorVersion int
4344
}
4445

4546
func NewFromEnv() (Configuration, error) {
@@ -105,17 +106,25 @@ func NewFromEnv() (Configuration, error) {
105106
if err != nil {
106107
return Configuration{}, fmt.Errorf("invalid LIBRARIES_API_URL: %w", err)
107108
}
109+
maxVersionStr := os.Getenv("ARDUINO_APP_CLI__MAX_UPDATE_MAJOR_VERSION")
110+
111+
maxVersion, err := strconv.Atoi(maxVersionStr)
112+
if err != nil || maxVersion <= 0 {
113+
maxVersion = 1
114+
}
115+
slog.Debug("Using max update major version", slog.Int("version", maxVersion))
108116

109117
c := Configuration{
110-
appsDir: appsDir,
111-
dataDir: dataDir,
112-
routerSocketPath: routerSocket,
113-
customEIModelsDir: customEIModelsDir,
114-
PythonImage: pythonImage,
115-
UsedPythonImageTag: usedPythonImageTag,
116-
RunnerVersion: runnerVersion,
117-
AllowRoot: allowRoot,
118-
LibrariesAPIURL: parsedLibrariesURL,
118+
appsDir: appsDir,
119+
dataDir: dataDir,
120+
routerSocketPath: routerSocket,
121+
customEIModelsDir: customEIModelsDir,
122+
PythonImage: pythonImage,
123+
UsedPythonImageTag: usedPythonImageTag,
124+
RunnerVersion: runnerVersion,
125+
AllowRoot: allowRoot,
126+
LibrariesAPIURL: parsedLibrariesURL,
127+
MaxAllowedMajorVersion: maxVersion,
119128
}
120129
if err := c.init(); err != nil {
121130
return Configuration{}, err

internal/update/apt/service.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import (
3131
"go.bug.st/f"
3232

3333
"github.com/arduino/arduino-app-cli/internal/orchestrator"
34+
"github.com/arduino/arduino-app-cli/internal/orchestrator/config"
3435
"github.com/arduino/arduino-app-cli/internal/update"
3536
)
3637

@@ -48,7 +49,7 @@ func New() *Service {
4849
// It runs the `apt-get update` command before listing the packages to ensure the package list is up to date.
4950
// It filters the packages using the provided matcher function.
5051
// It returns a slice of UpgradablePackage or an error if the command fails.
51-
func (s *Service) ListUpgradablePackages(ctx context.Context, matcher func(update.UpgradablePackage) bool) ([]update.UpgradablePackage, error) {
52+
func (s *Service) ListUpgradablePackages(cfg config.Configuration, ctx context.Context, matcher func(update.UpgradablePackage) bool) ([]update.UpgradablePackage, error) {
5253
if !s.lock.TryLock() {
5354
return nil, update.ErrOperationAlreadyInProgress
5455
}

internal/update/arduino/arduino.go

Lines changed: 42 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,15 @@ import (
2222
"sync"
2323
"time"
2424

25+
"github.com/Masterminds/semver/v3"
2526
"github.com/arduino/arduino-cli/commands"
2627
"github.com/arduino/arduino-cli/commands/cmderrors"
2728
rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1"
2829
"github.com/sirupsen/logrus"
2930

3031
"github.com/arduino/arduino-app-cli/internal/helpers"
3132
"github.com/arduino/arduino-app-cli/internal/orchestrator"
33+
"github.com/arduino/arduino-app-cli/internal/orchestrator/config"
3234
"github.com/arduino/arduino-app-cli/internal/update"
3335
)
3436

@@ -53,7 +55,7 @@ func setConfig(ctx context.Context, srv rpc.ArduinoCoreServiceServer) error {
5355
}
5456

5557
// ListUpgradablePackages implements ServiceUpdater.
56-
func (a *ArduinoPlatformUpdater) ListUpgradablePackages(ctx context.Context, _ func(update.UpgradablePackage) bool) ([]update.UpgradablePackage, error) {
58+
func (a *ArduinoPlatformUpdater) ListUpgradablePackages(cfg config.Configuration, ctx context.Context, _ func(update.UpgradablePackage) bool) ([]update.UpgradablePackage, error) {
5759
if !a.lock.TryLock() {
5860
return nil, update.ErrOperationAlreadyInProgress
5961
}
@@ -112,15 +114,51 @@ func (a *ArduinoPlatformUpdater) ListUpgradablePackages(ctx context.Context, _ f
112114
return nil, nil // No platform found
113115
}
114116

115-
if platformSummary.GetLatestVersion() == platformSummary.GetInstalledVersion() {
116-
return nil, nil // No update available
117+
installedVersionString := platformSummary.GetInstalledVersion()
118+
119+
installedV, err := semver.NewVersion(installedVersionString)
120+
if err != nil {
121+
slog.Warn("Failed to parse installed version", "version", installedVersionString, "error", err)
122+
return nil, nil
123+
}
124+
125+
var maxMajor uint64
126+
if cfg.MaxAllowedMajorVersion > 0 {
127+
maxMajor = uint64(cfg.MaxAllowedMajorVersion)
117128
}
129+
var bestUpdateV *semver.Version
130+
131+
allReleases := platformSummary.GetReleases()
132+
for versionString := range allReleases {
133+
candidateV, err := semver.NewVersion(versionString)
134+
if err != nil {
135+
slog.Debug("Skipping unparsable version", "version", versionString, "error", err)
136+
continue
137+
}
118138

139+
if candidateV.Major() > maxMajor {
140+
continue
141+
}
142+
143+
if !candidateV.GreaterThan(installedV) {
144+
continue
145+
}
146+
147+
if bestUpdateV == nil || candidateV.GreaterThan(bestUpdateV) {
148+
bestUpdateV = candidateV
149+
}
150+
}
151+
if bestUpdateV == nil {
152+
slog.Debug("No suitable updates found within major version constraint")
153+
return nil, nil
154+
}
155+
slog.Debug(" bestUpdateV.Original()", bestUpdateV.Original(), "")
156+
slog.Debug(" bestUpdateV.String()", bestUpdateV.String(), "")
119157
return []update.UpgradablePackage{{
120158
Type: update.Arduino,
121159
Name: "arduino:zephyr",
122160
FromVersion: platformSummary.GetInstalledVersion(),
123-
ToVersion: platformSummary.GetLatestVersion(),
161+
ToVersion: bestUpdateV.Original(),
124162
}}, nil
125163
}
126164

internal/update/update.go

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ import (
2626
"time"
2727

2828
"golang.org/x/sync/errgroup"
29+
30+
"github.com/arduino/arduino-app-cli/internal/orchestrator/config"
2931
)
3032

3133
var ErrOperationAlreadyInProgress = errors.New("an operation is already in progress")
@@ -48,7 +50,7 @@ type UpgradablePackage struct {
4850
}
4951

5052
type ServiceUpdater interface {
51-
ListUpgradablePackages(ctx context.Context, matcher func(UpgradablePackage) bool) ([]UpgradablePackage, error)
53+
ListUpgradablePackages(cfg config.Configuration, ctx context.Context, matcher func(UpgradablePackage) bool) ([]UpgradablePackage, error)
5254
UpgradePackages(ctx context.Context, names []string) (<-chan Event, error)
5355
}
5456

@@ -69,7 +71,7 @@ func NewManager(debUpdateService ServiceUpdater, arduinoPlatformUpdateService Se
6971
}
7072
}
7173

72-
func (m *Manager) ListUpgradablePackages(ctx context.Context, matcher func(UpgradablePackage) bool) ([]UpgradablePackage, error) {
74+
func (m *Manager) ListUpgradablePackages(cfg config.Configuration, ctx context.Context, matcher func(UpgradablePackage) bool) ([]UpgradablePackage, error) {
7375
if !m.lock.TryLock() {
7476
return nil, ErrOperationAlreadyInProgress
7577
}
@@ -89,7 +91,7 @@ func (m *Manager) ListUpgradablePackages(ctx context.Context, matcher func(Upgra
8991
)
9092

9193
g.Go(func() error {
92-
pkgs, err := m.debUpdateService.ListUpgradablePackages(ctx, matcher)
94+
pkgs, err := m.debUpdateService.ListUpgradablePackages(cfg, ctx, matcher)
9395
if err != nil {
9496
return err
9597
}
@@ -98,7 +100,7 @@ func (m *Manager) ListUpgradablePackages(ctx context.Context, matcher func(Upgra
98100
})
99101

100102
g.Go(func() error {
101-
pkgs, err := m.arduinoPlatformUpdateService.ListUpgradablePackages(ctx, matcher)
103+
pkgs, err := m.arduinoPlatformUpdateService.ListUpgradablePackages(cfg, ctx, matcher)
102104
if err != nil {
103105
return err
104106
}

0 commit comments

Comments
 (0)