From 7390509dffff4696706e469f4d9fbf7db9bcb972 Mon Sep 17 00:00:00 2001 From: Russell Jones Date: Sat, 4 Dec 2021 16:51:27 +0000 Subject: [PATCH] Added version checker. --- build.assets/version-check/go.mod | 17 ++++ build.assets/version-check/go.sum | 40 +++++++++ build.assets/version-check/main.go | 106 ++++++++++++++++++++++++ build.assets/version-check/main_test.go | 69 +++++++++++++++ 4 files changed, 232 insertions(+) create mode 100644 build.assets/version-check/go.mod create mode 100644 build.assets/version-check/go.sum create mode 100644 build.assets/version-check/main.go create mode 100644 build.assets/version-check/main_test.go diff --git a/build.assets/version-check/go.mod b/build.assets/version-check/go.mod new file mode 100644 index 0000000000000..9e362acc3b753 --- /dev/null +++ b/build.assets/version-check/go.mod @@ -0,0 +1,17 @@ +module github.com/gravitational/teleport/build.assets/version-check + +go 1.17 + +require github.com/google/go-github/v41 v41.0.0 + +require ( + github.com/google/go-querystring v1.1.0 // indirect + github.com/gravitational/trace v1.1.15 // indirect + github.com/jonboulle/clockwork v0.2.2 // indirect + github.com/sirupsen/logrus v1.8.1 // indirect + golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 // indirect + golang.org/x/mod v0.5.1 // indirect + golang.org/x/net v0.0.0-20210226172049-e18ecbb05110 // indirect + golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1 // indirect + golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 // indirect +) diff --git a/build.assets/version-check/go.sum b/build.assets/version-check/go.sum new file mode 100644 index 0000000000000..cebafe0cb3c6b --- /dev/null +++ b/build.assets/version-check/go.sum @@ -0,0 +1,40 @@ +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ= +github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-github/v41 v41.0.0 h1:HseJrM2JFf2vfiZJ8anY2hqBjdfY1Vlj/K27ueww4gg= +github.com/google/go-github/v41 v41.0.0/go.mod h1:XgmCA5H323A9rtgExdTcnDkcqp6S30AVACCBDOonIxg= +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/gravitational/trace v1.1.15 h1:dfaFcARt110nCX6RSvrcRUbvRawEYAasXyCqnhXo0Xg= +github.com/gravitational/trace v1.1.15/go.mod h1:RvdOUHE4SHqR3oXlFFKnGzms8a5dugHygGw1bqDstYI= +github.com/jonboulle/clockwork v0.2.2 h1:UOGuzwb1PwsrDAObMuhUnj0p5ULPj8V/xJ7Kx9qUBdQ= +github.com/jonboulle/clockwork v0.2.2/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= +github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 h1:HWj/xjIHfjYU5nVXpTM0s39J9CbLn7Cc5a7IC5rwsMQ= +golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/mod v0.5.1 h1:OJxoQ/rynoF0dcCdI7cLPktw/hR2cueqYfjm43oqK38= +golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= +golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110 h1:qWPm9rbaAMKs8Bq/9LRpbMqxWRVUAQwMI9fVrssnTfw= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1 h1:SrN+KX8Art/Sf4HNj6Zcz06G7VEz+7w9tdXTPOZ7+l4= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= diff --git a/build.assets/version-check/main.go b/build.assets/version-check/main.go new file mode 100644 index 0000000000000..fe99f4f34b16e --- /dev/null +++ b/build.assets/version-check/main.go @@ -0,0 +1,106 @@ +package main + +import ( + "context" + "flag" + "log" + "sort" + "time" + + "golang.org/x/mod/semver" + + "github.com/gravitational/trace" + + go_github "github.com/google/go-github/v41/github" +) + +func main() { + tag, err := parseFlags() + if err != nil { + log.Fatalf("Failed to parse flags; %v.", err) + } + + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + defer cancel() + + if err := check(ctx, newGitHub(), "gravitational", "teleport", tag); err != nil { + log.Fatalf("Check failed: %v.", err) + } +} + +func parseFlags() (string, error) { + tag := flag.String("tag", "", "tag to validate") + flag.Parse() + + if *tag == "" { + return "", trace.BadParameter("tag missing") + } + return *tag, nil +} + +func check(ctx context.Context, gh github, organization string, repository string, tag string) error { + releases, err := gh.ListReleases(context.Background(), "gravitational", "teleport") + if err != nil { + return trace.Wrap(err) + } + sort.SliceStable(releases, func(i int, j int) bool { + return releases[i] > releases[j] + }) + if len(releases) == 0 { + return trace.BadParameter("failed to find any releases on GitHub") + } + + if semver.Compare(tag, releases[0]) <= 0 { + return trace.BadParameter("found newer version of release, not releasing. Latest release: %v, tag: %v", releases[0], tag) + } + + return nil +} + +type github interface { + ListReleases(ctx context.Context, organization string, repository string) ([]string, error) +} + +type ghClient struct { + client *go_github.Client +} + +func newGitHub() *ghClient { + return &ghClient{ + client: go_github.NewClient(nil), + } +} + +func (c *ghClient) ListReleases(ctx context.Context, organization string, repository string) ([]string, error) { + var n int + var releases []string + + opt := &go_github.ListOptions{ + Page: 0, + PerPage: 100, + } + for { + page, resp, err := c.client.Repositories.ListReleases(ctx, + organization, + repository, + opt) + if err != nil { + return nil, trace.Wrap(err) + } + + for _, p := range page { + releases = append(releases, p.GetTagName()) + } + + n += 1 + if n == 100 { + break + } + if resp.NextPage == 0 { + break + } + opt.Page = resp.NextPage + } + + return releases, nil +} diff --git a/build.assets/version-check/main_test.go b/build.assets/version-check/main_test.go new file mode 100644 index 0000000000000..b177bcdc4ce77 --- /dev/null +++ b/build.assets/version-check/main_test.go @@ -0,0 +1,69 @@ +package main + +import ( + "context" + "testing" +) + +func TestCheck(t *testing.T) { + tests := []struct { + desc string + tag string + releases []string + err bool + }{ + { + desc: "fail-old-releases", + tag: "v7.3.3", + releases: []string{ + "v8.0.0", + "v7.3.2", + "v7.0.0", + }, + err: true, + }, + { + desc: "fail-same-releases", + tag: "v8.0.0", + releases: []string{ + "v8.0.0", + "v7.3.2", + "v7.0.0", + }, + err: true, + }, + { + desc: "pass-new-releases", + tag: "v8.0.1", + releases: []string{ + "v8.0.0", + "v7.3.2", + "v7.0.0", + }, + err: false, + }, + } + for _, test := range tests { + t.Run(test.desc, func(t *testing.T) { + gh := &fakeGitHub{ + releases: test.releases, + } + err := check(context.Background(), gh, "", "", test.tag) + if test.err && err == nil { + t.Fatalf("Expected an error, got nil.") + } + if !test.err && err != nil { + t.Fatalf("Did not expect and error, got: %v", err) + } + }) + } + +} + +type fakeGitHub struct { + releases []string +} + +func (f *fakeGitHub) ListReleases(ctx context.Context, organization string, repository string) ([]string, error) { + return f.releases, nil +}