Skip to content

Commit e66a3d8

Browse files
committed
add check for major relese update
1 parent fa54e74 commit e66a3d8

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
@@ -22,11 +22,12 @@ import (
2222
"log/slog"
2323

2424
"github.com/arduino/arduino-app-cli/internal/api/models"
25+
"github.com/arduino/arduino-app-cli/internal/orchestrator/config"
2526
"github.com/arduino/arduino-app-cli/internal/render"
2627
"github.com/arduino/arduino-app-cli/internal/update"
2728
)
2829

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

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

43-
pkgs, err := updater.ListUpgradablePackages(r.Context(), filterFunc)
44+
pkgs, err := updater.ListUpgradablePackages(cfg, r.Context(), filterFunc)
4445
if err != nil {
4546
code := update.GetUpdateErrorCode(err)
4647
if code == update.OperationInProgressCode {
@@ -69,7 +70,7 @@ type UpdateCheckResult struct {
6970
Packages []update.UpgradablePackage `json:"updates"`
7071
}
7172

72-
func HandleUpdateApply(updater *update.Manager) http.HandlerFunc {
73+
func HandleUpdateApply(cfg config.Configuration, updater *update.Manager) http.HandlerFunc {
7374
return func(w http.ResponseWriter, r *http.Request) {
7475
queryParams := r.URL.Query()
7576
onlyArduinoPackages := false
@@ -82,7 +83,7 @@ func HandleUpdateApply(updater *update.Manager) http.HandlerFunc {
8283
filterFunc = update.MatchArduinoPackage
8384
}
8485

85-
pkgs, err := updater.ListUpgradablePackages(r.Context(), filterFunc)
86+
pkgs, err := updater.ListUpgradablePackages(cfg, r.Context(), filterFunc)
8687
if err != nil {
8788
code := update.GetUpdateErrorCode(err)
8889
if code == update.OperationInProgressCode {

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.6.1"
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
@@ -30,6 +30,7 @@ import (
3030
"go.bug.st/f"
3131

3232
"github.com/arduino/arduino-app-cli/internal/orchestrator"
33+
"github.com/arduino/arduino-app-cli/internal/orchestrator/config"
3334
"github.com/arduino/arduino-app-cli/internal/update"
3435
)
3536

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

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
"log/slog"
2323
"sync"
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
}
@@ -121,15 +123,51 @@ func (a *ArduinoPlatformUpdater) ListUpgradablePackages(ctx context.Context, _ f
121123
return nil, nil // No platform found
122124
}
123125

124-
if platformSummary.GetLatestVersion() == platformSummary.GetInstalledVersion() {
125-
return nil, nil // No update available
126+
installedVersionString := platformSummary.GetInstalledVersion()
127+
128+
installedV, err := semver.NewVersion(installedVersionString)
129+
if err != nil {
130+
slog.Warn("Failed to parse installed version", "version", installedVersionString, "error", err)
131+
return nil, nil
132+
}
133+
134+
var maxMajor uint64
135+
if cfg.MaxAllowedMajorVersion > 0 {
136+
maxMajor = uint64(cfg.MaxAllowedMajorVersion)
126137
}
138+
var bestUpdateV *semver.Version
139+
140+
allReleases := platformSummary.GetReleases()
141+
for versionString := range allReleases {
142+
candidateV, err := semver.NewVersion(versionString)
143+
if err != nil {
144+
slog.Debug("Skipping unparsable version", "version", versionString, "error", err)
145+
continue
146+
}
127147

148+
if candidateV.Major() > maxMajor {
149+
continue
150+
}
151+
152+
if !candidateV.GreaterThan(installedV) {
153+
continue
154+
}
155+
156+
if bestUpdateV == nil || candidateV.GreaterThan(bestUpdateV) {
157+
bestUpdateV = candidateV
158+
}
159+
}
160+
if bestUpdateV == nil {
161+
slog.Debug("No suitable updates found within major version constraint")
162+
return nil, nil
163+
}
164+
slog.Debug(" bestUpdateV.Original()", bestUpdateV.Original(), "")
165+
slog.Debug(" bestUpdateV.String()", bestUpdateV.String(), "")
128166
return []update.UpgradablePackage{{
129167
Type: update.Arduino,
130168
Name: "arduino:zephyr",
131169
FromVersion: platformSummary.GetInstalledVersion(),
132-
ToVersion: platformSummary.GetLatestVersion(),
170+
ToVersion: bestUpdateV.Original(),
133171
}}, nil
134172
}
135173

internal/update/update.go

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

2727
"golang.org/x/sync/errgroup"
28+
29+
"github.com/arduino/arduino-app-cli/internal/orchestrator/config"
2830
)
2931

3032
var MatchArduinoPackage = func(p UpgradablePackage) bool {
@@ -45,7 +47,7 @@ type UpgradablePackage struct {
4547
}
4648

4749
type ServiceUpdater interface {
48-
ListUpgradablePackages(ctx context.Context, matcher func(UpgradablePackage) bool) ([]UpgradablePackage, error)
50+
ListUpgradablePackages(cfg config.Configuration, ctx context.Context, matcher func(UpgradablePackage) bool) ([]UpgradablePackage, error)
4951
UpgradePackages(ctx context.Context, names []string) (<-chan Event, error)
5052
}
5153

@@ -66,7 +68,7 @@ func NewManager(debUpdateService ServiceUpdater, arduinoPlatformUpdateService Se
6668
}
6769
}
6870

69-
func (m *Manager) ListUpgradablePackages(ctx context.Context, matcher func(UpgradablePackage) bool) ([]UpgradablePackage, error) {
71+
func (m *Manager) ListUpgradablePackages(cfg config.Configuration, ctx context.Context, matcher func(UpgradablePackage) bool) ([]UpgradablePackage, error) {
7072
if !m.lock.TryLock() {
7173
return nil, ErrOperationAlreadyInProgress
7274
}
@@ -86,7 +88,7 @@ func (m *Manager) ListUpgradablePackages(ctx context.Context, matcher func(Upgra
8688
)
8789

8890
g.Go(func() error {
89-
pkgs, err := m.debUpdateService.ListUpgradablePackages(ctx, matcher)
91+
pkgs, err := m.debUpdateService.ListUpgradablePackages(cfg, ctx, matcher)
9092
if err != nil {
9193
return err
9294
}
@@ -95,7 +97,7 @@ func (m *Manager) ListUpgradablePackages(ctx context.Context, matcher func(Upgra
9597
})
9698

9799
g.Go(func() error {
98-
pkgs, err := m.arduinoPlatformUpdateService.ListUpgradablePackages(ctx, matcher)
100+
pkgs, err := m.arduinoPlatformUpdateService.ListUpgradablePackages(cfg, ctx, matcher)
99101
if err != nil {
100102
return err
101103
}

0 commit comments

Comments
 (0)