From bcb55fdeb6d128e7532774bb868315bc92375949 Mon Sep 17 00:00:00 2001 From: Andrew Lytvynov Date: Fri, 31 May 2024 15:34:43 -0700 Subject: [PATCH] clientupdate: mention when Alpine system upgrade is needed (#12306) Alpine APK repos are versioned, and contain different package sets. Older APK releases and repos don't have the latest tailscale package. When we report "no update available", check whether pkgs.tailscale.com has a newer tarball release. If it does, it's possible that the system is on an older Alpine release. Print additional messages to suggest the user to upgrade their OS. Fixes #11309 Signed-off-by: Andrew Lytvynov --- clientupdate/clientupdate.go | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/clientupdate/clientupdate.go b/clientupdate/clientupdate.go index 9f5b7674e..c5471956f 100644 --- a/clientupdate/clientupdate.go +++ b/clientupdate/clientupdate.go @@ -653,6 +653,9 @@ func (up *Updater) updateAlpineLike() (err error) { return fmt.Errorf(`failed to parse latest version from "apk info tailscale": %w`, err) } if !up.confirm(ver) { + if err := checkOutdatedAlpineRepo(up.Logf, ver, up.Track); err != nil { + up.Logf("failed to check whether Alpine release is outdated: %v", err) + } return nil } @@ -690,6 +693,37 @@ func parseAlpinePackageVersion(out []byte) (string, error) { return "", errors.New("tailscale version not found in output") } +var apkRepoVersionRE = regexp.MustCompile(`v[0-9]+\.[0-9]+`) + +func checkOutdatedAlpineRepo(logf logger.Logf, apkVer, track string) error { + latest, err := LatestTailscaleVersion(track) + if err != nil { + return err + } + if latest == apkVer { + // Actually on latest release. + return nil + } + f, err := os.Open("/etc/apk/repositories") + if err != nil { + return err + } + defer f.Close() + // Read the first repo line. Typically, there are multiple repos that all + // contain the same version in the path, like: + // https://dl-cdn.alpinelinux.org/alpine/v3.20/main + // https://dl-cdn.alpinelinux.org/alpine/v3.20/community + s := bufio.NewScanner(f) + if !s.Scan() { + return s.Err() + } + alpineVer := apkRepoVersionRE.FindString(s.Text()) + if alpineVer != "" { + logf("The latest Tailscale release for Linux is %q, but your apk repository only provides %q.\nYour Alpine version is %q, you may need to upgrade the system to get the latest Tailscale version: https://wiki.alpinelinux.org/wiki/Upgrading_Alpine", latest, apkVer, alpineVer) + } + return nil +} + func (up *Updater) updateMacSys() error { return errors.New("NOTREACHED: On MacSys builds, `tailscale update` is handled in Swift to launch the GUI updater") }