Skip to content

Commit 5b4d2d6

Browse files
authored
fix: Fixing #4556 (#5640)
* fix: Fixing #4556 * fix: Addressing empty behavior
1 parent 0688270 commit 5b4d2d6

3 files changed

Lines changed: 125 additions & 1 deletion

File tree

internal/tf/cache/controllers/provider.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,12 +84,17 @@ func (controller *ProviderController) getVersionsAction(ctx echo.Context) error
8484
}
8585
}
8686

87+
validVersions, invalidVersions := allVersions.FilterValid()
88+
for _, v := range invalidVersions {
89+
controller.Logger.Warnf("Skipping invalid version %q for provider %s", v, provider.Address())
90+
}
91+
8792
versions := struct {
8893
ID string `json:"id"`
8994
Versions models.Versions `json:"versions"`
9095
}{
9196
ID: provider.Address(),
92-
Versions: allVersions,
97+
Versions: validVersions,
9398
}
9499

95100
return ctx.JSON(http.StatusOK, versions)

internal/tf/cache/models/provider.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ import (
66
"net/url"
77
"path"
88
"strings"
9+
10+
goversion "github.com/hashicorp/go-version"
911
)
1012

1113
type Providers []*Provider
@@ -64,6 +66,30 @@ func (version Version) String() string {
6466
return fmt.Sprintf("%s/%s/%s", version.Version, version.Protocols, version.Platforms)
6567
}
6668

69+
// FilterValid returns only versions with valid semver strings that conform to
70+
// the Terraform registry protocol (no "v" prefix, no empty strings).
71+
// The second return value contains the invalid version strings that were filtered out.
72+
func (versions Versions) FilterValid() (Versions, []string) {
73+
valid := make(Versions, 0, len(versions))
74+
invalid := make([]string, 0, len(versions))
75+
76+
for _, v := range versions {
77+
if v.Version == "" || strings.HasPrefix(v.Version, "v") {
78+
invalid = append(invalid, v.Version)
79+
continue
80+
}
81+
82+
if _, err := goversion.NewVersion(v.Version); err != nil {
83+
invalid = append(invalid, v.Version)
84+
continue
85+
}
86+
87+
valid = append(valid, v)
88+
}
89+
90+
return valid, invalid
91+
}
92+
6793
type Platforms []*Platform
6894

6995
type Platform struct {

internal/tf/cache/models/provider_test.go

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,99 @@ import (
1010
"github.com/stretchr/testify/require"
1111
)
1212

13+
func TestFilterValid(t *testing.T) {
14+
t.Parallel()
15+
16+
testCases := []struct {
17+
name string
18+
input models.Versions
19+
expectedValid []string
20+
expectedInvalid []string
21+
}{
22+
{
23+
name: "all valid versions",
24+
input: models.Versions{
25+
{Version: "1.0.0"},
26+
{Version: "2.5.2"},
27+
{Version: "0.1.0-beta1"},
28+
},
29+
expectedValid: []string{"1.0.0", "2.5.2", "0.1.0-beta1"},
30+
expectedInvalid: []string{},
31+
},
32+
{
33+
name: "v-prefixed versions are filtered",
34+
input: models.Versions{
35+
{Version: "1.0.0"},
36+
{Version: "v2.5.3"},
37+
{Version: "v1.0.0"},
38+
},
39+
expectedValid: []string{"1.0.0"},
40+
expectedInvalid: []string{"v2.5.3", "v1.0.0"},
41+
},
42+
{
43+
name: "empty strings are filtered",
44+
input: models.Versions{
45+
{Version: "1.0.0"},
46+
{Version: ""},
47+
{Version: "2.0.0"},
48+
},
49+
expectedValid: []string{"1.0.0", "2.0.0"},
50+
expectedInvalid: []string{""},
51+
},
52+
{
53+
name: "garbage strings are filtered",
54+
input: models.Versions{
55+
{Version: "1.0.0"},
56+
{Version: "not-a-version"},
57+
{Version: "latest"},
58+
},
59+
expectedValid: []string{"1.0.0"},
60+
expectedInvalid: []string{"not-a-version", "latest"},
61+
},
62+
{
63+
name: "mixed valid and invalid",
64+
input: models.Versions{
65+
{Version: "1.0.0"},
66+
{Version: "v2.5.3-alpha1"},
67+
{Version: ""},
68+
{Version: "3.1.4"},
69+
{Version: "not-a-version"},
70+
{Version: "0.1.0-beta1"},
71+
},
72+
expectedValid: []string{"1.0.0", "3.1.4", "0.1.0-beta1"},
73+
expectedInvalid: []string{"v2.5.3-alpha1", "", "not-a-version"},
74+
},
75+
{
76+
name: "all invalid",
77+
input: models.Versions{{Version: "v1.0.0"}, {Version: ""}, {Version: "bad"}},
78+
expectedValid: []string{},
79+
expectedInvalid: []string{"v1.0.0", "", "bad"},
80+
},
81+
{
82+
name: "empty input",
83+
input: models.Versions{},
84+
expectedValid: []string{},
85+
expectedInvalid: []string{},
86+
},
87+
}
88+
89+
for _, tc := range testCases {
90+
t.Run(tc.name, func(t *testing.T) {
91+
t.Parallel()
92+
93+
valid, invalid := tc.input.FilterValid()
94+
95+
validStrs := make([]string, 0, len(valid))
96+
for _, v := range valid {
97+
validStrs = append(validStrs, v.Version)
98+
}
99+
100+
assert.Equal(t, tc.expectedValid, validStrs)
101+
assert.Equal(t, tc.expectedInvalid, invalid)
102+
})
103+
}
104+
}
105+
13106
func TestResolveRelativeReferences(t *testing.T) {
14107
t.Parallel()
15108

0 commit comments

Comments
 (0)