Skip to content

Commit 5702d8b

Browse files
authored
[TT-1792] fix sorting by semantic versioning in ecrimagefetcher (#1244)
1 parent 1b1ea93 commit 5702d8b

File tree

4 files changed

+79
-17
lines changed

4 files changed

+79
-17
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fixes how tags are sorted so that semnatinc versioning is respected.

tools/ecrimagefetcher/main.go

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@ import (
1010
"sort"
1111
"strconv"
1212
"strings"
13+
"unicode"
1314

1415
"github.com/Masterminds/semver/v3"
15-
1616
"github.com/itchyny/gojq"
1717
)
1818

@@ -22,6 +22,15 @@ func fetchImageDetails(repositoryName string) ([]byte, error) {
2222
return cmd.Output()
2323
}
2424

25+
func trimToVersion(s string) string {
26+
for i, r := range s {
27+
if unicode.IsDigit(r) || r == 'v' {
28+
return s[i:]
29+
}
30+
}
31+
return s
32+
}
33+
2534
func parseImageTags(output []byte, grepString string, constraints *semver.Constraints) ([]string, error) {
2635
var imageDetails []interface{}
2736
if err := json.Unmarshal(output, &imageDetails); err != nil {
@@ -33,21 +42,25 @@ func parseImageTags(output []byte, grepString string, constraints *semver.Constr
3342
return nil, fmt.Errorf("failed to parse gojq query: %w", err)
3443
}
3544

36-
var tags []string
45+
var tags semver.Collection
3746
iter := query.Run(imageDetails)
3847
for {
3948
tag, ok := iter.Next()
4049
if !ok {
4150
break
4251
}
4352
if tagStr, ok := tag.(string); ok {
44-
tags = append(tags, tagStr)
53+
asVersion, err := semver.NewVersion(trimToVersion(tagStr))
54+
if err != nil {
55+
return nil, fmt.Errorf("failed to parse version: %w", err)
56+
}
57+
tags = append(tags, asVersion)
4558
} else if err, ok := tag.(error); ok {
4659
return nil, fmt.Errorf("failed to run gojq query: %w", err)
4760
}
4861
}
4962

50-
sort.Sort(sort.Reverse(sort.StringSlice(tags)))
63+
sort.Sort(sort.Reverse(tags))
5164

5265
re, err := regexp.Compile(grepString)
5366
if err != nil {
@@ -56,20 +69,16 @@ func parseImageTags(output []byte, grepString string, constraints *semver.Constr
5669

5770
var filteredTags []string
5871
for _, tag := range tags {
59-
if re.MatchString(tag) {
72+
if re.MatchString(tag.Original()) {
6073
ignore := false
6174
if constraints != nil {
62-
version, err := semver.NewVersion(tag)
63-
if err != nil {
64-
return nil, fmt.Errorf("failed to parse version: %w", err)
65-
}
66-
if !constraints.Check(version) {
75+
if !constraints.Check(tag) {
6776
ignore = true
6877
}
6978
}
7079

7180
if !ignore {
72-
filteredTags = append(filteredTags, tag)
81+
filteredTags = append(filteredTags, tag.Original())
7382
}
7483
}
7584
}

tools/ecrimagefetcher/main_test.go

Lines changed: 57 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import (
77
"testing"
88

99
"github.com/Masterminds/semver/v3"
10-
1110
"github.com/stretchr/testify/require"
1211
)
1312

@@ -17,14 +16,55 @@ func mockFetchImageDetailsSuccess(_ string) ([]byte, error) {
1716
"imageTags": ["v1.0.0"]
1817
},
1918
{
20-
"imageTags": ["v1.1.0"]
19+
"imageTags": ["v1.1.2"]
20+
},
21+
{
22+
"imageTags": ["v1.1.11"]
2123
},
2224
{
2325
"imageTags": ["v1.2.0"]
2426
}
2527
]`), nil
2628
}
2729

30+
func mockFetchImageMixedDetailsSuccess(_ string) ([]byte, error) {
31+
return []byte(`[
32+
{
33+
"imageTags": ["alltools-0.0.1"]
34+
},
35+
{
36+
"imageTags": ["1.0.0"]
37+
},
38+
{
39+
"imageTags": ["0.5.0-alpha1"]
40+
},
41+
{
42+
"imageTags": ["0.5.0-alpha2"]
43+
},
44+
{
45+
"imageTags": ["1.0.0-alpha"]
46+
},
47+
{
48+
"imageTags": ["1.0.0-alpha.1"]
49+
},
50+
{
51+
"imageTags": ["1.0.0-alpha.2"]
52+
},
53+
{
54+
"imageTags": ["1.0.0-beta"]
55+
},
56+
{
57+
"imageTags": ["1.0.0-rc2"]
58+
},
59+
{
60+
"imageTags": ["1.0.0-rc1"]
61+
},
62+
{
63+
"imageTags": ["v1.1.2-alpha"]
64+
}
65+
]`), nil
66+
}
67+
2868
func mockFetchImageDetailsError(_ string) ([]byte, error) {
2969
return nil, fmt.Errorf("failed to describe images")
3070
}
@@ -33,7 +73,19 @@ func TestGetLatestImages(t *testing.T) {
3373
t.Run("Success", func(t *testing.T) {
3474
images, err := getLatestImages(mockFetchImageDetailsSuccess, "test-repo", "v1.*", 2, nil)
3575
require.NoError(t, err)
36-
require.Equal(t, "test-repo:v1.2.0,test-repo:v1.1.0", images)
76+
require.Equal(t, "test-repo:v1.2.0,test-repo:v1.1.11", images)
77+
})
78+
79+
t.Run("SuccessWithMixedVersionsWithoutFilter", func(t *testing.T) {
80+
images, err := getLatestImages(mockFetchImageMixedDetailsSuccess, "test-repo", "", 11, nil)
81+
require.NoError(t, err)
82+
require.Equal(t, "test-repo:v1.1.2-alpha,test-repo:1.0.0,test-repo:1.0.0-rc2,test-repo:1.0.0-rc1,test-repo:1.0.0-beta,test-repo:1.0.0-alpha.2,test-repo:1.0.0-alpha.1,test-repo:1.0.0-alpha,test-repo:0.5.0-alpha2,test-repo:0.5.0-alpha1,test-repo:0.0.1", images)
83+
})
84+
85+
t.Run("SuccessWithMixedVersionsWithFilter", func(t *testing.T) {
86+
images, err := getLatestImages(mockFetchImageMixedDetailsSuccess, "test-repo", "^1.*", 4, nil)
87+
require.NoError(t, err)
88+
require.Equal(t, "test-repo:1.0.0,test-repo:1.0.0-rc2,test-repo:1.0.0-rc1,test-repo:1.0.0-beta", images)
3789
})
3890

3991
t.Run("ErrorFetchingDetails", func(t *testing.T) {
@@ -51,15 +103,15 @@ func TestGetLatestImages(t *testing.T) {
51103
t.Run("InsufficientTags", func(t *testing.T) {
52104
images, err := getLatestImages(mockFetchImageDetailsSuccess, "test-repo", "v1.*", 5, nil)
53105
require.NoError(t, err)
54-
require.Equal(t, "test-repo:v1.2.0,test-repo:v1.1.0,test-repo:v1.0.0", images)
106+
require.Equal(t, "test-repo:v1.2.0,test-repo:v1.1.11,test-repo:v1.1.2,test-repo:v1.0.0", images)
55107
})
56108

57109
t.Run("WithConstraint", func(t *testing.T) {
58110
constraints, err := semver.NewConstraint("<v1.2.0")
59111
require.NoError(t, err)
60112
images, err := getLatestImages(mockFetchImageDetailsSuccess, "test-repo", "v1.*", 2, constraints)
61113
require.NoError(t, err)
62-
require.Equal(t, "test-repo:v1.1.0,test-repo:v1.0.0", images)
114+
require.Equal(t, "test-repo:v1.1.11,test-repo:v1.1.2", images)
63115
})
64116
}
65117

tools/ecrimagefetcher/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
22
"name": "ecrimagefetcher",
33
"description": "Tool that fetches latest ECR images for a given repository",
4-
"version": "1.0.1"
4+
"version": "1.0.2"
55
}

0 commit comments

Comments
 (0)