Skip to content

Commit

Permalink
chore: add grype version to application update check headers
Browse files Browse the repository at this point in the history
Signed-off-by: Keith Zantow <kzantow@gmail.com>
  • Loading branch information
kzantow committed Jul 31, 2024
1 parent 406d196 commit 4926e3b
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 10 deletions.
5 changes: 2 additions & 3 deletions cmd/grype/cli/commands/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -259,13 +259,12 @@ func checkForAppUpdate(id clio.Identification, opts *options.Grype) {
return
}

version := id.Version
isAvailable, newVersion, err := isUpdateAvailable(version)
isAvailable, newVersion, err := isUpdateAvailable(id)
if err != nil {
log.Errorf(err.Error())
}
if isAvailable {
log.Infof("new version of %s is available: %s (currently running: %s)", id.Name, newVersion, version)
log.Infof("new version of %s is available: %s (currently running: %s)", id.Name, newVersion, id.Version)

bus.Publish(partybus.Event{
Type: event.CLIAppUpdateAvailable,
Expand Down
13 changes: 8 additions & 5 deletions cmd/grype/cli/commands/update.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"net/http"
"strings"

"github.com/anchore/clio"
hashiVersion "github.com/anchore/go-version"
"github.com/anchore/grype/cmd/grype/internal"
)
Expand All @@ -25,17 +26,17 @@ func isProductionBuild(version string) bool {
return true
}

func isUpdateAvailable(version string) (bool, string, error) {
if !isProductionBuild(version) {
func isUpdateAvailable(id clio.Identification) (bool, string, error) {
if !isProductionBuild(id.Version) {
// don't allow for non-production builds to check for a version.
return false, "", nil
}
currentVersion, err := hashiVersion.NewVersion(version)
currentVersion, err := hashiVersion.NewVersion(id.Version)
if err != nil {
return false, "", fmt.Errorf("failed to parse current application version: %w", err)
}

latestVersion, err := fetchLatestApplicationVersion()
latestVersion, err := fetchLatestApplicationVersion(id)
if err != nil {
return false, "", err
}
Expand All @@ -47,12 +48,14 @@ func isUpdateAvailable(version string) (bool, string, error) {
return false, "", nil
}

func fetchLatestApplicationVersion() (*hashiVersion.Version, error) {
func fetchLatestApplicationVersion(id clio.Identification) (*hashiVersion.Version, error) {
req, err := http.NewRequest(http.MethodGet, latestAppVersionURL.host+latestAppVersionURL.path, nil)
if err != nil {
return nil, fmt.Errorf("failed to create request for latest version: %w", err)
}

req.Header.Add("User-Agent", fmt.Sprintf("%v %v", id.Name, id.Version))

client := http.Client{}
resp, err := client.Do(req)
if err != nil {
Expand Down
29 changes: 27 additions & 2 deletions cmd/grype/cli/commands/update_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"net/http/httptest"
"testing"

"github.com/anchore/clio"
hashiVersion "github.com/anchore/go-version"
"github.com/anchore/grype/cmd/grype/internal"
)
Expand Down Expand Up @@ -108,7 +109,7 @@ func TestIsUpdateAvailable(t *testing.T) {
latestAppVersionURL.host = mockSrv.URL
defer mockSrv.Close()

isAvailable, newVersion, err := isUpdateAvailable(version)
isAvailable, newVersion, err := isUpdateAvailable(clio.Identification{Version: version})
if err != nil && !test.err {
t.Fatalf("got error but expected none: %+v", err)
} else if err == nil && test.err {
Expand Down Expand Up @@ -190,7 +191,7 @@ func TestFetchLatestApplicationVersion(t *testing.T) {
latestAppVersionURL.host = mockSrv.URL
defer mockSrv.Close()

actual, err := fetchLatestApplicationVersion()
actual, err := fetchLatestApplicationVersion(clio.Identification{})
if err != nil && !test.err {
t.Fatalf("got error but expected none: %+v", err)
} else if err == nil && test.err {
Expand All @@ -208,3 +209,27 @@ func TestFetchLatestApplicationVersion(t *testing.T) {
}

}

func Test_UserAgent(t *testing.T) {
got := ""

// setup mock
handler := http.NewServeMux()
handler.HandleFunc(latestAppVersionURL.path, func(w http.ResponseWriter, r *http.Request) {
got = r.Header.Get("User-Agent")
w.WriteHeader(http.StatusOK)
_, _ = w.Write([]byte("1.0.0"))
})
mockSrv := httptest.NewServer(handler)
latestAppVersionURL.host = mockSrv.URL
defer mockSrv.Close()

fetchLatestApplicationVersion(clio.Identification{
Name: "the-app",
Version: "v3.2.1",
})

if got != "the-app v3.2.1" {
t.Errorf("expected User-Agent header to match, got: %v", got)
}
}

0 comments on commit 4926e3b

Please sign in to comment.