Upgrade to Bazel 8.7.0 - #144
Conversation
Current Aviator status
This PR was merged using Aviator (commit 0e5410e).
See the real-time status of this PR on the
Aviator webapp.
Use the Aviator Chrome Extension
to see the status of your PR within GitHub.
|
52f0d50 to
1bf69ca
Compare
1bf69ca to
9ef4c2b
Compare
There was a problem hiding this comment.
Pull request overview
Upgrades the build system to Bazel 8.7.0 while retaining WORKSPACE mode and addressing dependency and compatibility requirements.
Changes:
- Updates Bazel, rules_python, Protobuf, and bazel_features.
- Adds gRPC patches for generated protos and macOS linking.
- Adjusts Python toolchains, runfiles handling, and build configuration.
Reviewed changes
Copilot reviewed 15 out of 26 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
.bazeliskrc |
Selects Bazel 8.7.0. |
.bazelrc |
Preserves WORKSPACE mode and disables Python precompilation. |
bazel/repos.bzl |
Updates dependencies and applies gRPC patches. |
bazel/pypi_repos.bzl |
Uses the host Python interpreter target. |
bazel/grpc_03_generated_protos_staging.patch |
Handles generated proto staging. |
bazel/grpc_04_macos_dynamic_lookup.patch |
Fixes macOS Cython extension linking. |
reboot/requirements.in |
Pins Protobuf 5.29.3. |
reboot/requirements_lock.txt |
Regenerates the Protobuf lock entry. |
tests/requirements.in |
Aligns the test Protobuf pin. |
tests/requirements_lock.txt |
Regenerates the test lock entry. |
reboot/routing/filters/BUILD.bazel |
Removes the relocated SHA-1 filegroup. |
reboot/cli/commands/init/test.sh |
Resolves expected output beside the test executable. |
reboot/cli/commands/init/nodejs_test.sh |
Updates Node.js test data lookup. |
reboot/examples/reboot-swag-store/uv.lock |
Updates locked Protobuf artifacts. |
reboot/examples/monorepo/uv.lock |
Updates locked Protobuf artifacts. |
reboot/examples/kcdc-2025/uv.lock |
Updates locked Protobuf artifacts. |
reboot/examples/chick-potle/uv.lock |
Updates locked Protobuf artifacts. |
reboot/examples/chat-room/uv.lock |
Updates locked Protobuf artifacts. |
reboot/examples/boutique/uv.lock |
Updates locked Protobuf artifacts. |
reboot/examples/bank/uv.lock |
Updates locked Protobuf artifacts. |
reboot/examples/bank-pydantic/uv.lock |
Updates locked Protobuf artifacts. |
reboot/examples/ai-chat-counter/uv.lock |
Updates locked Protobuf artifacts. |
reboot/examples/ai-chat-counter-dashboard/uv.lock |
Updates locked Protobuf artifacts. |
reboot/examples/agent-wiki/uv.lock |
Updates locked Protobuf artifacts. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
9ef4c2b to
d60cef5
Compare
Code reviewNo issues found. Checked for bugs and CLAUDE.md compliance. |
d60cef5 to
df1ab8d
Compare
Code reviewNo issues found. Checked for bugs and CLAUDE.md compliance. |
df1ab8d to
3b4ac5e
Compare
Code reviewNo issues found. Checked for bugs and CLAUDE.md compliance. |
95cfdc5 to
3b4ac5e
Compare
Code reviewNo issues found. Checked for bugs and CLAUDE.md compliance. |
3b4ac5e to
e1395f3
Compare
Prepares this repository for Bazel 8, in which `--incompatible_disallow_empty_glob` defaults to true. Before this change the `filegroup` globbed `sha1/src/**/*` from a package with no `sha1` directory - the `sha1` submodule lives at `reboot/server/sha1`, and `reboot/server/BUILD.bazel` already has the `sha1_lua` target that actually matches it and is actually depended on. On Bazel 8 the empty glob turns into `package contains errors: reboot/routing/filters`. Nothing referenced `//reboot/routing/filters:sha1_lua`, so it is deleted rather than repointed. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QwqjZJ1LqSJp3cM9aJYFWi
Prepares this repository for Bazel 8, whose built-in WORKSPACE suffix runs `rules_java` 8.12.0's `rules_java_dependencies()`. Loading that `rules_java` needs `bazel_features` to expose `rules._has_launcher_maker_toolchain`, which arrived in 1.30.0. Before this change nothing declared `bazel_features` before `grpc_deps()` did, at 1.14.0, and Bazel 8 failed the invocation with `'struct' value has no field or method '_has_launcher_maker_toolchain'` before it could load a single package. Declaring it in `repos()`, which runs before `deps()`, makes `grpc_deps()`'s own declaration a no-op. Upgrading gRPC instead would be a much larger change: its Python wheels have to stay aligned with the `grpcio` version we pin in `reboot/requirements.in`. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QwqjZJ1LqSJp3cM9aJYFWi
Prepares this repository for Bazel 8, which removed the native `PyInfo` and `PyRuntimeInfo` globals and instead autoloads them from `@rules_python`. Before this change, `rules_python` 0.27.0 still re-exported those globals, so every Bazel 8 invocation died while computing the main repo mapping with `name 'PyInfo' is not defined`. 1.0.0 rather than a 0.4x release: 0.40.0's `py_repositories()` declares `rules_cc` 0.0.13 and `protobuf` 27.0 with plain `http_archive` calls, which override whatever we declared earlier - `maybe()` cannot defend against that. `rules_cc` 0.0.13's `cc/defs.bzl` then takes `cc_proto_library` from that `@protobuf` 27.0, where it is only a stub reading `native.cc_proto_library`, a symbol Bazel 8 no longer has, so loading any package that uses `@rules_cc//cc:defs.bzl` failed. 1.0.0 switched both declarations to `maybe()` and to versions that work on Bazel 8. Two follow-on changes come with the upgrade: - 1.0.0 dropped the `interpreter` symbol from the toolchain repo's `defs.bzl`, so `pip_parse` now names the `_host` repository's interpreter directly. - 1.0.0 can precompile `.py` sources to `.pyc` at build time. Several of our `.py` files appear in the `srcs` of more than one target, which is fine on its own but gives each of those targets its own action writing the same `__pycache__/<name>.cpython-310.pyc`, and Bazel rejects that as conflicting actions. Precompiling only moves work the interpreter already does on first import, so `.bazelrc` turns it off rather than us restructuring the targets. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QwqjZJ1LqSJp3cM9aJYFWi
Prepares this repository for Bazel 8, which no longer has a native `proto_library`; it autoloads the rule from Protobuf's own Starlark implementation in `bazel/proto_library.bzl` instead. Protobuf 27.1 only has a stub there that reads `native.proto_library`, so on Bazel 8 loading any package with a `proto_library` failed with `no native function or rule 'proto_library'`. 29.x is the first release with a real implementation. 29.3 specifically: it is what `stout` already pins, it is what `rules_java` 8.12.0 expects, and gRPC 1.71.0 - the version we pin - builds against Protobuf 29. Generated Python code refuses to load against an older runtime, so the `protobuf` pin moves from 5.28.3 to 5.29.3 in lockstep; without it every `protoc` invocation that runs our own Python plugins died with `Detected incompatible Protobuf Gencode/Runtime versions ... gencode 5.29.3 runtime 5.28.3`. `grpcio-tools` 1.64.3 accepts any `protobuf` below 6.0, so the `grpcio` pin is unaffected. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QwqjZJ1LqSJp3cM9aJYFWi
Prepares this repository for Bazel 8. Bazel's native `proto_library` used to place generated `.proto` sources under `_virtual_imports` (see Bazel's `--incompatible_generated_protos_in_virtual_imports`). Protobuf's Starlark reimplementation, which Bazel 8 autoloads in place of the native rule, only creates virtual imports when `import_prefix` or `strip_import_prefix` is set, so a generated `.proto` now reaches gRPC's `get_staged_proto_file()` as a plain file under `bazel-out/.../bin`. Before this change that made gRPC take its "different package" branch and strip a source-tree prefix off an output-tree path. Whether the result was merely wrong or fatal depended on how long the package path happened to be; for `tests/reboot/pydantic_web/nested_types` it produced `/pydantic_web/nested_types/servicer_api.proto` and failed analysis outright. `declare_out_files()`, immediately below the patched function, already knows how to handle a generated proto that sits in its own package directory, so the patch teaches `get_staged_proto_file()` the same check and leaves such a file alone. Two alternatives were rejected: giving our generated `proto_library` targets a `strip_import_prefix` to force virtual imports would change the import path every consumer of those protos sees, and upgrading gRPC would drag the `grpcio` Python pin along with it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QwqjZJ1LqSJp3cM9aJYFWi
Picks up the Bazel 8 preparation in both submodules. They are `local_repository` dependencies, so their `repos()` functions are what declare `rules_java` and `bazel_skylib` at versions Bazel 8 can use, and their `pip_parse` calls need the same `interpreter` fix as ours. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QwqjZJ1LqSJp3cM9aJYFWi
Before this change we built with Bazel 6.5.0, which reached end of support long ago; staying on it means no upstream fixes and a growing gap to whatever we eventually migrate to. 8.7.0 is the newest stable Bazel that can still build a `WORKSPACE` repository. Bazel 9 removed all `WORKSPACE` logic, so going further would force a Bzlmod migration, which we deliberately keep as a separate step. Bazel 8 disables `WORKSPACE` by default, so `.bazelrc` now asks for it explicitly. Our existing `--enable_bzlmod=false` is not enough on its own: Bazel then refuses to fetch anything at all, with `Both --enable_bzlmod and --enable_workspace are disabled, but one of them must be enabled to fetch external dependencies.` The preceding commits make the dependency versions and BUILD files Bazel 8 needs. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QwqjZJ1LqSJp3cM9aJYFWi
The flag defaults to true from Bazel 7 on, which the comment on it already anticipated, so on Bazel 8.7.0 it only restates a default. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QwqjZJ1LqSJp3cM9aJYFWi
Bazel 8's test setup no longer defines an implicit `rlocation` shell function; a test that calls one now aborts with `rlocation is no longer implicitly provided by Bazel's test setup`. Before this change that took out `//tests/reboot/cli/init:init_sh_test_python311` and `//tests/reboot/cli/init:init_nodejs_sh_test` after their assertions had already passed. Both call sites passed an absolute path - `$(dirname "$0")/...` - and Bazel's `rlocation` echoed absolute paths back unchanged, so the call was already doing nothing. Dropping it keeps the behaviour identical. Sourcing `rules_shell`'s `runfiles.bash` instead would mean naming the files by repository-qualified runfiles path, which is a bigger change for no gain here. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QwqjZJ1LqSJp3cM9aJYFWi
`cython_library()` builds each Cython extension as a `cc_binary` with `linkshared = 1` that deliberately leaves every `Py*` symbol undefined, for the interpreter that loads it to resolve. On MacOS that only links with `-undefined dynamic_lookup`. Bazel 6's MacOS crosstool added that flag to every dynamic-library link action from its `default_link_flags` feature; Bazel 8's does not. Before this change, `Build public repo for MacOS arm64` failed linking `cygrpc.so` with several hundred `Undefined symbols for architecture arm64` errors. Passing the flag through `--linkopt` in `.bazelrc` would apply it to every MacOS link, including executables, where it would turn a genuine missing-symbol error into a crash at run time. Setting it on the one target that wants it keeps that error checking everywhere else. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QwqjZJ1LqSJp3cM9aJYFWi
Our example projects lock their transitive dependencies against the *released* `reboot` wheel, but their Docker-based tests run against the *dev* wheel, which is pre-installed in the locally built `reboot-base` image. Both agreed on `protobuf` 5.28.3 until the Protobuf upgrade earlier in this branch moved the dev wheel to 5.29.3. Before this change, the `pip install` of the `uv export`ed lockfile inside each example's Docker build then had to satisfy both `protobuf==5.28.3` (from the lockfile) and `protobuf==5.29.3` (from the already-installed dev `reboot`), and failed with `ResolutionImpossible`. That took out `serve_test` on the Linux arm64 runner, which unlike x86_64 does not filter out `requires-docker` tests. `uv lock` cannot produce these lockfiles on its own yet: the released `reboot` 1.4.1 on PyPI still declares `protobuf==5.28.3`, so a plain re-resolve returns 5.28.3. Each lockfile was therefore re-resolved with a temporary `[tool.uv] override-dependencies` entry forcing 5.29.3, and only the `protobuf` entry changed. The next release runs `make lockfiles`, which re-resolves them against the newly published `reboot` and reaches the same place on its own. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QwqjZJ1LqSJp3cM9aJYFWi
e1395f3 to
c8ad23c
Compare
Bazel 6.5.0 has been out of support for a long time, so we get no upstream fixes and the gap to whatever we eventually migrate to keeps growing. This PR moves the repo to Bazel 8.7.0, the newest stable Bazel that can still build a
WORKSPACErepository — Bazel 9 removed allWORKSPACElogic, so anything newer would force a Bzlmod migration, which we deliberately keep as a separate step.Each commit is one logical change with its own rationale to support Bazel 8; the last two are the Bazel 8 version flip itself and the removal of a flag that the flip makes redundant. Companion PRs:
3rdparty/stout#90andreboot-dev/pyprotoc-plugin#48, whose commits this PR's submodule bump picks up.