Skip to content

Commit

Permalink
Implement wildcard version identifier "N.*" (#636)
Browse files Browse the repository at this point in the history
* Implement wildcard version identifier "N.*"

Unlike the floating version identifier "N.x", "N.*" can also return release candidates.

Fixes #630

* Fix inconsistent test name
  • Loading branch information
fweikert authored Nov 20, 2024
1 parent e81f342 commit 1f492e5
Show file tree
Hide file tree
Showing 5 changed files with 71 additions and 34 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,8 @@ Bazelisk currently understands the following formats for version labels:
Previous releases can be specified via `latest-1`, `latest-2` etc.
- A version number like `0.17.2` means that exact version of Bazel.
It can also be a release candidate version like `0.20.0rc3`, or a rolling release version like `5.0.0-pre.20210317.1`.
- A floating version identifier like `4.x` that returns the latest release from the LTS series started by Bazel 4.0.0.
- A floating version identifier like `4.x` that returns the latest **release** from the LTS series started by Bazel 4.0.0.
- A wildcard version identifier like `4.*` that returns the latest **release or candidate** from the LTS series started by Bazel 4.0.0.
- The hash of a Git commit. Please note that Bazel binaries are only available for commits that passed [Bazel CI](https://buildkite.com/bazel/bazel-bazel).

Additionally, a few special version names are supported for our official releases only (these formats do not work when using a fork):
Expand Down
74 changes: 54 additions & 20 deletions bazelisk_version_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -256,26 +256,60 @@ func TestResolveLatestRollingRelease(t *testing.T) {
}
}

func TestAcceptFloatingReleaseVersions(t *testing.T) {
s := setUp(t)
s.AddVersion("3.0.0", true, nil, []string{"4.0.0-pre.20210504.1"})
s.AddVersion("4.0.0", true, nil, nil)
s.AddVersion("4.1.0", true, nil, nil)
s.AddVersion("4.2.0", true, nil, nil)
s.AddVersion("4.2.1", true, []int{1, 2}, nil)
s.AddVersion("5.0.0", true, nil, nil)
s.Finish()

gcs := &repositories.GCSRepo{}
repos := core.CreateRepositories(gcs, nil, nil, nil, false)
version, _, err := repos.ResolveVersion(tmpDir, versions.BazelUpstream, "4.x", config.Null())

if err != nil {
t.Fatalf("Version resolution failed unexpectedly: %v", err)
}
expectedVersion := "4.2.1"
if version != expectedVersion {
t.Fatalf("Expected version %s, but got %s", expectedVersion, version)
func TestAcceptTrackBasedReleaseVersions(t *testing.T) {
tests := []struct {
name string
requestedVersion string
releaseExists bool
wantVersion string
}{
{
name: "Floating_ReleaseExists",
requestedVersion: "4.x",
releaseExists: true,
wantVersion: "4.2.1",
},
{
name: "Floating_NoRelease",
requestedVersion: "4.x",
releaseExists: false,
wantVersion: "4.2.0",
},
{
name: "Wildcard_ReleaseExists",
requestedVersion: "4.*",
releaseExists: true,
wantVersion: "4.2.1",
},
{
name: "Wildcard_NoRelease",
requestedVersion: "4.*",
releaseExists: false,
wantVersion: "4.2.1rc3",
},
}

for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
s := setUp(t)
s.AddVersion("4.0.0", true, nil, []string{"4.0.0-pre.20210504.1"})
s.AddVersion("4.1.0", true, nil, nil)
s.AddVersion("4.2.0", true, nil, nil)
s.AddVersion("4.2.1", test.releaseExists, []int{1, 2, 3}, nil)
s.AddVersion("5.0.0", true, nil, nil)
s.Finish()

gcs := &repositories.GCSRepo{}
repos := core.CreateRepositories(gcs, nil, nil, nil, false)
version, _, err := repos.ResolveVersion(tmpDir, versions.BazelUpstream, test.requestedVersion, config.Null())

if err != nil {
t.Fatalf("Version resolution failed unexpectedly: %v", err)
}
if version != test.wantVersion {
t.Fatalf("Expected version %s, but got %s", test.wantVersion, version)
}
})
}
}

Expand Down
9 changes: 6 additions & 3 deletions core/repositories.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ func (r *Repositories) ResolveVersion(bazeliskHome, fork, version string, config
}

func (r *Repositories) resolveFork(bazeliskHome string, vi *versions.Info, config config.Config) (string, DownloadFunc, error) {
if vi.IsRelative && (vi.IsCandidate || vi.IsCommit) {
if vi.IsRelative && (vi.MustBeCandidate || vi.IsCommit) {
return "", nil, errors.New("forks do not support last_rc and last_green")
}
lister := func(bazeliskHome string) ([]string, error) {
Expand Down Expand Up @@ -131,10 +131,13 @@ func (r *Repositories) resolveLTS(bazeliskHome string, vi *versions.Info, config
Track: vi.TrackRestriction,
}

if vi.IsRelease {
if vi.MustBeRelease {
opts.Filter = IsRelease
} else {
} else if vi.MustBeCandidate {
opts.Filter = IsCandidate
} else {
// Wildcard -> can be either release or candidate
opts.Filter = func(v string) bool { return true }
}

lister := func(bazeliskHome string) ([]string, error) {
Expand Down
1 change: 0 additions & 1 deletion repositories/gcs.go
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,6 @@ func (gcs *GCSRepo) matchingVersions(history []string, opts *core.FilterOpts) ([
// history is a list of base versions in ascending order (i.e. X.Y.Z, no rolling releases or candidates).
for hpos := len(history) - 1; hpos >= 0; hpos-- {
baseVersion := history[hpos]

if opts.Track > 0 {
track, err := getTrack(baseVersion)
if err != nil {
Expand Down
18 changes: 9 additions & 9 deletions versions/versions.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ const (

var (
releasePattern = regexp.MustCompile(`^(\d+)\.\d+\.\d+$`)
trackPattern = regexp.MustCompile(`^(\d+)\.x$`)
trackPattern = regexp.MustCompile(`^(\d+)\.(x|\*)$`)
patchPattern = regexp.MustCompile(`^(\d+\.\d+\.\d+)-([\w\d]+)$`)
candidatePattern = regexp.MustCompile(`^(\d+\.\d+\.\d+)rc(\d+)$`)
rollingPattern = regexp.MustCompile(`^\d+\.0\.0-pre\.\d{8}(\.\d+){1,2}$`)
Expand All @@ -28,7 +28,7 @@ var (

// Info represents a structured Bazel version identifier.
type Info struct {
IsRelease, IsCandidate bool
MustBeRelease, MustBeCandidate bool
IsLTS, IsRolling bool
IsCommit, IsFork, IsRelative bool
Fork, Value string
Expand All @@ -41,22 +41,22 @@ func Parse(fork, version string) (*Info, error) {

if m := releasePattern.FindStringSubmatch(version); m != nil {
vi.IsLTS = true
vi.IsRelease = true
vi.MustBeRelease = true
} else if m := trackPattern.FindStringSubmatch(version); m != nil {
track, err := strconv.Atoi(m[1])
if err != nil {
return nil, fmt.Errorf("invalid version %q, expected something like '5.x'", version)
return nil, fmt.Errorf("invalid version %q, expected something like '5.x' or '5.*'", version)
}
vi.IsLTS = true
vi.IsRelease = true
vi.MustBeRelease = (m[2] == "x")
vi.IsRelative = true
vi.TrackRestriction = track
} else if patchPattern.MatchString(version) {
vi.IsLTS = true
vi.IsRelease = true
vi.MustBeRelease = true
} else if m := latestReleasePattern.FindStringSubmatch(version); m != nil {
vi.IsLTS = true
vi.IsRelease = true
vi.MustBeRelease = true
vi.IsRelative = true
if m[1] != "" {
offset, err := strconv.Atoi(m[1])
Expand All @@ -67,10 +67,10 @@ func Parse(fork, version string) (*Info, error) {
}
} else if candidatePattern.MatchString(version) {
vi.IsLTS = true
vi.IsCandidate = true
vi.MustBeCandidate = true
} else if version == "last_rc" {
vi.IsLTS = true
vi.IsCandidate = true
vi.MustBeCandidate = true
vi.IsRelative = true
} else if commitPattern.MatchString(version) {
vi.IsCommit = true
Expand Down

0 comments on commit 1f492e5

Please sign in to comment.