@@ -124,15 +124,54 @@ func downloadBinaryAssets(ctx context.Context, binaryAssetsDirectory, binaryAsse
124
124
}
125
125
}
126
126
127
+ var requestedRange semver.Range
128
+ if binaryAssetsVersion != "" {
129
+ binaryAssetsVersion = strings .TrimPrefix (binaryAssetsVersion , "v" )
130
+ parsedVersion , errV := semver .ParseTolerant (binaryAssetsVersion )
131
+ parsedRange , errR := semver .ParseRange (binaryAssetsVersion )
132
+
133
+ switch {
134
+ // When an exact version is requested, don't look for it in the release index.
135
+ case errV == nil && parsedVersion .String () == binaryAssetsVersion :
136
+ requestedRange = nil
137
+
138
+ // When the version looks like a range, apply it to the index.
139
+ case errR == nil :
140
+ requestedRange = parsedRange
141
+
142
+ // When the version isn't exact, turn it into a range.
143
+ //
144
+ // The `setup-envtest` tool interprets a partial version to mean "latest stable with that prefix."
145
+ // For example, "1" and "1.2" are akin to "1.x.x" and "1.2.x" in [semver.ParseRange].
146
+ // [semver.ParseTolerant] fills in missing minor or patch with "0", so this replaces those with "x".
147
+ //
148
+ // That *should* produce a valid range. If it doesn't, use the original value and skip the index.
149
+ case errV == nil :
150
+ suffix := strings .TrimPrefix (parsedVersion .FinalizeVersion (), binaryAssetsVersion )
151
+ suffix = strings .ReplaceAll (suffix , "0" , "x" )
152
+ parsedRange , errR = semver .ParseRange (binaryAssetsVersion + suffix )
153
+
154
+ if errR == nil {
155
+ requestedRange = parsedRange
156
+ } else {
157
+ requestedRange = nil
158
+ }
159
+ }
160
+ } else {
161
+ // When no version is requested, look for one in the release index.
162
+ requestedRange = semver .MustParseRange (">0.0.0" )
163
+ }
164
+
165
+ // When a range a versions is requested, select one from the release index.
127
166
var binaryAssetsIndex * index
128
- if binaryAssetsVersion == "" || strings . Count ( binaryAssetsVersion , "." ) < 2 {
167
+ if requestedRange != nil {
129
168
var err error
130
169
binaryAssetsIndex , err = getIndex (ctx , binaryAssetsIndexURL )
131
170
if err != nil {
132
171
return "" , "" , "" , err
133
172
}
134
173
135
- binaryAssetsVersion , err = latestStableVersionFromIndex (binaryAssetsIndex , binaryAssetsVersion )
174
+ binaryAssetsVersion , err = latestStableVersionFromIndex (binaryAssetsIndex , requestedRange )
136
175
if err != nil {
137
176
return "" , "" , "" , err
138
177
}
@@ -219,6 +258,8 @@ func fileExists(path string) bool {
219
258
}
220
259
221
260
func downloadBinaryAssetsArchive (ctx context.Context , index * index , version string , out io.Writer ) error {
261
+ version = "v" + strings .TrimPrefix (version , "v" )
262
+
222
263
archives , ok := index .Releases [version ]
223
264
if ! ok {
224
265
return fmt .Errorf ("failed to find envtest binaries for version %s" , version )
@@ -252,26 +293,20 @@ func downloadBinaryAssetsArchive(ctx context.Context, index *index, version stri
252
293
return readBody (resp , out , archiveName , archive .Hash )
253
294
}
254
295
255
- func latestStableVersionFromIndex (index * index , prefix string ) (string , error ) {
296
+ func latestStableVersionFromIndex (index * index , satisfying semver. Range ) (string , error ) {
256
297
if len (index .Releases ) == 0 {
257
298
return "" , fmt .Errorf ("failed to find latest stable version from index: index is empty" )
258
299
}
259
300
260
- prefix = strings .TrimPrefix (prefix , "v" )
261
301
parsedVersions := []semver.Version {}
262
302
for releaseVersion := range index .Releases {
263
- // Filter on prefix.
264
- if ! strings .HasPrefix (strings .TrimPrefix (releaseVersion , "v" ), prefix ) {
265
- continue
266
- }
267
-
268
303
v , err := semver .ParseTolerant (releaseVersion )
269
304
if err != nil {
270
305
return "" , fmt .Errorf ("failed to parse version %q: %w" , releaseVersion , err )
271
306
}
272
307
273
- // Filter out pre-releases.
274
- if len (v .Pre ) > 0 {
308
+ // Filter out pre-releases and undesirable versions .
309
+ if len (v .Pre ) > 0 || ! satisfying ( v ) {
275
310
continue
276
311
}
277
312
0 commit comments