feat(build): summer plugin:update

- module installs move to the newest compatible registry release with
  one go get; submodules fetch tags, check out the release tag and
  require it in go.mod; go.work overrides and version pins are refreshed
- unlisted submodules (git URL installs) update from their own tags and
  plugin.yaml; --offline restricts to that
- without an ID every plugin that resolves is updated; in-app, unlisted
  and incompatible ones are reported; failure only when a resolved
  update cannot be carried out
- same prompt rule as plugin:install
This commit is contained in:
Jakub Zych
2026-10-29 18:46:14 +01:00
parent 8093587696
commit d024ab4bb8
8 changed files with 838 additions and 55 deletions

View File

@@ -340,59 +340,15 @@ func (in *installer) installedSatisfies(id, min string) (bool, error) {
return true, nil
}
// installedVersion returns the release of the module providing pkg: the
// go.mod require, a version replace from go.mod or go.work, or the base
// tag of `git describe` in a plugin directory that is its own repository
// (a submodule). It returns "" when the version cannot be told.
// installedVersion returns the installed release of the plugin package
// pkg (see installedSource): the module version of a module install, the
// base tag of git describe for a submodule, "" for an in-app plugin.
func installedVersion(ctx context.Context, appDir, pkg string) (string, error) {
gomod, err := editJSON(ctx, appDir, "mod", "edit", "-json", filepath.Join(appDir, "go.mod"))
src, err := installedSource(ctx, appDir, pkg)
if err != nil {
return "", fmt.Errorf("build: %w", err)
return "", err
}
mod, version := "", ""
for _, r := range gomod.Require {
if (pkg == r.Path || strings.HasPrefix(pkg, r.Path+"/")) && len(r.Path) > len(mod) {
mod, version = r.Path, r.Version
}
}
if mod == "" {
return "", nil
}
localDir := ""
apply := func(replaces []struct {
Old struct{ Path string }
New struct{ Path, Version string }
}, base string) {
for _, r := range replaces {
if r.Old.Path != mod {
continue
}
if r.New.Version != "" {
version, localDir = r.New.Version, ""
continue
}
localDir = r.New.Path
if !filepath.IsAbs(localDir) {
localDir = filepath.Join(base, localDir)
}
}
}
apply(gomod.Replace, appDir)
if gw := findGoWork(appDir); gw != "" {
if work, err := editJSON(ctx, appDir, "work", "edit", "-json", gw); err == nil {
apply(work.Replace, filepath.Dir(gw))
}
}
if localDir == "" {
if kiosk.ValidVersion(version) {
return version, nil
}
return "", nil
}
if !isOwnRepository(ctx, localDir) {
return "", nil
}
return kiosk.BaseVersion(gitDescribe(ctx, localDir)), nil
return src.Version, nil
}
func sortedKeys(m kiosk.Requires) []string {