bazel-skylib icon indicating copy to clipboard operation
bazel-skylib copied to clipboard

Support minimum supported bazel version check from bazelisk's .bazelversion

Open davido opened this issue 5 years ago • 18 comments

Gerrit Code Review project is optionally supporting Bazelisk, by providing .bazelversion file. In the same time, we are checking the minimum supported Bazel version in WORKSPACE file by using bazel_skylib's versions.check() function (in case the build is invoked with Bazel and not with Bazelisk command), e.g.:

http_archive(
    name = "bazel_skylib",
    sha256 = "2ea8a5ed2b448baf4a6855d3ce049c4c452a6470b1efd1504fdb7c1c134d220a",
    strip_prefix = "bazel-skylib-0.8.0",
    urls = ["https://github.com/bazelbuild/bazel-skylib/archive/0.8.0.tar.gz"],
)

load("@bazel_skylib//lib:versions.bzl", "versions")

versions.check(minimum_bazel_version = "0.29.0")

However, this is disadvantageously, to maintain Bazel versions in two different places, and upgrade them in two places, when Bazel version is bumped, like it was done in this CL: [1]:

  1. .bazelversion
  2. WORKSPACE

What we need is a supported built-in way to check minimum supported Bazel version check from .bazelversion, e.g.:

bazel_version_check_from_bazelversion_file()

with the outcome, that the Build would break, if Bazel version is less than 0.29.

Bonus point, would be to not invoke anything, but just add a line in .bazelrc file, e.g.:

build --bazel_version_check_from_bazelversion_file

Even a bigger bonus point, when this check performed automatically, without saying anything (neither in WORKSPACE nor in .bazelrc files). So, if there is .bazelversion file with content 1.0.0, and I am invoking the build with bazel version 0.0.1, then the build should just fail.

[1] https://gerrit-review.googlesource.com/c/gerrit/+/232533

davido avatar Sep 01 '19 21:09 davido

Do you really need the version check? If you use Bazelisk and Bazelisk uses the .bazelversion, you should be fine.

Bazel doesn't know about .bazelversion.

laurentlb avatar Sep 03 '19 13:09 laurentlb

I think you can get the version from .bazelversion with a custom repository rule.

WORKSPACE:

http_archive(
    name = "bazel_skylib",
    sha256 = "2ea8a5ed2b448baf4a6855d3ce049c4c452a6470b1efd1504fdb7c1c134d220a",
    strip_prefix = "bazel-skylib-0.8.0",
    urls = ["https://github.com/bazelbuild/bazel-skylib/archive/0.8.0.tar.gz"],
)

load("//:bazelisk_version.bzl", "bazelisk_version")
bazelisk_version(name = "bazelisk_version",)
load("@bazelisk_version//:check.bzl", "check_bazelisk_version")
check_bazelisk_version()

bazelisk_version.bzl:


_template = """
load("@bazel_skylib//lib:versions.bzl", "versions")

def check_bazelisk_version():
  versions.check(minimum_bazel_version = "{version}")
""".strip()

def _impl(repository_ctx):
  repository_ctx.symlink(Label('@//:.bazelversion'), '.bazelversion')
  bazelversion = repository_ctx.read('.bazelversion').strip()

  repository_ctx.file('BUILD', executable=False)

  repository_ctx.file('check.bzl', executable=False, content=_template.format(version=bazelversion))

bazelisk_version = repository_rule(implementation=_impl)

Yannic avatar Sep 03 '19 14:09 Yannic

Thanks @Yannic. Would it be an option to implement that check in bazel_skylib, as this use case may be interesting for other projects as well.

@laurentlb Not all users and developers of Gerrit switched to using Bazelisk, and still using Bazel directly, so that yes, unfortunately we still need that check in WORKSPACE file.

davido avatar Sep 04 '19 05:09 davido

@Yannic Thank you for your rule! Could you please explain what is the purpose of repository_ctx.symlink(Label('@//:.bazelversion'), '.bazelversion') statement?

konste avatar Feb 19 '20 01:02 konste

FTR: Starting from Bazel release 2.0.0 bazel shell script was extended to perform the version check. FWIW, Gerrit project removed the version check entirely.

davido avatar Feb 19 '20 06:02 davido

AFAIU Bazel shell script does not work on Windows and we want to have version check on all three supported platforms.

konste avatar Feb 19 '20 06:02 konste

@philwo Is there any plans to backport Shellzelisk from 2a8cc7075f741721563efd9dc050ca3458cde30b to Windows? If not, would it make sense to include Yannic's version check to check against .bazelversion in some common place, like bazel_skylib or bazel itself?

davido avatar Feb 19 '20 07:02 davido

@davido No plans for a wrapper script for Windows that I know of. Considering that there are various ways of installing Bazel and not all of them include the wrapper script, I would recommend to implement a version check in bazel_skylib or bazel. This sounds like a good idea to me.

The wrapper or Bazelisk would help people to automatically run a compatible Bazel version. The Starlark-based version check would then act as a second layer of defense and catch all users (even for people who directly run the Bazel binary without any wrappers).

philwo avatar Feb 19 '20 09:02 philwo

@laurentlb Could we add Yannic's check in a skylib, WDYT?

philwo avatar Feb 19 '20 09:02 philwo

Maybe. This can be decided on skylib repository (PR or issue).

laurentlb avatar Feb 19 '20 12:02 laurentlb

@Yannic Can you upload your rule (or extend the existing check_version rule) to check against the content of .bazelversion to skylib repository?

davido avatar Feb 19 '20 13:02 davido

Maybe. This can be decided on skylib repository (PR or issue).

@laurentlb Can you move this issue to skylib repository? It seems, that I can not do it.

davido avatar Feb 19 '20 13:02 davido

I'll move it over.

philwo avatar Feb 19 '20 13:02 philwo

Thank you for doing it, guys!

konste avatar Feb 19 '20 14:02 konste

Thanks @philwo !

davido avatar Feb 19 '20 16:02 davido

Still could somebody please explain the purpose of this line repository_ctx.symlink(Label('@//:.bazelversion'), '.bazelversion') in the rule implementation by @Yannic ? Can't repository_ctx.read() on the next line be used on the file name directly?

konste avatar Feb 19 '20 17:02 konste

@konste I wrote this a long time ago and didn't exactly try very hard to find a clean solution. This line creates a symlink from @//:.bazelversion to @bazelisk_version//:.bazelversion. I think I had some trouble reading the original file and this was the easiest workaround, but as I said, my memory might be off, and I'm sure there's a nicer solution than that snipped above ;).

Yannic avatar Feb 19 '20 18:02 Yannic

No matter what solution, this maybe a a good feature for the users. One scenario is if we want everyone use the bazel for the LTS version, such as > 4.0.0.

libratiger avatar Nov 11 '21 01:11 libratiger