Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Notify users if there is a new version of preflight #2

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,12 @@ image-push:
.PHONY: test
test:
go test -v $$(go list ./... | grep -v e2e) \
-ldflags "-X github.com/redhat-openshift-ecosystem/openshift-preflight/version.commit=bar -X github.com/redhat-openshift-ecosystem/openshift-preflight/version.version=foo"
-ldflags "-X github.com/redhat-openshift-ecosystem/openshift-preflight/version.commit=foobar -X github.com/redhat-openshift-ecosystem/openshift-preflight/version.version=0.0.1"

.PHONY: cover
cover:
go test -v \
-ldflags "-X github.com/redhat-openshift-ecosystem/openshift-preflight/version.commit=bar -X github.com/redhat-openshift-ecosystem/openshift-preflight/version.version=foo" \
-ldflags "-X github.com/redhat-openshift-ecosystem/openshift-preflight/version.commit=foobar -X github.com/redhat-openshift-ecosystem/openshift-preflight/version.version=0.0.1" \
$$(go list ./... | grep -v e2e) \
-race \
-cover -coverprofile=coverage.out
Expand Down
59 changes: 50 additions & 9 deletions cmd/preflight/cmd/check_container.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,20 @@ import (
"context"
"fmt"
"io"
"net/http"
"os"
"path/filepath"
rt "runtime"
"strings"
"time"

"github.com/go-logr/logr"
"github.com/google/go-containerregistry/pkg/crane"
"github.com/google/go-containerregistry/pkg/name"
"github.com/google/go-containerregistry/pkg/v1/remote"
"github.com/google/go-github/v57/github"
"github.com/spf13/cobra"
"github.com/spf13/pflag"

"github.com/redhat-openshift-ecosystem/openshift-preflight/artifacts"
"github.com/redhat-openshift-ecosystem/openshift-preflight/certification"
Expand All @@ -23,13 +33,6 @@ import (
"github.com/redhat-openshift-ecosystem/openshift-preflight/internal/runtime"
"github.com/redhat-openshift-ecosystem/openshift-preflight/internal/viper"
"github.com/redhat-openshift-ecosystem/openshift-preflight/version"

"github.com/go-logr/logr"
"github.com/google/go-containerregistry/pkg/crane"
"github.com/google/go-containerregistry/pkg/name"
"github.com/google/go-containerregistry/pkg/v1/remote"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
)

var submit bool
Expand All @@ -45,7 +48,7 @@ func checkContainerCmd(runpreflight runPreflight) *cobra.Command {
Args: checkContainerPositionalArgs,
// this fmt.Sprintf is in place to keep spacing consistent with cobras two spaces that's used in: Usage, Flags, etc
Example: fmt.Sprintf(" %s", "preflight check container quay.io/repo-name/container-name:version"),
PreRunE: validateCertificationProjectID,
PreRunE: validateConditions,
RunE: func(cmd *cobra.Command, args []string) error {
return checkContainerRunE(cmd, args, runpreflight)
},
Expand Down Expand Up @@ -88,6 +91,9 @@ func checkContainerCmd(runpreflight runPreflight) *cobra.Command {
flags.String("platform", rt.GOARCH, "Architecture of image to pull. Defaults to runtime platform.")
_ = viper.BindPFlag("platform", flags.Lookup("platform"))

flags.String("gh-auth-token", "", "A Github auth token can be specified to work around rate limits")
_ = viper.BindPFlag("gh-auth-token", flags.Lookup("gh-auth-token"))

return checkContainerCmd
}

Expand Down Expand Up @@ -237,9 +243,16 @@ func checkContainerPositionalArgs(cmd *cobra.Command, args []string) error {
return nil
}

// validateConditions run all pre-run functions
func validateConditions(cmd *cobra.Command, args []string) error {
err := validateCertificationProjectID()
checkForNewerReleaseVersion(cmd)
return err
}

// validateCertificationProjectID validates that the certification project id is in the proper format
// and throws an error if the value provided is in a legacy format that is not usable to query pyxis
func validateCertificationProjectID(cmd *cobra.Command, args []string) error {
func validateCertificationProjectID() error {
viper := viper.Instance()
certificationProjectID := viper.GetString("certification_project_id")
// splitting the certification project id into parts. if there are more than 2 elements in the array,
Expand All @@ -257,6 +270,34 @@ func validateCertificationProjectID(cmd *cobra.Command, args []string) error {
return nil
}

// checkForNewerReleaseVersion checks if there is a newer release available
func checkForNewerReleaseVersion(cmd *cobra.Command) {
logger := logr.FromContextOrDiscard(cmd.Context())

// use an authenticated client if a token is provided
var client *github.Client
ghToken, err := cmd.Flags().GetString("gh-auth-token")
if err == nil && len(ghToken) > 0 {
client = github.NewClient(&http.Client{
// Timeout in 1s in case Github is slow to respond
Timeout: time.Second * 1,
}).WithAuthToken(ghToken)
} else {
client = github.NewClient(&http.Client{
// timeout in 1s in case Github is slow to respond
Timeout: time.Second * 1,
})
}
// check if a newer release is available
latestRelease, err := version.Version.LatestReleasedVersion(cmd, client.Repositories)
if err != nil {
logger.Error(err, "Unable to determine if running the latest release")
}
if latestRelease != nil {
logger.Info("Found newer release", "New version", *latestRelease.TagName, "available at", *latestRelease.HTMLURL)
}
}

// generateContainerCheckOptions returns appropriate container.Options based on cfg.
func generateContainerCheckOptions(cfg *runtime.Config) []container.Option {
o := []container.Option{
Expand Down
24 changes: 12 additions & 12 deletions cmd/preflight/cmd/check_container_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,6 @@ import (
"path/filepath"
"runtime"

"github.com/redhat-openshift-ecosystem/openshift-preflight/artifacts"
"github.com/redhat-openshift-ecosystem/openshift-preflight/certification"
"github.com/redhat-openshift-ecosystem/openshift-preflight/internal/check"
"github.com/redhat-openshift-ecosystem/openshift-preflight/internal/cli"
"github.com/redhat-openshift-ecosystem/openshift-preflight/internal/formatters"
"github.com/redhat-openshift-ecosystem/openshift-preflight/internal/lib"
"github.com/redhat-openshift-ecosystem/openshift-preflight/internal/viper"

"github.com/go-logr/logr"
"github.com/google/go-containerregistry/pkg/crane"
"github.com/google/go-containerregistry/pkg/name"
Expand All @@ -33,6 +25,14 @@ import (
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
"github.com/onsi/gomega/types"

"github.com/redhat-openshift-ecosystem/openshift-preflight/artifacts"
"github.com/redhat-openshift-ecosystem/openshift-preflight/certification"
"github.com/redhat-openshift-ecosystem/openshift-preflight/internal/check"
"github.com/redhat-openshift-ecosystem/openshift-preflight/internal/cli"
"github.com/redhat-openshift-ecosystem/openshift-preflight/internal/formatters"
"github.com/redhat-openshift-ecosystem/openshift-preflight/internal/lib"
"github.com/redhat-openshift-ecosystem/openshift-preflight/internal/viper"
)

func createPlatformImage(arch string, addlLayers int) cranev1.Image {
Expand Down Expand Up @@ -225,7 +225,7 @@ certification_project_id: mycertid`
DeferCleanup(viper.Instance().Set, "certification_project_id", "")
})
It("should not change the flag value", func() {
err := validateCertificationProjectID(checkContainerCmd(mockRunPreflightReturnNil), []string{"foo"})
err := validateCertificationProjectID()
Expect(err).ToNot(HaveOccurred())
Expect(viper.Instance().GetString("certification_project_id")).To(Equal("123456789"))
})
Expand All @@ -236,7 +236,7 @@ certification_project_id: mycertid`
DeferCleanup(viper.Instance().Set, "certification_project_id", "")
})
It("should strip ospid- from the flag value", func() {
err := validateCertificationProjectID(checkContainerCmd(mockRunPreflightReturnNil), []string{"foo"})
err := validateCertificationProjectID()
Expect(err).ToNot(HaveOccurred())
Expect(viper.Instance().GetString("certification_project_id")).To(Equal("123456789"))
})
Expand All @@ -247,7 +247,7 @@ certification_project_id: mycertid`
DeferCleanup(viper.Instance().Set, "certification_project_id", "")
})
It("should throw an error", func() {
err := validateCertificationProjectID(checkContainerCmd(mockRunPreflightReturnNil), []string{"foo"})
err := validateCertificationProjectID()
Expect(err).To(HaveOccurred())
})
})
Expand All @@ -257,7 +257,7 @@ certification_project_id: mycertid`
DeferCleanup(viper.Instance().Set, "certification_project_id", "")
})
It("should throw an error", func() {
err := validateCertificationProjectID(checkContainerCmd(mockRunPreflightReturnNil), []string{"foo"})
err := validateCertificationProjectID()
Expect(err).To(HaveOccurred())
})
})
Expand Down
3 changes: 3 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@ module github.com/redhat-openshift-ecosystem/openshift-preflight
go 1.21

require (
github.com/Masterminds/semver/v3 v3.2.1
github.com/blang/semver v3.5.1+incompatible
github.com/bombsimon/logrusr/v4 v4.1.0
github.com/docker/cli v25.0.3+incompatible
github.com/glebarez/go-sqlite v1.22.0
github.com/go-logr/logr v1.4.1
github.com/google/go-containerregistry v0.19.0
github.com/google/go-github/v57 v57.0.0
github.com/knqyf263/go-rpmdb v0.0.0-20230517124904-b97c85e63254
github.com/onsi/ginkgo/v2 v2.15.0
github.com/onsi/gomega v1.31.1
Expand Down Expand Up @@ -59,6 +61,7 @@ require (
github.com/google/cel-go v0.17.7 // indirect
github.com/google/gnostic-models v0.6.8 // indirect
github.com/google/go-cmp v0.6.0 // indirect
github.com/google/go-querystring v1.1.0 // indirect
github.com/google/gofuzz v1.2.0 // indirect
github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 // indirect
github.com/google/uuid v1.5.0 // indirect
Expand Down
7 changes: 7 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
github.com/Masterminds/semver/v3 v3.2.1 h1:RN9w6+7QoMeJVGyfmbcgs28Br8cvmnucEXnY0rYXWg0=
github.com/Masterminds/semver/v3 v3.2.1/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ=
github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20230305170008-8188dc5388df h1:7RFfzj4SSt6nnvCPbCqijJi1nWCd+TqAT3bYCStRC18=
github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20230305170008-8188dc5388df/go.mod h1:pSwJ0fSY5KhvocuWSx4fz3BA8OrA1bQn+K1Eli3BRwM=
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a h1:idn718Q4B6AGu/h5Sxe66HYVdqdGu2l9Iebqhi/AEoA=
Expand Down Expand Up @@ -82,12 +84,17 @@ github.com/google/cel-go v0.17.7 h1:6ebJFzu1xO2n7TLtN+UBqShGBhlD85bhvglh5DpcfqQ=
github.com/google/cel-go v0.17.7/go.mod h1:HXZKzB0LXqer5lHHgfWAnlYwJaQBDKMjxjulNQzhwhY=
github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I=
github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U=
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-containerregistry v0.19.0 h1:uIsMRBV7m/HDkDxE/nXMnv1q+lOOSPlQ/ywc5JbB8Ic=
github.com/google/go-containerregistry v0.19.0/go.mod h1:u0qB2l7mvtWVR5kNcbFIhFY1hLbf8eeGapA+vbFDCtQ=
github.com/google/go-github/v57 v57.0.0 h1:L+Y3UPTY8ALM8x+TV0lg+IEBI+upibemtBD8Q9u7zHs=
github.com/google/go-github/v57 v57.0.0/go.mod h1:s0omdnye0hvK/ecLvpsGfJMiRt85PimQh4oygmLIxHw=
github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
Expand Down
44 changes: 43 additions & 1 deletion version/version.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,16 @@
// describing the preflight project.
package version

import "fmt"
import (
"context"
"fmt"
"strings"

semver "github.com/Masterminds/semver/v3"
"github.com/go-logr/logr"
"github.com/google/go-github/v57/github"
"github.com/spf13/cobra"
)

var (
projectName = "github.com/redhat-openshift-ecosystem/openshift-preflight"
Expand All @@ -16,6 +25,10 @@ var Version = VersionContext{
Commit: commit,
}

type VersionClient interface {
GetLatestRelease(ctx context.Context, owner string, repo string) (*github.RepositoryRelease, *github.Response, error)
}

type VersionContext struct {
Name string `json:"name"`
Version string `json:"version"`
Expand All @@ -25,3 +38,32 @@ type VersionContext struct {
func (vc *VersionContext) String() string {
return fmt.Sprintf("%s <commit: %s>", vc.Version, vc.Commit)
}

func (vc *VersionContext) LatestReleasedVersion(cmd *cobra.Command, svc VersionClient) (*github.RepositoryRelease, error) {
ctx := cmd.Context()
logger := logr.FromContextOrDiscard(ctx)

projectTokens := strings.Split(vc.Name, "/")
owner := projectTokens[1]
repo := projectTokens[2]
// Fetch latest release from Github
latestRelease, resp, err := svc.GetLatestRelease(ctx, owner, repo)
if err != nil {
return nil, err
}
logger.Info("Github responded with", "rate limit", resp.Rate.String())
currentVersion, err := semver.NewVersion(vc.Version)
if err != nil {
logger.Error(err, "Unable to determine current semver")
return nil, err
}
latestVersion, err := semver.NewVersion(*latestRelease.TagName)
if err != nil {
logger.Error(err, "Unable to determine latest semver")
return nil, err
}
if !currentVersion.Equal(latestVersion) {
return latestRelease, nil
}
return nil, nil
}
Loading