From 4f115fce10f74179704232e0294cd168ab1edc45 Mon Sep 17 00:00:00 2001 From: Marcin Antas Date: Thu, 4 Jan 2024 17:42:39 +0100 Subject: [PATCH] Fix parsing of Weaviate versions --- apps/upgrade-journey/go.mod | 1 + apps/upgrade-journey/go.sum | 2 + apps/upgrade-journey/run.go | 6 +-- apps/upgrade-journey/versions.go | 57 +++++++++++---------------- apps/upgrade-journey/versions_test.go | 55 ++++++++++++++++++++++++++ 5 files changed, 84 insertions(+), 37 deletions(-) create mode 100644 apps/upgrade-journey/versions_test.go diff --git a/apps/upgrade-journey/go.mod b/apps/upgrade-journey/go.mod index 24360199..c711fd31 100644 --- a/apps/upgrade-journey/go.mod +++ b/apps/upgrade-journey/go.mod @@ -5,6 +5,7 @@ go 1.20 require ( github.com/docker/go-connections v0.4.0 github.com/google/uuid v1.3.1 + github.com/hashicorp/go-version v1.6.0 github.com/testcontainers/testcontainers-go v0.21.0 github.com/weaviate/weaviate v1.18.0 github.com/weaviate/weaviate-go-client/v4 v4.6.1 diff --git a/apps/upgrade-journey/go.sum b/apps/upgrade-journey/go.sum index d668e313..eb329cb3 100644 --- a/apps/upgrade-journey/go.sum +++ b/apps/upgrade-journey/go.sum @@ -557,6 +557,8 @@ github.com/hashicorp/go-multierror v0.0.0-20161216184304-ed905158d874/go.mod h1: github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek= +github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= diff --git a/apps/upgrade-journey/run.go b/apps/upgrade-journey/run.go index 0ac1fa65..2ad597de 100644 --- a/apps/upgrade-journey/run.go +++ b/apps/upgrade-journey/run.go @@ -206,15 +206,15 @@ func findObjectUsingVersionInts(ctx context.Context, client *weaviate.Client, filters.Where(). WithOperator(filters.Equal). WithPath([]string{"major_version"}). - WithValueInt(int64(parsed.major)), + WithValueInt(parsed.major()), filters.Where(). WithOperator(filters.Equal). WithPath([]string{"minor_version"}). - WithValueInt(int64(parsed.minor)), + WithValueInt(parsed.minor()), filters.Where(). WithOperator(filters.Equal). WithPath([]string{"patch_version"}). - WithValueInt(int64(parsed.patch)), + WithValueInt(parsed.patch()), }, ) diff --git a/apps/upgrade-journey/versions.go b/apps/upgrade-journey/versions.go index b507baa1..5cccd107 100644 --- a/apps/upgrade-journey/versions.go +++ b/apps/upgrade-journey/versions.go @@ -9,10 +9,10 @@ import ( "net/http" "regexp" "sort" - "strconv" "time" "github.com/docker/go-connections/nat" + hashicorpversion "github.com/hashicorp/go-version" "github.com/testcontainers/testcontainers-go" "github.com/testcontainers/testcontainers-go/wait" "github.com/weaviate/weaviate-go-client/v4/weaviate" @@ -81,57 +81,45 @@ func parseSemverList(input []string) semverList { continue } - sm := r.FindStringSubmatch(version) + ver, err := hashicorpversion.NewSemver(version) + if err != nil { + panic(fmt.Errorf("cannot parse version %q: %w", version, err)) + } out[i] = semver{ - major: mustParseInt(sm[1]), - minor: mustParseInt(sm[2]), - patch: mustParseInt(sm[3]), + version: ver, } i++ - } return out[:i] } type semver struct { - major int - minor int - patch int + version *hashicorpversion.Version } type semverList []semver func (self semver) largerOrEqual(other semver) bool { - if self.major < other.major { - return false - } + return self.version.GreaterThanOrEqual(other.version) +} - if self.minor < other.minor { - return false - } +func (self semver) major() int64 { + return self.version.Segments64()[0] +} - return self.patch >= other.patch +func (self semver) minor() int64 { + return self.version.Segments64()[1] } -func mustParseInt(in string) int { - res, err := strconv.Atoi(in) - if err != nil { - panic(err) - } - return res +func (self semver) patch() int64 { + return self.version.Segments64()[2] } func sortSemverAndTrimToMinimum(versions semverList, min, max string) semverList { sort.Slice(versions, func(a, b int) bool { - if versions[a].major != versions[b].major { - return versions[a].major < versions[b].major - } - if versions[a].minor != versions[b].minor { - return versions[a].minor < versions[b].minor - } - return versions[a].patch < versions[b].patch + return versions[a].version.LessThan(versions[b].version) }) minV := parseSingleSemverWithoutLeadingV(min) @@ -170,19 +158,20 @@ func maybeParseSingleSemverWithoutLeadingV(input string) (semver, bool) { return semver{}, false } - sm := r.FindStringSubmatch(input) + ver, err := hashicorpversion.NewSemver(input) + if err != nil { + panic(fmt.Errorf("cannot parse version %q: %w", input, err)) + } return semver{ - major: mustParseInt(sm[1]), - minor: mustParseInt(sm[2]), - patch: mustParseInt(sm[3]), + version: ver, }, true } func (s semverList) toStringList() []string { out := make([]string, len(s)) for i, ver := range s { - out[i] = fmt.Sprintf("%d.%d.%d", ver.major, ver.minor, ver.patch) + out[i] = ver.version.String() } return out } diff --git a/apps/upgrade-journey/versions_test.go b/apps/upgrade-journey/versions_test.go new file mode 100644 index 00000000..ddcf0e07 --- /dev/null +++ b/apps/upgrade-journey/versions_test.go @@ -0,0 +1,55 @@ +package main + +import ( + "reflect" + "testing" +) + +func Test_sortSemverAndTrimToMinimum(t *testing.T) { + ghReleases := []string{ + "v1.23.0", "v1.22.8", "v1.23.0-rc.1", "v1.22.7", "v1.23.0-rc.0", "v1.22.6", "v1.22.5", "v1.22.4", "v1.22.3", + "v1.22.2", "v1.21.9", "v1.22.1", "v1.22.0", "v1.21.8", "v1.22.0-rc.0", "v1.21.7", "v1.21.6", "v1.21.5", + "v1.21.4", "v1.21.3", "v1.21.2", "v1.21.1", "v1.20.6", "v1.19.13", "v1.18.6", "v1.21.0", "v1.21.0-rc.1", + "v1.21.0-rc.0", "v1.20.5", "v1.20.4", "v1.20.3", "v1.20.2", "v1.20.1", "v1.20.0", "v1.19.12", "v1.19.11", + "v1.19.10", "v1.19.9", "v1.19.8", "v1.19.7", "v1.19.6", "v1.19.5", "v1.19.4", "v1.18.5", "v1.19.3", "v1.19.2", + "v1.19.1", "v1.19.0", "v1.18.4", "v1.19.0-beta.1", "v1.19.0-beta.0", "v1.18.3", "v1.18.2", "v1.18.1", + "v1.18.0", "v1.17.6", "v1.18.0-rc.0", "v1.17.5", "v1.17.4", "v1.17.3", "v1.17.2", "v1.17.1", "v1.17.0", + "v1.16.9", "v1.16.8", "v1.16.7", "v1.16.6", "v1.16.5", "v1.16.4", "v1.16.3", "v1.16.2", "v1.16.1", "v1.16.0", + "v1.15.5", "v1.15.4", "v1.15.3", "v1.15.2", "v1.15.1", "v1.15.0", "v1.15.0-alpha1", "v1.14.1", "v1.14.0", "v1.13.2", + "v1.13.1", "v1.13.0", "v1.12.2", "v1.12.1", "v1.12.0", "v1.11.0", "v1.10.1", "v1.10.0", "v1.9.1", "v1.9.1-rc.0", + "v1.9.0", "v1.8.0", "v1.8.0-rc.3", "v1.8.0-rc.2", "v1.8.0-rc.1", "v1.8.0-rc.0", "v1.7.2", + } + versions := parseSemverList(ghReleases) + tests := []struct { + name string + versions semverList + min string + max string + want []string + }{ + { + name: "from 1.22.7 to 1.22.9", + versions: versions, + min: "1.22.7", + max: "1.22.9", + want: []string{"1.22.7", "1.22.8"}, + }, + { + name: "from 1.20.0 to 1.22.9", + versions: versions, + min: "1.20.0", + max: "1.22.9", + want: []string{ + "1.20.0", "1.20.1", "1.20.2", "1.20.3", "1.20.4", "1.20.5", "1.20.6", "1.21.0", "1.21.1", "1.21.2", "1.21.3", "1.21.4", "1.21.5", + "1.21.6", "1.21.7", "1.21.8", "1.21.9", "1.22.0", "1.22.1", "1.22.2", "1.22.3", "1.22.4", "1.22.5", "1.22.6", "1.22.7", "1.22.8", + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := sortSemverAndTrimToMinimum(tt.versions, tt.min, tt.max); !reflect.DeepEqual(got.toStringList(), tt.want) { + t.Errorf("sortSemverAndTrimToMinimum() = %v, want %v", got.toStringList(), tt.want) + } + }) + } +}