github.com/nextlinux/gosbom@v0.81.1-0.20230627115839-1ff50c281391/internal/version/update.go (about) 1 package version 2 3 import ( 4 "fmt" 5 "io" 6 "net/http" 7 "strings" 8 9 "github.com/nextlinux/gosbom/internal" 10 11 hashiVersion "github.com/anchore/go-version" 12 ) 13 14 var latestAppVersionURL = struct { 15 host string 16 path string 17 }{ 18 host: "https://toolbox-data.anchore.io", 19 path: fmt.Sprintf("/%s/releases/latest/VERSION", internal.ApplicationName), 20 } 21 22 // IsUpdateAvailable indicates if there is a newer application version available, and if so, what the new version is. 23 func IsUpdateAvailable() (bool, string, error) { 24 currentBuildInfo := FromBuild() 25 if !currentBuildInfo.IsProductionBuild() { 26 // don't allow for non-production builds to check for a version. 27 return false, "", nil 28 } 29 currentVersion, err := hashiVersion.NewVersion(currentBuildInfo.Version) 30 if err != nil { 31 return false, "", fmt.Errorf("failed to parse current application version: %w", err) 32 } 33 34 latestVersion, err := fetchLatestApplicationVersion() 35 if err != nil { 36 return false, "", err 37 } 38 39 if latestVersion.GreaterThan(currentVersion) { 40 return true, latestVersion.String(), nil 41 } 42 43 return false, "", nil 44 } 45 46 func fetchLatestApplicationVersion() (*hashiVersion.Version, error) { 47 req, err := http.NewRequest(http.MethodGet, latestAppVersionURL.host+latestAppVersionURL.path, nil) 48 if err != nil { 49 return nil, fmt.Errorf("failed to create request for latest version: %w", err) 50 } 51 52 client := http.Client{} 53 resp, err := client.Do(req) 54 if err != nil { 55 return nil, fmt.Errorf("failed to fetch latest version: %w", err) 56 } 57 defer resp.Body.Close() 58 59 if resp.StatusCode != http.StatusOK { 60 return nil, fmt.Errorf("HTTP %d on fetching latest version: %s", resp.StatusCode, resp.Status) 61 } 62 63 versionBytes, err := io.ReadAll(resp.Body) 64 if err != nil { 65 return nil, fmt.Errorf("failed to read latest version: %w", err) 66 } 67 68 versionStr := strings.TrimSuffix(string(versionBytes), "\n") 69 if len(versionStr) > 50 { 70 return nil, fmt.Errorf("version too long: %q", versionStr[:50]) 71 } 72 73 return hashiVersion.NewVersion(versionStr) 74 }