From 9672a6dbfed0d3c920078ef8384f0ce9ab009837 Mon Sep 17 00:00:00 2001 From: Federico Guerinoni Date: Fri, 31 Jan 2025 17:37:01 +0100 Subject: [PATCH] feat: implement outdated command This allow to present all new versions available for the pkg installed. It is a lot useful because otherwise you need to check this manually. --- internal/boxcli/outdated.go | 45 +++++++++++++++++++++++++++++++++++++ internal/boxcli/root.go | 1 + internal/devbox/packages.go | 43 +++++++++++++++++++++++++++++++++++ 3 files changed, 89 insertions(+) create mode 100644 internal/boxcli/outdated.go diff --git a/internal/boxcli/outdated.go b/internal/boxcli/outdated.go new file mode 100644 index 00000000000..9abff7a8c0c --- /dev/null +++ b/internal/boxcli/outdated.go @@ -0,0 +1,45 @@ +package boxcli + +import ( + "github.com/pkg/errors" + "github.com/spf13/cobra" + "go.jetpack.io/devbox/internal/devbox" + "go.jetpack.io/devbox/internal/devbox/devopt" +) + +func outdatedCmd() *cobra.Command { + flags := listCmdFlags{} + command := &cobra.Command{ + Use: "outdated", + Short: "Show all outdated packages", + Args: cobra.MaximumNArgs(0), + PreRunE: ensureNixInstalled, + RunE: func(cmd *cobra.Command, _ []string) error { + box, err := devbox.Open(&devopt.Opts{ + Dir: flags.config.path, + Stderr: cmd.ErrOrStderr(), + }) + if err != nil { + return errors.WithStack(err) + } + + resutls, err := box.Outdated(cmd.Context()) + if err != nil { + return errors.WithStack(err) + } + + if len(resutls) == 0 { + cmd.Println("Your packages are up to date!") + return nil + } + + cmd.Println("The following packages can be updated:") + for pkg, version := range resutls { + cmd.Printf(" * %-30s %s -> %s\n", pkg, version.Current, version.Latest) + } + return nil + }, + } + + return command +} diff --git a/internal/boxcli/root.go b/internal/boxcli/root.go index c502915aa52..415d8f28f0f 100644 --- a/internal/boxcli/root.go +++ b/internal/boxcli/root.go @@ -66,6 +66,7 @@ func RootCmd() *cobra.Command { command.AddCommand(infoCmd()) command.AddCommand(initCmd()) command.AddCommand(installCmd()) + command.AddCommand(outdatedCmd()) command.AddCommand(integrateCmd()) command.AddCommand(listCmd()) command.AddCommand(logCmd()) diff --git a/internal/devbox/packages.go b/internal/devbox/packages.go index 83d1fba7450..45654371452 100644 --- a/internal/devbox/packages.go +++ b/internal/devbox/packages.go @@ -25,6 +25,7 @@ import ( "go.jetpack.io/devbox/internal/devpkg" "go.jetpack.io/devbox/internal/devpkg/pkgtype" "go.jetpack.io/devbox/internal/lock" + "go.jetpack.io/devbox/internal/searcher" "go.jetpack.io/devbox/internal/setup" "go.jetpack.io/devbox/internal/shellgen" "go.jetpack.io/devbox/internal/telemetry" @@ -43,6 +44,48 @@ const StateOutOfDateMessage = "Your devbox environment may be out of date. Run % // packages.go has functions for adding, removing and getting info about nix // packages +type UpdateVersion struct { + Current string + Latest string +} + +// Outdated returns a map of package names to their available latest version. +func (d *Devbox) Outdated(ctx context.Context) (map[string]UpdateVersion, error) { + ctx, task := trace.NewTask(ctx, "devboxOutdated") + defer task.End() + + outdatedPackages := map[string]UpdateVersion{} + + for _, pkg := range d.AllPackages() { + if strings.HasSuffix(pkg.Versioned(), "latest") { + continue + } + + result, err := searcher.Client().Search(ctx, pkg.CanonicalName()) + if err != nil { + return nil, err + } + + for _, p := range result.Packages { + if p.Name == pkg.CanonicalName() { + for _, v := range p.Versions { + vv, err := pkg.ResolvedVersion() + if err != nil { + return nil, err + } + + if v.Version > vv { + outdatedPackages[p.Name] = UpdateVersion{Current: vv, Latest: v.Version} + break + } + } + } + } + } + + return outdatedPackages, nil +} + // Add adds the `pkgs` to the config (i.e. devbox.json) and nix profile for this // devbox project func (d *Devbox) Add(ctx context.Context, pkgsNames []string, opts devopt.AddOpts) error {