bazel: Bazel installer stopped working after d3f8efc, if project has .bazelversion file
After installing of bazel 2.0.0rc3 I am seeing this:
$ cd gerrit
$ cat .bazelversion
2.0.0rc3
bazelisk build :gerrit
019/12/02 21:55:13 Downloading https://releases.bazel.build/2.0.0/rc3/bazel-2.0.0rc3-linux-x86_64...
Starting local Bazel server and connecting to it...
INFO: Invocation ID: 893fd804-3bed-41d5-8b7c-dda793e67520
INFO: Analyzed target //:release (419 packages loaded, 8377 targets configured).
INFO: Found 1 target...
INFO: Deleting stale sandbox base /home/davido/.cache/bazel/_bazel_davido/5c01f4f713b675540b8b424c5c647f63/sandbox
INFO: From Compiling 656 JavaScript files to polygerrit-ui/app/polygerrit_ui_closure_bin.js:
WARNING - Failed to resolve sourcemap at bazel-out/k8-fastbuild/bin/polygerrit-ui/app/custom-style-interface.min.js.map: bazel-out/k8-fastbuild/bin/polygerrit-ui/app/custom-style-interface.min.js.map
Codes: SOURCEMAP_RESOLVE_FAILED
0 error(s), 1 warning(s)
Target //:release up-to-date:
bazel-bin/release.war
INFO: Elapsed time: 154.755s, Critical Path: 99.96s
INFO: 435 processes: 3 remote cache hit, 330 linux-sandbox, 8 local, 94 worker.
INFO: Build completed successfully, 457 total actions
As expected, bazel was downloaded by the bazelisk:
$ ls -all ~/.cache/bazelisk/bin/bazelbuild/bazel-2.0.0rc3-linux-x86_64
-rwxr-xr-x 1 davido users 43780359 Dec 2 21:55 /home/davido/.cache/bazelisk/bin/bazelbuild/bazel-2.0.0rc3-linux-x86_64
Now, if I try to build with bazel directly, bypassing bazelisk, it is failing:
$ bazel build :gerrit
ERROR: The project you're trying to build requires Bazel 2.0.0rc3 (specified in /home/davido/projects/gerrit2/.bazelversion), but it wasn't found in /home/davido/.bazel/bin.
Bazel binaries for all official releaeses can be downloaded from here:
https://github.com/bazelbuild/bazel/releases
You can download the required version directly using this command:
(cd "/home/davido/.bazel/bin" && curl -LO https://releases.bazel.build/2.0.0rc3/release/bazel-2.0.0rc3-linux-x86_64 && chmod +x bazel-2.0.0rc3-linux-x86_64)
Now, I have to fetch bazel twice? It also doesn’t change if I install Bazel locally, I still see the same breakage, even though bazel-2.0.0rc3 was installed:
$ bash bazel-2.0.0rc3-installer-linux-x86_64.sh --user
[...]
Uncompressing.......
Bazel is now installed!
Make sure you have "/home/davido/bin" in your path. You can also activate bash
completion by adding the following line to your :
source /home/davido/.bazel/bin/bazel-complete.bash
See http://bazel.build/docs/getting-started.html to start a new project!
And bazel still doesn’t work:
$ bazel version
Build label: 2.0.0rc3
$ cd gerrit
$ bazel build :gerrit
ERROR: The project you're trying to build requires Bazel 2.0.0rc3 (specified in /home/davido/projects/gerrit2/.bazelversion), but it wasn't found in /home/davido/.bazel/bin.
Bazel binaries for all official releaeses can be downloaded from here:
https://github.com/bazelbuild/bazel/releases
You can download the required version directly using this command:
(cd "/home/davido/.bazel/bin" && curl -LO https://releases.bazel.build/2.0.0rc3/release/bazel-2.0.0rc3-linux-x86_64 && chmod +x bazel-2.0.0rc3-linux-x86_64)
About this issue
- Original URL
- State: closed
- Created 5 years ago
- Comments: 26 (20 by maintainers)
Commits related to this issue
- Let shellzelisk fallback to bazel-real if it's the requested version. This means that if you "apt-get install bazel" and that happens to be version "2.0.0" and in your `.bazelversion` file you have "... — committed to bazelbuild/bazel by philwo 5 years ago
- Do not fail or print errors when Shellzelisk cannot find a requested ? ?Bazel binary, if tools/bazel exists. Instead, we should do our best to populate the $BAZEL_REAL env var with some meaningful p... — committed to bazelbuild/bazel by philwo 4 years ago
- Do not fail or print errors when Shellzelisk cannot find a requested ? ?Bazel binary, if tools/bazel exists. Instead, we should do our best to populate the $BAZEL_REAL env var with some meaningful p... — committed to bazelbuild/bazel by philwo 4 years ago
- Do not fail or print errors when Shellzelisk cannot find a requested ? ?Bazel binary, if tools/bazel exists. Instead, we should do our best to populate the $BAZEL_REAL env var with some meaningful p... — committed to bazelbuild/bazel by philwo 4 years ago
- Do not fail or print errors when Shellzelisk cannot find a requested ? ?Bazel binary, if tools/bazel exists. Instead, we should do our best to populate the $BAZEL_REAL env var with some meaningful p... — committed to bazelbuild/bazel by philwo 4 years ago
- Do not fail or print errors when Shellzelisk cannot find a requested ? ?Bazel binary, if tools/bazel exists. Instead, we should do our best to populate the $BAZEL_REAL env var with some meaningful p... — committed to bazelbuild/bazel by philwo 4 years ago
We would like to kindly request this issue to be reopened as it does appears to have broken both Bazel and
bazeliskat the same time in a significant manner without acceptable workarounds with the 2.0.0 release.The requirements of CI and an organisation of 100+ engineers mean that the way in which we manage versions for
bazelmust be fully automated across all three supported platforms in a seamless way. This includes:bazelneeds to be used for a given invocation depending on configuration. The version might be different depending on the repository that is being built / tested.bazelbinary with the original command and arguments passed to the top-levelbazelinvocation.To achieve this:
tools/bazelscript to pin and auto-manage the versions required to build our various repositories. It provides nearly identical features to whatbazeliskcame to provide at a later point in time.bazeliskas an off-the-shelf solution.While attempting the move to
bazeliskwe are introducing the required.bazelversionfile. While testing this on a Ubuntu workstation that hasbazel2.0.0 installed we found out that the new logic that was added to the wrapper script forbazel’s Debian package makes our attempt at migrating tobazeliskimpossible.The repo under tests currently relies on
bazel1.2.1. When runningbazel versionwith ourtools/bazelscript stripped to simply invokebazelisk, we would expect it to invokebazelisk versionwhich would:bazelisk’s cache.versioncommand passed tobazeliskat the start.However, instead, we found that we never even get into
bazeliskor eventools/bazeland instead are presented with the already reported error message:Although the suggested solution is
this manual actions is clearly not an option given the requirement of automating the entire process, which is the very goal of a tool like
bazelisk, as well as Bazel itself.From reading the code in the wrapper script we have also found that there is no way of deactivating this new logic.
As a result we are now faced with the fact that we cannot at any point in the foreseeable future migrate to
bazelisk, even in the theoretical case if this feature was rolled back in a 3.0.0 release. It would still require a.bazelversionfile and the mere presence of this file will trigger errors on any Debian-based machine that happens to havebazel2.0.0 installed, since this feature does its checks before any other wrapper script or user configuration can intervene.The questions that we have are:
.bazelversionlogic into thebazelwrapper script? It intermingles the functionality ofbazelandbazeliskin an awkward way. The collision on the filename makes it virtually impossible to undo the implications of this change. Releasing a 3.0.0, or 2.0.1 for that matter is not sufficient as people can still have 2.0.0 installed.bazeltrying to implement the features thatbazeliskalready provides in a clean and cross-platform way? Thebazelisktool is already part of thebazelbuildorganisation / ecosystem on GitHub and can thus be clearly advertised for people needing the automated version management. All while leavingbazelitself do what it’s good at: building stuff in a fast and reproducible manner.bazelisk’s key-feature of automated version management not actually being supported all while actually breaking existing users ofbazeliskon that platform?To be clear: if we had already been using
bazeliskbefore the release of 2.0.0 instead of our in-house script then the release of this “feature” would have actively broken all our Linux-based developers overnight.Thanks for the input! I’ll go with @Helcaraxan’s plan and will make sure that the fixed wrapper (skip version check if
tools/bazelexists) gets into Bazel 2.1.Thanks everyone for commenting and/or upvoting @Helcaraxan’s post so that I can get a good feeling for the impact and urgency here and communicate this to my colleagues. This really helps prioritize this, so that we can hopefully find a good solution for all users quickly. 😃
Before Bazel 2.0, users could install Bazel using a variety of ways:
bazel-2.0.0-linux-x86_64) and check them into their source code repository or put them on their $PATH.bazel-2.0.0-installer-linux-x86_64.sh) and install Bazel using that. This will actually install a shell-script as thebazelcommand, which tries to execute$REPO/tools/bazelif it exists, otherwise will execute Bazel.bazelcommand on the PATH), which will automatically download the latest Bazel version (or the one specified in$REPO/.bazelversion), then check if a$REPO/tools/bazelscript exists and if yes, run that, otherwise run the downloaded Bazel binary.When the wrapper or Bazelisk run
$REPO/tools/bazelthey pass the location of the actual Bazel binary via the $BAZEL_REAL environment variable. Thetools/bazelscript is then expected to do whatever pre/post steps it wants to do (e.g. strip environment variables, run Bazel in a sandbox, upload logs after each invocation, …) and execute$BAZEL_REAL "$@"at the appropriate point in time.All users from above list except the Bazelisk users would now regularly run into this problem: They somehow end up with a version of Bazel that doesn’t match the project that they want to build (e.g. downloaded the wrong version or their package manager automatically updated Bazel over night and whamm the entire team’s build is broken).
How do we fix that? Two ideas:
tools/bazel..bazelversionand tells the user to install the correct version of Bazel using their native packaging solution (e.g. it will tell Debian users toapt-get install bazel-1.1.0, installer-script users towget -O ... https://..., …).Although I would have loved option 1, it didn’t sound too convincing in practice:
tools/bazeldoesn’t actually guarantee that it gets called - if your user is on Windows or installs Bazel by downloading Bazel binaries directly, theirbazelinvocation will not runtools/bazel.So I went for option 2. The users who cannot use Bazelisk are happy that their Bazel versioning problem is now finally solved, yay. 🎉 The users who actually were using option 1 are now broken. Not-so-yay. 😞
Let’s figure out how to support this without breaking anyone. Here’s all combinations of users and repository setups. In the third column “Wrapper” refers to a script that simply changes the environment a bit and then delegates to
$BAZEL_REAL, while “Bazelisk” refers to either Bazelisk or any other script that tries to find the correct Bazel version and then executes that (ignores$BAZEL_REAL).bazelisIt looks like we have to fix the case where:
apt-getor similar that causes theirbazelcommand to be Bazel’s shell script wrapper..bazelversionfile.tools/bazelscript that is either Bazelisk or something similar.Do you have suggestions how to fix this? Some ideas:
tools/bazelis Bazelisk or a variant and then skip its own.bazelversioncheck. However I can’t immediately see a reliable way how to detect this..bazelversioniftools/bazelexists. This might not be too bad - it would basically restore pre-2.0 behavior for this specific case only. I have to think about this a bit. 🤔.bazelversionfeature again from the shell-script wrapper and instead change Bazelisk so that it can be used by all users, even those in offline-only or security restricted scenarios. For example we could add a feature to Bazelisk so that it fetches its binaries and version-information from an internal location.The reason was that users who could not use Bazelisk (or download binaries from the internet) still wanted a way to version Bazel with their source code (= the
.bazelversionidea). The current solution makes it easy for users who install Bazel viaapt-getto work with repositories that use.bazelversionfiles (but breaks the case where project owners assume that when a user runsbazelit will actually just run their$REPO/tools/bazelscript).I don’t see this quite as dark - if people installed Bazel 2.0.0 in a way that gave them the shell-script wrapper that you relied on, then it usually means that they used a package manager, which will automatically update their Bazel to later versions. Also, any Bazel version could potentially be so broken that it doesn’t work with your project - it’s not great, but we have to fix it and then go on.
See above - I would love if everyone could just Bazelisk. Maybe I should have pushed more for this. If you and others think that adding offline support etc. to Bazelisk is the right direction, we can try to do that instead.
I don’t think this is the case - all platforms that ship the shell-script wrapper (which are all platforms for which a
tools/bazelapproach would have worked) now support the.bazelversionfile, too. Bazelisk supports more platforms, which is why I recommend users to directly install Bazelisk as theirbazel.If the question is about “why didn’t you just add this directly to Bazel” - because I didn’t want to add something that “phones home” to the internet to Bazel. User trust is super important for me and others on the Bazel team and we think your build tool shouldn’t rely on the internet in order to work.
Hope this already answers some questions - I’ll follow-up tomorrow in case I have any other ideas / thoughts about this and of course for any comments and questions that come up 😃
Just wanted to follow up @philwo about the resulting fix that now is making its way into 2.1.0. The reactiveness and communication has been greatly appreciated.
A great thanks on behalf of the entire team. ❤️
Is this a release blocker for 2.0?
Great resolution @philwo! Do we want to have a 2.0 patch release for this?
@philwo Thanks for adding the option to skip the check in the script wrapper.
Now, to test a minor Bazel upgrade, say 2.1.0rc4 from [1] in Gerrit workspace, where
.bazelversioncontains 2.0.0, I could add thistool/bazelto skip the check:Now, after installing
bash bazel-2.1.0rc4-installer-linux-x86_64.sh --userlocally, I can actually test it, and the check is skipped:Of course, I could temporary update the
.bazelversionin the tree, temporary remove it, or just passUSE_BAZEL_VERSION=2.1.0rc4 bazel version…[1] https://releases.bazel.build/2.1.0/rc4/index.html
Hi @Helcaraxan and others,
sorry for the trouble you and others are having with the new feature. I’ll respond tomorrow to all of your questions. I designed the new feature to not break any existing users, but obviously this didn’t work out. I reopened this issue - let’s see that we can fix it together to also work for you and others who check in Bazelisk as
tools/bazelinto their repo.Also, I don’t understand this reasoning:
No, of course not - the workaround is not to remove the .bazelversion file, the “workaround” is to simply do what the (IMHO pretty helpful) error message suggests - install the required Bazel version 😃 I don’t see how this is “broken” or how “Bazel stopped working”.
Edit: @davido Sorry, to be clear, I totally understand why having to download the same Bazel version twice (once as the “latest” Bazel and once as the “specifically versioned package” Bazel) is weird and not a good UX. I’ll fix this before we release Bazel 2.0. The general behavior should be fine and an improvement, though, or what do you think?
So, here are some thoughts on this:
If a project has a .bazelversion file, it means it “should” be built with that exact Bazel version. Because the .bazelversion file is used to basically “version your build tool with your source code”, I do not want to implement fuzzy matching like “as long as it’s the same major version, it’s fine”. It will use and require the exact version, so this is working as intended.
Let’s assume you have a project with a .bazelversion file that specifies “1.1.0” as the required Bazel version, then here’s what happens:
bazel-1.1.0package installed, it will suggest to run the command to install that package.I think this behavior makes sense and is pretty user friendly?
However, I agree that there’s one optimization we should add: If the .bazelversion asks for Bazel X.Y and the Bazel version that was installed via
apt-get install bazelor the installer script is already Bazel X.Y, then we do not need to download the same version once again. (Basically what Yun suggested.)I’ll think of some logic for the wrapper script that supports this, then we can do a cherry-pick and it should be fine.