From f0033f07c6b9884b03b27f0ecf1f76aeddc4373d Mon Sep 17 00:00:00 2001 From: Robert-Jan Huijsman <22160949+rjhuijsman@users.noreply.github.com> Date: Tue, 24 Mar 2026 09:39:25 +0000 Subject: [PATCH 1/3] Upgrade to Bazel 7.7.0, rules_python 1.0.0, and protobuf 29.5 Bazel 7 introduces several breaking changes that required updates: - `.bazeliskrc`: Bump version from 5.4.1 to 7.7.0. - `.bazelrc`: Add `common --enable_bzlmod=false`. Bazel 7 enables bzlmod by default; disabling it keeps the WORKSPACE-based build working until we are ready to migrate to MODULE.bazel. - `WORKSPACE.bazel`: Remove the `external = False` argument from `repos()`. This parameter no longer exists (see repos.bzl below). - `bazel/repos.bzl`: Bazel 7 removes the `repo_mapping` parameter from repository rules (`http_archive`, `git_repository`, etc.), so all explicit `repo_mapping = {}` arguments are removed. `native.existing_rules()` is deprecated in Bazel 7; the conditional self-registration pattern (`if external:`) is replaced throughout with `maybe()` from `@bazel_tools`. `rules_python` is upgraded from 0.27.0 to 1.0.0 (required by protobuf 29.x). The `com_google_protobuf` `git_repository` is replaced with an `http_archive` for protobuf 29.5 (better reproducibility and avoids git fetch overhead). - `bazel/deps.bzl`, `bazel/py_toolchains.bzl`: Remove `repo_mapping` parameter (no longer accepted by the called functions). - `bazel/pypi_repos.bzl`: rules_python 1.0.0 removed the `@python3_10_12//:defs.bzl` `interpreter` symbol. Replace with the `"@python3_10_12_host//:python"` label string. - `rules.bzl`: Update `ProtoInfo` import from `@rules_proto//proto:defs.bzl` to `@com_google_protobuf//bazel/common:proto_info.bzl` (moved in protobuf 29.x). Also fix a latent output-directory bug: in Bazel 7, `output_files[0].path` for directory-typed outputs already includes the workspace root for external repos; the old code appended it a second time, doubling the path and breaking protoc invocations when this rule is used from an external consumer. - `tests/python/BUILD.bazel`: protobuf 29.x moved `py_proto_library` to `@com_google_protobuf//bazel:py_proto_library.bzl` and changed the attribute from `srcs` to `deps`. - `tests/cpp/BUILD.bazel`: protobuf 29.x moved `cc_proto_library` to `@com_google_protobuf//bazel:cc_proto_library.bzl`. - `requirements.in`, `requirements_lock.txt`: Bump the minimum protobuf Python runtime from `>=3` to `>=5.29.5` to match the gencode version produced by protobuf 29.5, and regenerate the lock file accordingly. Co-Authored-By: Claude Sonnet 4.6 --- .bazeliskrc | 2 +- .bazelrc | 2 ++ WORKSPACE.bazel | 2 +- bazel/deps.bzl | 4 ++-- bazel/py_toolchains.bzl | 3 +-- bazel/pypi_repos.bzl | 3 +-- bazel/repos.bzl | 48 ++++++++++++---------------------------- requirements.in | 2 +- requirements_lock.txt | 21 ++++++++---------- rules.bzl | 20 +++++++++-------- tests/cpp/BUILD.bazel | 3 ++- tests/python/BUILD.bazel | 7 +++--- 12 files changed, 48 insertions(+), 69 deletions(-) diff --git a/.bazeliskrc b/.bazeliskrc index bd4a535..e920830 100644 --- a/.bazeliskrc +++ b/.bazeliskrc @@ -1 +1 @@ -USE_BAZEL_VERSION=5.4.1 +USE_BAZEL_VERSION=7.7.0 diff --git a/.bazelrc b/.bazelrc index 7a9655a..da6bbf6 100644 --- a/.bazelrc +++ b/.bazelrc @@ -1,3 +1,5 @@ +common --enable_bzlmod=false + # Use a remote build cache that's world-readable. Don't write unless told otherwise. build --remote_cache=https://storage.googleapis.com/reboot-dev-bazel-remote-cache-reboot-us diff --git a/WORKSPACE.bazel b/WORKSPACE.bazel index d73f3a8..3790e29 100644 --- a/WORKSPACE.bazel +++ b/WORKSPACE.bazel @@ -2,7 +2,7 @@ workspace(name = "com_github_reboot_dev_pyprotoc_plugin") load("//bazel:repos.bzl", "repos") -repos(external = False) +repos() load("//bazel:py_toolchains.bzl", "py_toolchains") diff --git a/bazel/deps.bzl b/bazel/deps.bzl index 510ca54..0cbe689 100644 --- a/bazel/deps.bzl +++ b/bazel/deps.bzl @@ -3,7 +3,7 @@ load("@com_google_protobuf//:protobuf_deps.bzl", "protobuf_deps") load("@pyprotoc_plugin_pypi//:requirements.bzl", pypi_deps = "install_deps") -def deps(repo_mapping = {}): +def deps(): protobuf_deps() - pypi_deps(repo_mapping = repo_mapping) + pypi_deps() diff --git a/bazel/py_toolchains.bzl b/bazel/py_toolchains.bzl index e300d5f..a80795b 100644 --- a/bazel/py_toolchains.bzl +++ b/bazel/py_toolchains.bzl @@ -2,11 +2,10 @@ load("@rules_python//python:repositories.bzl", "py_repositories", "python_register_toolchains") -def py_toolchains(repo_mapping = {}): +def py_toolchains(): py_repositories() python_register_toolchains( name = "python3_10_12", python_version = "3.10.12", - repo_mapping = repo_mapping, ) diff --git a/bazel/pypi_repos.bzl b/bazel/pypi_repos.bzl index 0647888..ebf8407 100644 --- a/bazel/pypi_repos.bzl +++ b/bazel/pypi_repos.bzl @@ -3,12 +3,11 @@ should be installed later in WORKSPACE file to be accessible. `pip_parse` takes a `requirements_lock` file as input, which is generated by the `bazel run :requirements.update` command.""" -load("@python3_10_12//:defs.bzl", "interpreter") load("@rules_python//python:pip.bzl", "pip_parse") def pypi_repos(): pip_parse( name = "pyprotoc_plugin_pypi", - python_interpreter_target = interpreter, + python_interpreter_target = "@python3_10_12_host//:python", requirements_lock = "@com_github_reboot_dev_pyprotoc_plugin//:requirements_lock.txt", ) diff --git a/bazel/repos.bzl b/bazel/repos.bzl index fe099cf..e7a7891 100644 --- a/bazel/repos.bzl +++ b/bazel/repos.bzl @@ -9,45 +9,25 @@ # instructions at https://github.com/reboot-dev/pyprotoc-plugin. ######################################################################## -load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository") load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") load("@bazel_tools//tools/build_defs/repo:utils.bzl", "maybe") -def repos(external = True, repo_mapping = {}): - """Adds repositories/archives needed by pyprotoc-plugin - - Args: - external: whether or not we're invoking this function as though - though we're an external dependency - repo_mapping: passed through to all other functions that expect/use - repo_mapping, e.g., 'git_repository' - """ +def repos(): + """Adds repositories/archives needed by pyprotoc-plugin.""" maybe( http_archive, name = "rules_python", - sha256 = "9acc0944c94adb23fba1c9988b48768b1bacc6583b52a2586895c5b7491e2e31", - strip_prefix = "rules_python-0.27.0", - url = "https://github.com/bazelbuild/rules_python/releases/download/0.27.0/rules_python-0.27.0.tar.gz", - repo_mapping = repo_mapping, + sha256 = "4f7e2aa1eb9aa722d96498f5ef514f426c1f55161c3c9ae628c857a7128ceb07", + strip_prefix = "rules_python-1.0.0", + url = "https://github.com/bazelbuild/rules_python/releases/download/1.0.0/rules_python-1.0.0.tar.gz", ) - if "com_google_protobuf" not in native.existing_rules(): - git_repository( - name = "com_google_protobuf", - remote = "https://github.com/protocolbuffers/protobuf", - # Release v3.19.4. - # TODO(codingcanuck): Update to a newer release after - # https://github.com/protocolbuffers/protobuf/issues/9688 is fixed. - commit = "22d0e265de7d2b3d2e9a00d071313502e7d4cccf", - shallow_since = "1643340956 -0800", - repo_mapping = repo_mapping, - ) - - if external and "com_github_reboot_dev_pyprotoc_plugin" not in native.existing_rules(): - git_repository( - name = "com_github_reboot_dev_pyprotoc_plugin", - remote = "https://github.com/reboot-dev/pyprotoc-plugin", - commit = "9f7a281670f03b77140c4437ac2a56b86f978af6", - shallow_since = "1649038239 +0000", - repo_mapping = repo_mapping, - ) + maybe( + http_archive, + name = "com_google_protobuf", + sha256 = "955ef3235be41120db4d367be81efe6891c9544b3a71194d80c3055865b26e09", + strip_prefix = "protobuf-29.5", + urls = [ + "https://github.com/protocolbuffers/protobuf/archive/v29.5.tar.gz", + ], + ) diff --git a/requirements.in b/requirements.in index 9fb21af..0b70da8 100644 --- a/requirements.in +++ b/requirements.in @@ -1,2 +1,2 @@ Jinja2>=3 -protobuf>=3 +protobuf>=5.29.5 diff --git a/requirements_lock.txt b/requirements_lock.txt index 63b8c40..5d404c4 100644 --- a/requirements_lock.txt +++ b/requirements_lock.txt @@ -70,16 +70,13 @@ markupsafe==2.1.3 \ --hash=sha256:fec21693218efe39aa7f8599346e90c705afa52c5b31ae019b2e57e8f6542bb2 \ --hash=sha256:ffcc3f7c66b5f5b7931a5aa68fc9cecc51e685ef90282f4a82f0f5e9b704ad11 # via jinja2 -protobuf==4.25.1 \ - --hash=sha256:0bf384e75b92c42830c0a679b0cd4d6e2b36ae0cf3dbb1e1dfdda48a244f4bcd \ - --hash=sha256:0f881b589ff449bf0b931a711926e9ddaad3b35089cc039ce1af50b21a4ae8cb \ - --hash=sha256:1484f9e692091450e7edf418c939e15bfc8fc68856e36ce399aed6889dae8bb0 \ - --hash=sha256:193f50a6ab78a970c9b4f148e7c750cfde64f59815e86f686c22e26b4fe01ce7 \ - --hash=sha256:3497c1af9f2526962f09329fd61a36566305e6c72da2590ae0d7d1322818843b \ - --hash=sha256:57d65074b4f5baa4ab5da1605c02be90ac20c8b40fb137d6a8df9f416b0d0ce2 \ - --hash=sha256:8bdbeaddaac52d15c6dce38c71b03038ef7772b977847eb6d374fc86636fa510 \ - --hash=sha256:a19731d5e83ae4737bb2a089605e636077ac001d18781b3cf489b9546c7c80d6 \ - --hash=sha256:abc0525ae2689a8000837729eef7883b9391cd6aa7950249dcf5a4ede230d5dd \ - --hash=sha256:becc576b7e6b553d22cbdf418686ee4daa443d7217999125c045ad56322dda10 \ - --hash=sha256:ca37bf6a6d0046272c152eea90d2e4ef34593aaa32e8873fc14c16440f22d4b7 +protobuf==7.34.1 \ + --hash=sha256:34b84ce27680df7cca9f231043ada0daa55d0c44a2ddfaa58ec1d0d89d8bf60a \ + --hash=sha256:403b093a6e28a960372b44e5eb081775c9b056e816a8029c61231743d63f881a \ + --hash=sha256:5185e0e948d07abe94bb76ec9b8416b604cfe5da6f871d67aad30cbf24c3110b \ + --hash=sha256:8ff40ce8cd688f7265326b38d5a1bed9bfdf5e6723d49961432f83e21d5713e4 \ + --hash=sha256:9ce42245e704cc5027be797c1db1eb93184d44d1cdd71811fb2d9b25ad541280 \ + --hash=sha256:bb3812cd53aefea2b028ef42bd780f5b96407247f20c6ef7c679807e9d188f11 \ + --hash=sha256:d8b2cc79c4d8f62b293ad9b11ec3aebce9af481fa73e64556969f7345ebf9fc7 \ + --hash=sha256:e97b55646e6ce5cbb0954a8c28cd39a5869b59090dfaa7df4598a7fba869468c # via -r requirements.in diff --git a/rules.bzl b/rules.bzl index d8cc2da..dcc1f8f 100644 --- a/rules.bzl +++ b/rules.bzl @@ -1,6 +1,6 @@ """Defines rules to create pyprotoc-based bazel rules.""" -load("@rules_proto//proto:defs.bzl", "ProtoInfo") +load("@com_google_protobuf//bazel/common:proto_info.bzl", "ProtoInfo") def _get_proto_sources(context): proto_files = [ @@ -48,15 +48,17 @@ def _protoc_plugin_rule_implementation(context): proto_files = _get_proto_sources(context) output_files = _declare_outputs(context) - output_directory = context.genfiles_dir.path - if not context.attr._extensions: - # Declare a directory on one level upper to generated ones, to be sure - # it works with a couple proto files. - output_directory = "/".join(output_files[0].path.split("/")[:-1]) - - if len(context.label.workspace_root) != 0: - output_directory += "/" + context.label.workspace_root + # Declare a directory one level up from generated ones, to + # be sure it works with a couple proto files. The output + # file path already includes the workspace root for + # external repos, so no need to append it again. + output_directory = "/".join( + output_files[0].path.split("/")[:-1]) + else: + output_directory = context.genfiles_dir.path + if len(context.label.workspace_root) != 0: + output_directory += "/" + context.label.workspace_root plugin_path = context.executable._plugin.path plugin_name = plugin_path.split("/")[-1] diff --git a/tests/cpp/BUILD.bazel b/tests/cpp/BUILD.bazel index 8a20e3f..139ce72 100644 --- a/tests/cpp/BUILD.bazel +++ b/tests/cpp/BUILD.bazel @@ -1,4 +1,5 @@ -load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library", "cc_proto_library") +load("@com_google_protobuf//bazel:cc_proto_library.bzl", "cc_proto_library") +load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library") load("@rules_proto//proto:defs.bzl", "proto_library") load("@rules_python//python:defs.bzl", "py_binary") load(":cpp_rule.bzl", "cc_generate_library") diff --git a/tests/python/BUILD.bazel b/tests/python/BUILD.bazel index f6d17fd..7e9a170 100644 --- a/tests/python/BUILD.bazel +++ b/tests/python/BUILD.bazel @@ -1,4 +1,4 @@ -load("@com_google_protobuf//:protobuf.bzl", "py_proto_library") +load("@com_google_protobuf//bazel:py_proto_library.bzl", "py_proto_library") load("@rules_proto//proto:defs.bzl", "proto_library") load("@rules_python//python:defs.bzl", "py_binary", "py_library", "py_test") load(":sample_rule.bzl", "py_sample_library") @@ -30,7 +30,7 @@ proto_library( py_proto_library( name = "sample_messages_py_proto", - srcs = ["sample_messages.proto"], + deps = [":sample_messages_proto"], ) proto_library( @@ -41,8 +41,7 @@ proto_library( py_proto_library( name = "sample_service_py_proto", - srcs = ["sample_service.proto"], - deps = [":sample_messages_py_proto"], + deps = [":sample_service_proto"], ) py_sample_library( From 4d5f220a3d8e84d2efd0b8901bb940b47fad22fc Mon Sep 17 00:00:00 2001 From: Robert-Jan Huijsman <22160949+rjhuijsman@users.noreply.github.com> Date: Tue, 24 Mar 2026 09:49:18 +0000 Subject: [PATCH 2/3] buildifier: reformat rules.bzl Trailing comma in multi-line function call required by buildifier. Co-Authored-By: Claude Sonnet 4.6 --- rules.bzl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/rules.bzl b/rules.bzl index dcc1f8f..7a4bad4 100644 --- a/rules.bzl +++ b/rules.bzl @@ -54,7 +54,8 @@ def _protoc_plugin_rule_implementation(context): # file path already includes the workspace root for # external repos, so no need to append it again. output_directory = "/".join( - output_files[0].path.split("/")[:-1]) + output_files[0].path.split("/")[:-1], + ) else: output_directory = context.genfiles_dir.path if len(context.label.workspace_root) != 0: From 0fd18f0996313bcf333252a05d92f50623ccba90 Mon Sep 17 00:00:00 2001 From: Robert-Jan Huijsman <22160949+rjhuijsman@users.noreply.github.com> Date: Tue, 24 Mar 2026 12:40:52 +0000 Subject: [PATCH 3/3] pip_parse: increase timeout for slow CI runners On resource-constrained CI runners (e.g., macOS arm64), the default 600s timeout for whl_library extraction may be insufficient when running concurrently with intensive C++ compilation. Increase to 1800s to avoid spurious timeouts. Co-Authored-By: Claude Sonnet 4.6 --- bazel/pypi_repos.bzl | 1 + 1 file changed, 1 insertion(+) diff --git a/bazel/pypi_repos.bzl b/bazel/pypi_repos.bzl index ebf8407..b23a6b2 100644 --- a/bazel/pypi_repos.bzl +++ b/bazel/pypi_repos.bzl @@ -10,4 +10,5 @@ def pypi_repos(): name = "pyprotoc_plugin_pypi", python_interpreter_target = "@python3_10_12_host//:python", requirements_lock = "@com_github_reboot_dev_pyprotoc_plugin//:requirements_lock.txt", + timeout = 1800, )