Repository: bazelbuild/bazelisk
Pull request #274 (2021-10-11 04:01:47)

Bump github.com/bazelbuild/rules_go from 0.28.0 to 0.29.0
Bumps [github.com/bazelbuild/rules_go](https://github.com/bazelbuild/rules_go) from 0.28.0 to 0.29.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a href="https://github.com/bazelbuild/rules_go/releases">github.com/bazelbuild/rules_go's releases</a>.</em></p>
<blockquote>
<h2>v0.29.0</h2>
<h2>Changes</h2>
<ul>
<li>
<p>nogo analyzers may now depend on <code>go_library</code> rules (<a href="https://github-redirect.dependabot.com/bazelbuild/rules_go/issues/2922">#2922</a>).</p>
<p>This is a major upgrade to nogo usability that enables the use of
the popular <a href="https://staticcheck.io/">staticcheck</a> tool, via
<a href="https://github.com/sluongng/staticcheck-codegen">https://github.com/sluongng/staticcheck-codegen</a>.</p>
<p>Many thanks to <a href="https://github.com/thomas-wk"><code>@​thomas-wk</code></a></p>
</li>
<li>
<p>Editor / IDE integration (gopackagesdriver) now supports automatic target detection (<a href="https://github-redirect.dependabot.com/bazelbuild/rules_go/issues/2932">#2932</a>).</p>
<p>No user input is required after the <code>GOPACKAGESDRIVER</code> setup.
This effectively deprecates the following environment variables:</p>
<ul>
<li><code>GOPACKAGESDRIVER_BAZEL_TARGETS</code></li>
<li><code>GOPACKAGESDRIVER_BAZEL_QUERY</code></li>
<li><code>GOPACKAGESDRIVER_BAZEL_TAG_FILTERS</code></li>
</ul>
<p>Many thanks to <a href="https://github.com/steeve"><code>@​steeve</code></a> for his ongoing development of gopackagesdriver</p>
</li>
<li>
<p>The rules_cc dependency has been removed (<a href="https://github-redirect.dependabot.com/bazelbuild/rules_go/issues/2950">#2950</a>).</p>
</li>
<li>
<p>rules_go tool builds are now reproducible (<a href="https://github-redirect.dependabot.com/bazelbuild/rules_go/issues/2952">#2952</a>).</p>
</li>
<li>
<p>cgo-related bug fixes: <a href="https://github-redirect.dependabot.com/bazelbuild/rules_go/issues/2930">#2930</a>, <a href="https://github-redirect.dependabot.com/bazelbuild/rules_go/issues/2925">#2925</a>, <a href="https://github-redirect.dependabot.com/bazelbuild/rules_go/issues/2947">#2947</a>, <a href="https://github-redirect.dependabot.com/bazelbuild/rules_go/issues/2926">#2926</a>.</p>
</li>
</ul>
<p>Thanks to all of the contributors.</p>
<h2>Compatibility</h2>
<ul>
<li>Bazel 4.2.0 or higher is now required. The previous minimum version
was 4.0.0.</li>
</ul>
<h2>Updated dependencies</h2>
<p>As always, you can use higher versions of rules_go's dependencies by declaring
them in WORKSPACE before calling <code>go_rules_dependencies</code>. Lower versions may
work but are not supported.</p>
<ul>
<li><code>bazel_skylib</code> updated to <code>v1.1.1</code></li>
<li><code>org_golang_x_tools</code> updated to <code>v0.1.7</code></li>
<li><code>org_golang_x_sys</code> updated to <code>master</code> as of 2021-10-06.</li>
<li><code>org_golang_google_genproto</code> updated to <code>master</code> as of 2021-10-06.</li>
<li><code>go_googleapis</code> updated to <code>master</code> as of 2021-10-06.</li>
</ul>
<h2><code>WORKSPACE</code> code</h2>
<pre><code>load(&quot;@bazel_tools//tools/build_defs/repo:http.bzl&quot;, &quot;http_archive&quot;)
&lt;/tr&gt;&lt;/table&gt; 
</code></pre>
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a href="https://github.com/bazelbuild/rules_go/commit/4955534303141eef9570f447328510e5412d0009"><code>4955534</code></a> Set RULES_GO_VERSION to 0.29.0 (<a href="https://github-redirect.dependabot.com/bazelbuild/rules_go/issues/2978">#2978</a>)</li>
<li><a href="https://github.com/bazelbuild/rules_go/commit/3f8ee3155e2bc3c7520f0fe53026bbc4e4d0e102"><code>3f8ee31</code></a> Upgrade dependencies for v0.29.0 (<a href="https://github-redirect.dependabot.com/bazelbuild/rules_go/issues/2977">#2977</a>)</li>
<li><a href="https://github.com/bazelbuild/rules_go/commit/0535de8950ec83ce6339266917a2c6260d1902f9"><code>0535de8</code></a> Upgrade Bazel to 4.2.0 (<a href="https://github-redirect.dependabot.com/bazelbuild/rules_go/issues/2976">#2976</a>)</li>
<li><a href="https://github.com/bazelbuild/rules_go/commit/f1019ef4c2c22d6ca78257084a9da47e15fc415d"><code>f1019ef</code></a> go_test: add compatibility with fuzzing in Go 1.18+ (<a href="https://github-redirect.dependabot.com/bazelbuild/rules_go/issues/2970">#2970</a>)</li>
<li><a href="https://github.com/bazelbuild/rules_go/commit/61b6c0c6d9bef2a14d483a9a331546e292bf60c7"><code>61b6c0c</code></a> go/tools/releaser: add prepare subcommand (<a href="https://github-redirect.dependabot.com/bazelbuild/rules_go/issues/2913">#2913</a>)</li>
<li><a href="https://github.com/bazelbuild/rules_go/commit/a00b47cd24b3bb855fcf8e1ac4842538f92ad450"><code>a00b47c</code></a> Update go_googleapis to latest (<a href="https://github-redirect.dependabot.com/bazelbuild/rules_go/issues/2959">#2959</a>)</li>
<li><a href="https://github.com/bazelbuild/rules_go/commit/7d62d4cc3e973a5a55d82169805160eb80667180"><code>7d62d4c</code></a> -resource-dir flag for clang should be absolute (<a href="https://github-redirect.dependabot.com/bazelbuild/rules_go/issues/2925">#2925</a>)</li>
<li><a href="https://github.com/bazelbuild/rules_go/commit/f93f505b7652baa9b805116352ee84196e173b33"><code>f93f505</code></a> Supporting versioned dylib in has_versioned_shared_lib_extension (<a href="https://github-redirect.dependabot.com/bazelbuild/rules_go/issues/2947">#2947</a>)</li>
<li><a href="https://github.com/bazelbuild/rules_go/commit/9f77676a87f23c7d5963bb9aef91f07398706809"><code>9f77676</code></a> Make go_test() with embedsrcs work (<a href="https://github-redirect.dependabot.com/bazelbuild/rules_go/issues/2936">#2936</a>)</li>
<li><a href="https://github.com/bazelbuild/rules_go/commit/63dfd99403076331fef0775d52a8039d502d4115"><code>63dfd99</code></a> Allow nogo to depend on go_library (<a href="https://github-redirect.dependabot.com/bazelbuild/rules_go/issues/2922">#2922</a>)</li>
<li>Additional commits viewable in <a href="https://github.com/bazelbuild/rules_go/compare/v0.28.0...v0.29.0">compare view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github.com/bazelbuild/rules_go&package-manager=go_modules&previous-version=0.28.0&new-version=0.29.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
- `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)


</details>


Patch:
diff --git a/BUILD b/BUILD
index 7254d33..394ed85 100644
--- a/BUILD
+++ b/BUILD
@@ -197,6 +197,7 @@ pkg_npm(
         "LICENSE",
         "README.md",
         "bazelisk.js",
+        "bazelisk.d.ts",
         "package.json",
     ],
     deps = [
diff --git a/README.md b/README.md
index 64ca6bf..b1ff4b0 100644
--- a/README.md
+++ b/README.md
@@ -53,6 +53,7 @@ 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.
 - 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):
@@ -76,12 +77,20 @@ You can also override the URL by setting the environment variable `$BAZELISK_BAS
 
 ## Ensuring that your developers use Bazelisk rather than Bazel
 
-Bazel does check the `.bazelversion` file itself, but the failure when it mismatches with the actual version of Bazel can be quite confusing to developers.
+Bazel installers typically provide Bazel's [shell wrapper script] as the `bazel` on the PATH.
+
+When installed this way, Bazel checks the `.bazelversion` file itself, but the failure when it mismatches with the actual version of Bazel can be quite confusing to developers.
 You may find yourself having to explain the difference between Bazel and Bazelisk (especially when you upgrade the pinned version).
 To avoid this, you can add a check in your `tools/bazel` wrapper.
 Since Bazelisk is careful to avoid calling itself in a loop, it always calls the wrapper with the environment variable `BAZELISK_SKIP_WRAPPER` set to `true'.
 You can check for the presence of that variable, and when not found, report a useful error to your users about how to install Bazelisk.
 
+Note that if users directly downloaded a Bazel binary and put it in their PATH, rather than running
+an installer, then `tools/bazel` and `.bazelversion` are not checked. You could call the
+[versions.check](https://github.com/bazelbuild/bazel-skylib/blob/1.1.1/docs/versions_doc.md#versionscheck) starlark module from the beginning of your WORKSPACE to
+require users update their bazel.
+
+[shell wrapper script]: https://github.com/bazelbuild/bazel/blob/master/scripts/packages/bazel.sh
 ## Other features
 
 The Go version of Bazelisk offers two new flags.
diff --git a/bazelisk.d.ts b/bazelisk.d.ts
new file mode 100644
index 0000000..27b1fc4
--- /dev/null
+++ b/bazelisk.d.ts
@@ -0,0 +1,1 @@
+export function getNativeBinary(): string;
diff --git a/core/repositories.go b/core/repositories.go
index f179d1c..8a2919c 100644
--- a/core/repositories.go
+++ b/core/repositories.go
@@ -3,6 +3,7 @@ package core
 import (
 	"errors"
 	"fmt"
+	"strings"
 
 	"github.com/bazelbuild/bazelisk/httputil"
 	"github.com/bazelbuild/bazelisk/platforms"
@@ -116,7 +117,13 @@ func (r *Repositories) resolveFork(bazeliskHome string, vi *versions.Info) (stri
 
 func (r *Repositories) resolveRelease(bazeliskHome string, vi *versions.Info) (string, DownloadFunc, error) {
 	lister := func(bazeliskHome string) ([]string, error) {
-		return r.Releases.GetReleaseVersions(bazeliskHome, vi.LatestOffset+1)
+		var lastN int
+		// Optimization: only fetch last (x+1) releases if the version is "latest-x".
+		// This does not work if the version is "4.x", i.e. if TrackRestriction is set.
+		if vi.TrackRestriction == 0 {
+			lastN = vi.LatestOffset + 1
+		}
+		return r.Releases.GetReleaseVersions(bazeliskHome, lastN)
 	}
 	version, err := resolvePotentiallyRelativeVersion(bazeliskHome, lister, vi)
 	if err != nil {
@@ -179,6 +186,11 @@ func resolvePotentiallyRelativeVersion(bazeliskHome string, lister listVersionsF
 	if err != nil {
 		return "", fmt.Errorf("unable to determine latest version: %v", err)
 	}
+
+	if vi.TrackRestriction > 0 {
+		available = restrictToTrack(available, vi.TrackRestriction)
+	}
+
 	index := len(available) - 1 - vi.LatestOffset
 	if index < 0 {
 		return "", fmt.Errorf("cannot resolve version \"%s\": There are only %d Bazel versions", vi.Value, len(available))
@@ -187,6 +199,17 @@ func resolvePotentiallyRelativeVersion(bazeliskHome string, lister listVersionsF
 	return sorted[index], nil
 }
 
+func restrictToTrack(versions []string, track int) []string {
+	filtered := make([]string, 0)
+	prefix := fmt.Sprintf("%d.", track)
+	for _, v := range versions {
+		if strings.HasPrefix(v, prefix) {
+			filtered = append(filtered, v)
+		}
+	}
+	return filtered
+}
+
 // DownloadFromBaseURL can download Bazel binaries from a specific URL while ignoring the predefined repositories.
 func (r *Repositories) DownloadFromBaseURL(baseURL, version, destDir, destFile string) (string, error) {
 	if !r.supportsBaseURL {
diff --git a/go.mod b/go.mod
index fc5437e..112afa0 100644
--- a/go.mod
+++ b/go.mod
@@ -3,7 +3,7 @@ module github.com/bazelbuild/bazelisk
 go 1.15
 
 require (
-	github.com/bazelbuild/rules_go v0.28.0
+	github.com/bazelbuild/rules_go v0.29.0
 	github.com/hashicorp/go-version v1.3.0
 	github.com/mitchellh/go-homedir v1.1.0
 )
diff --git a/go.sum b/go.sum
index c8ff146..20b426c 100644
--- a/go.sum
+++ b/go.sum
@@ -1,5 +1,5 @@
-github.com/bazelbuild/rules_go v0.28.0 h1:fNtx0dJpG5ENGdMj3/GICoi/7z+ixB3IIW5rERTzOgM=
-github.com/bazelbuild/rules_go v0.28.0/go.mod h1:MC23Dc/wkXEyk3Wpq6lCqz0ZAYOZDw2DR5y3N1q2i7M=
+github.com/bazelbuild/rules_go v0.29.0 h1:SfxjyO/V68rVnzOHop92fB0gv/Aa75KNLAN0PMqXbIw=
+github.com/bazelbuild/rules_go v0.29.0/go.mod h1:MC23Dc/wkXEyk3Wpq6lCqz0ZAYOZDw2DR5y3N1q2i7M=
 github.com/hashicorp/go-version v1.3.0 h1:McDWVJIU/y+u1BRV06dPaLfLCaT7fUTJLp5r04x7iNw=
 github.com/hashicorp/go-version v1.3.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
 github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
diff --git a/package.json b/package.json
index aa3f430..a8b56b0 100644
--- a/package.json
+++ b/package.json
@@ -7,6 +7,8 @@
         "bazelisk": "bazelisk.js",
         "bazel": "bazelisk.js"
     },
+    "main": "bazelisk.js",
+    "types": "bazelisk.d.ts",
     "keywords": [
         "bazel"
     ],
diff --git a/versions/versions.go b/versions/versions.go
index 4ef6245..8ea3a9b 100644
--- a/versions/versions.go
+++ b/versions/versions.go
@@ -17,7 +17,7 @@ const (
 )
 
 var (
-	releasePattern       = regexp.MustCompile(`^(\d+\.\d+\.\d+)$`)
+	releasePattern       = regexp.MustCompile(`^(\d+)\.(x|\d+\.\d+)$`)
 	candidatePattern     = regexp.MustCompile(`^(\d+\.\d+\.\d+)rc(\d+)$`)
 	rollingPattern       = regexp.MustCompile(`^\d+\.0\.0-pre\.\d{8}(\.\d+){1,2}$`)
 	latestReleasePattern = regexp.MustCompile(`^latest(?:-(?P<offset>\d+))?$`)
@@ -27,16 +27,24 @@ var (
 // Info represents a structured Bazel version identifier.
 type Info struct {
 	IsRelease, IsCandidate, IsCommit, IsFork, IsRolling, IsRelative, IsDownstream bool
-	Fork, Value                                                        string
-	LatestOffset                                                       int
+	Fork, Value                                                                   string
+	LatestOffset, TrackRestriction                                                int
 }
 
 // Parse extracts and returns structured information about the given Bazel version label.
 func Parse(fork, version string) (*Info, error) {
 	vi := &Info{Fork: fork, Value: version, IsFork: isFork(fork)}
 
-	if releasePattern.MatchString(version) {
+	if m := releasePattern.FindStringSubmatch(version); m != nil {
 		vi.IsRelease = true
+		if m[2] == "x" {
+			track, err := strconv.Atoi(m[1])
+			if err != nil {
+				return nil, fmt.Errorf("invalid version %q, expected something like '5.2.1' or '5.x'", version)
+			}
+			vi.IsRelative = true
+			vi.TrackRestriction = track
+		}
 	} else if m := latestReleasePattern.FindStringSubmatch(version); m != nil {
 		vi.IsRelease = true
 		vi.IsRelative = true


Test patch:
diff --git a/bazelisk_version_test.go b/bazelisk_version_test.go
index 0de0f62..1a3e06a 100644
--- a/bazelisk_version_test.go
+++ b/bazelisk_version_test.go
@@ -227,6 +227,29 @@ 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, nil, false)
+	version, _, err := repos.ResolveVersion(tmpDir, versions.BazelUpstream, "4.x")
+
+	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)
+	}
+}
+
 type gcsSetup struct {
 	baseURL         string
 	versionPrefixes []string