Skip to content

Commit

Permalink
Fixed a crash when parsing invalid release versions as SemVer
Browse files Browse the repository at this point in the history
Release tags that did not follow SemVer would result in parse errors,
but error handling was not being done correctly and resulted in panic by
nil references in sortVersions().

For examples:
https://github.com/winebarrel/terraform-provider-mysql/releases/tag/mysqlx-v1.9.0-0
  • Loading branch information
minamijoyo committed Oct 8, 2023
1 parent 69690a8 commit 4b1cefd
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 21 deletions.
8 changes: 5 additions & 3 deletions release/release.go
Expand Up @@ -33,18 +33,20 @@ func Latest(ctx context.Context, r Release) (string, error) {
// List returns a list of releases in semver order.
// If preRelease is set to false, the result doesn't contain pre-releases.
func List(ctx context.Context, r Release, maxLength int, preRelease bool) ([]string, error) {
versions, err := r.ListReleases(ctx)
res, err := r.ListReleases(ctx)
if err != nil {
return nil, err
}

versions := toVersions(res)
sorted := sortVersions(versions)
releases := sorted
rels := sorted

if !preRelease {
releases = excludePreReleases(sorted)
rels = excludePreReleases(sorted)
}

releases := fromVersions(rels)
start := len(releases) - minInt(maxLength, len(releases))
return releases[start:], nil
}
9 changes: 9 additions & 0 deletions release/release_test.go
Expand Up @@ -61,6 +61,15 @@ func TestLatest(t *testing.T) {
want: "",
ok: false,
},
{
desc: "parse error",
r: &mockRelease{
versions: []string{"foo", "0.3.0", "0.2.0", "0.1.0", "0.1.1"},
err: nil,
},
want: "0.3.0",
ok: true,
},
}

for _, tc := range cases {
Expand Down
30 changes: 14 additions & 16 deletions release/version.go
Expand Up @@ -31,17 +31,21 @@ func minInt(a, b int) int {
return b
}

// toVersions converts []string to []*version.Version
// toVersions converts []string to []*version.Version.
// Ignore if parse error.
func toVersions(versionsRaw []string) []*version.Version {
versions := make([]*version.Version, len(versionsRaw))
for i, raw := range versionsRaw {
v, _ := version.NewVersion(raw)
versions[i] = v
versions := []*version.Version{}
for _, raw := range versionsRaw {
v, err := version.NewVersion(raw)
if err != nil {
continue
}
versions = append(versions, v)
}
return versions
}

// fromVersions converts []*version.Version to []string
// fromVersions converts []*version.Version to []string.
func fromVersions(versions []*version.Version) []string {
versionsRaw := make([]string, len(versions))
for i, v := range versions {
Expand All @@ -52,19 +56,13 @@ func fromVersions(versions []*version.Version) []string {
}

// sortVersions sort a list of versions in semver order.
func sortVersions(versionsRaw []string) []string {
versions := toVersions(versionsRaw)

// sort them in semver order
func sortVersions(versions []*version.Version) []*version.Version {
sort.Sort(version.Collection(versions))

return fromVersions(versions)
return versions
}

// excludePreReleases excludes pre-releases such as alpha, beta, rc.
func excludePreReleases(versionsRaw []string) []string {
versions := toVersions(versionsRaw)

func excludePreReleases(versions []*version.Version) []*version.Version {
// exclude pre-release
filtered := []*version.Version{}
for _, v := range versions {
Expand All @@ -73,5 +71,5 @@ func excludePreReleases(versionsRaw []string) []string {
}
}

return fromVersions(filtered)
return filtered
}
4 changes: 2 additions & 2 deletions release/version_test.go
Expand Up @@ -30,7 +30,7 @@ func TestSortVersions(t *testing.T) {

for _, tc := range cases {
t.Run(tc.desc, func(t *testing.T) {
got := sortVersions(tc.versionsRaw)
got := fromVersions(sortVersions(toVersions(tc.versionsRaw)))
if !reflect.DeepEqual(got, tc.want) {
t.Errorf("got = %#v, but want = %#v", got, tc.want)
}
Expand Down Expand Up @@ -68,7 +68,7 @@ func TestExcludePreReleases(t *testing.T) {

for _, tc := range cases {
t.Run(tc.desc, func(t *testing.T) {
got := excludePreReleases(tc.versionsRaw)
got := fromVersions(excludePreReleases(toVersions(tc.versionsRaw)))
if !reflect.DeepEqual(got, tc.want) {
t.Errorf("got = %#v, but want = %#v", got, tc.want)
}
Expand Down

0 comments on commit 4b1cefd

Please sign in to comment.