Skip to content

Commit d1b92e9

Browse files
authored
fix: ensure deterministic results for SortBySemVer() (argoproj-labs#559)
Signed-off-by: Kent <[email protected]>
1 parent e372237 commit d1b92e9

File tree

3 files changed

+36
-4
lines changed

3 files changed

+36
-4
lines changed

pkg/tag/semver.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package tag
2+
3+
import "github.com/Masterminds/semver"
4+
5+
// semverCollection is a replacement for semver.Collection that breaks version
6+
// comparison ties through a lexical comparison of the original version strings.
7+
// Using this, instead of semver.Collection, when sorting will yield
8+
// deterministic results that semver.Collection will not yield.
9+
type semverCollection []*semver.Version
10+
11+
// Len returns the length of a collection. The number of Version instances
12+
// on the slice.
13+
func (s semverCollection) Len() int {
14+
return len(s)
15+
}
16+
17+
// Less is needed for the sort interface to compare two Version objects on the
18+
// slice. If checks if one is less than the other.
19+
func (s semverCollection) Less(i, j int) bool {
20+
comp := s[i].Compare(s[j])
21+
if comp != 0 {
22+
return comp < 0
23+
}
24+
return s[i].Original() < s[j].Original()
25+
}
26+
27+
// Swap is needed for the sort interface to replace the Version objects
28+
// at two different positions in the slice.
29+
func (s semverCollection) Swap(i, j int) {
30+
s[i], s[j] = s[j], s[i]
31+
}

pkg/tag/tag.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ func (il ImageTagList) SortBySemVer() SortableImageTagList {
165165
}
166166
svl = append(svl, svi)
167167
}
168-
sort.Sort(semver.Collection(svl))
168+
sort.Sort(semverCollection(svl))
169169
for _, svi := range svl {
170170
sil = append(sil, NewImageTag(svi.Original(), *il.items[svi.Original()].TagDate, il.items[svi.Original()].TagDigest))
171171
}

pkg/tag/tag_test.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ func Test_SortableImageTagList(t *testing.T) {
106106
})
107107

108108
t.Run("Sort by semver", func(t *testing.T) {
109-
names := []string{"v2.0.2", "v1.0", "v1.0.1", "v2.0.3", "v2.0"}
109+
names := []string{"v2.0.2", "v1.0", "v2.0.0", "v1.0.1", "v2.0.3", "v2.0"}
110110
il := NewImageTagList()
111111
for _, name := range names {
112112
tag := NewImageTag(name, time.Now(), "")
@@ -117,8 +117,9 @@ func Test_SortableImageTagList(t *testing.T) {
117117
assert.Equal(t, "v1.0", sil[0].TagName)
118118
assert.Equal(t, "v1.0.1", sil[1].TagName)
119119
assert.Equal(t, "v2.0", sil[2].TagName)
120-
assert.Equal(t, "v2.0.2", sil[3].TagName)
121-
assert.Equal(t, "v2.0.3", sil[4].TagName)
120+
assert.Equal(t, "v2.0.0", sil[3].TagName)
121+
assert.Equal(t, "v2.0.2", sil[4].TagName)
122+
assert.Equal(t, "v2.0.3", sil[5].TagName)
122123
})
123124

124125
t.Run("Sort by date", func(t *testing.T) {

0 commit comments

Comments
 (0)