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