Repository: bazelbuild/bazelisk
Pull request #319 (2022-05-20 05:48:35)

Fetch rolling releases from GCS
Closes https://github.com/bazelbuild/bazelisk/issues/228

Has the benefit of avoiding github rate limits on github actions when using rolling releases

keith: I need to figure out how the tests work to update them
keith: Yay, done

Patch:
diff --git a/bazelisk.go b/bazelisk.go
index 1aebe0d..5cdee07 100644
--- a/bazelisk.go
+++ b/bazelisk.go
@@ -26,9 +26,8 @@ import (
 func main() {
 	gcs := &repositories.GCSRepo{}
 	gitHub := repositories.CreateGitHubRepo(core.GetEnvOrConfig("BAZELISK_GITHUB_TOKEN"))
-	// Fetch LTS releases, release candidates and Bazel-at-commits from GCS, forks and rolling releases from GitHub.
-	// TODO(https://github.com/bazelbuild/bazelisk/issues/228): get rolling releases from GCS, too.
-	repos := core.CreateRepositories(gcs, gcs, gitHub, gcs, gitHub, true)
+	// Fetch LTS releases, release candidates, rolling releases and Bazel-at-commits from GCS, forks from GitHub.
+	repos := core.CreateRepositories(gcs, gcs, gitHub, gcs, gcs, true)
 
 	exitCode, err := core.RunBazelisk(os.Args[1:], repos)
 	if err != nil {
diff --git a/repositories/gcs.go b/repositories/gcs.go
index 82e33dd..170f172 100644
--- a/repositories/gcs.go
+++ b/repositories/gcs.go
@@ -239,3 +239,40 @@ func (gcs *GCSRepo) DownloadAtCommit(commit, destDir, destFile string) (string,
 	url := fmt.Sprintf("%s/%s/%s/bazel", nonCandidateBaseURL, platforms.GetPlatform(), commit)
 	return httputil.DownloadBinary(url, destDir, destFile)
 }
+
+// RollingRepo
+
+// GetRollingVersions returns a list of all available rolling release versions for the newest release.
+func (gcs *GCSRepo) GetRollingVersions(bazeliskHome string) ([]string, error) {
+	history, err := getVersionHistoryFromGCS()
+	if err != nil {
+		return []string{}, err
+	}
+
+	newest := history[len(history)-1]
+	versions, _, err := listDirectoriesInReleaseBucket(newest + "/rolling/")
+	if err != nil {
+		return []string{}, err
+	}
+
+	releases := make([]string, 0)
+	for _, v := range versions {
+		if !strings.Contains(v, "rc") {
+			releases = append(releases, strings.Split(v, "/")[2])
+		}
+	}
+
+	return releases, nil
+}
+
+// DownloadRolling downloads the given Bazel version into the specified location and returns the absolute path.
+func (gcs *GCSRepo) DownloadRolling(version, destDir, destFile string) (string, error) {
+	srcFile, err := platforms.DetermineBazelFilename(version, true)
+	if err != nil {
+		return "", err
+	}
+
+	release_version := strings.Split(version, "-")[0]
+	url := fmt.Sprintf("%s/%s/rolling/%s/%s", candidateBaseURL, release_version, version, srcFile)
+	return httputil.DownloadBinary(url, destDir, destFile)
+}
diff --git a/repositories/github.go b/repositories/github.go
index 60baacb..b75edcd 100644
--- a/repositories/github.go
+++ b/repositories/github.go
@@ -6,7 +6,6 @@ import (
 
 	"github.com/bazelbuild/bazelisk/httputil"
 	"github.com/bazelbuild/bazelisk/platforms"
-	"github.com/bazelbuild/bazelisk/versions"
 )
 
 const (
@@ -89,14 +88,3 @@ func (gh *GitHubRepo) DownloadVersion(fork, version, destDir, destFile string) (
 	url := fmt.Sprintf(urlPattern, fork, version, filename)
 	return httputil.DownloadBinary(url, destDir, destFile)
 }
-
-// GetRollingVersions returns a list of all available rolling release versions.
-func (gh *GitHubRepo) GetRollingVersions(bazeliskHome string) ([]string, error) {
-	// Release candidates are uploaded to GCS only, which means that all prerelease binaries on GitHub belong to rolling releases.
-	return gh.getFilteredVersions(bazeliskHome, versions.BazelUpstream, true)
-}
-
-// DownloadRolling downloads the given Bazel version into the specified location and returns the absolute path.
-func (gh *GitHubRepo) DownloadRolling(version, destDir, destFile string) (string, error) {
-	return gh.DownloadVersion(versions.BazelUpstream, version, destDir, destFile)
-}


Test patch:
diff --git a/bazelisk_version_test.go b/bazelisk_version_test.go
index b754f81..bd83cf7 100644
--- a/bazelisk_version_test.go
+++ b/bazelisk_version_test.go
@@ -208,8 +208,8 @@ func TestResolveLatestVersion_GitHubIsDown(t *testing.T) {
 }
 
 func TestAcceptRollingReleaseName(t *testing.T) {
-	gh := repositories.CreateGitHubRepo("test_token")
-	repos := core.CreateRepositories(nil, nil, nil, nil, gh, false)
+	gcs := &repositories.GCSRepo{}
+	repos := core.CreateRepositories(nil, nil, nil, nil, gcs, false)
 
 	for _, version := range []string{"10.0.0-pre.20201103.4", "10.0.0-pre.20201103.4.2"} {
 		resolvedVersion, _, err := repos.ResolveVersion(tmpDir, "", version)
@@ -225,31 +225,13 @@ func TestAcceptRollingReleaseName(t *testing.T) {
 }
 
 func TestResolveLatestRollingRelease(t *testing.T) {
-	text := `
-	[
-	  {
-		"tag_name": "4.0.0",
-		"prerelease": false
-	  },
-	  {
-		"tag_name": "5.0.0-pre.20210319.1",
-		"prerelease": true
-	  },
-	  {
-		"tag_name": "5.0.0-pre.20210322.4",
-		"prerelease": true
-	  },
-	  {
-		"tag_name": "5.0.0",
-		"prerelease": false
-	  }
-	]
-	`
-	transport := installTransport()
-	transport.AddResponse("https://api.github.com/repos/bazelbuild/bazel/releases", 200, text, nil)
+	s := setUp(t)
+	s.AddVersion("11.0.0", false, nil, []string{"11.0.0/rolling/11.0.0-pre.20210503.1"})
+	s.AddVersion("12.0.0", false, nil, []string{"12.0.0/rolling/12.0.0-pre.20210504.1"})
+	s.Finish()
 
-	gh := repositories.CreateGitHubRepo("test_token")
-	repos := core.CreateRepositories(nil, nil, nil, nil, gh, false)
+	gcs := &repositories.GCSRepo{}
+	repos := core.CreateRepositories(nil, nil, nil, nil, gcs, false)
 
 	version, _, err := repos.ResolveVersion(tmpDir, "", rollingReleaseIdentifier)
 
@@ -257,7 +239,7 @@ func TestResolveLatestRollingRelease(t *testing.T) {
 		t.Fatalf("ResolveVersion(%q, \"\", %q): expected no error, but got %v", tmpDir, rollingReleaseIdentifier, err)
 	}
 
-	want := "5.0.0-pre.20210322.4"
+	want := "12.0.0-pre.20210504.1"
 	if version != want {
 		t.Fatalf("ResolveVersion(%q, \"\", %q) = %v, but expected %v", tmpDir, rollingReleaseIdentifier, version, want)
 	}
@@ -308,9 +290,7 @@ func (g *gcsSetup) AddVersion(version string, hasRelease bool, rcs []int, rollin
 		register(fmt.Sprintf("rc%d", rc))
 	}
 
-	for _, r := range rolling {
-		register(r)
-	}
+	g.addURL(fmt.Sprintf("%s/rolling/", version), false, rolling...)
 
 	// The /release/ URLs have to exist, even if there is no release. In this case GCS returns no items, though.
 	releasePrefix := fmt.Sprintf("%s/release/", version)