Skip to content

Commit 5b5ece5

Browse files
authored
fix: upgrade Protobuf and gRPC in WORKSPACE (#17882)
- Upgrade Dependencies: Upgrade Protobuf to v35.1, rules_python to v1.1.0, and gRPC to v1.83.0 - Hermetic Python & CI: Register hermetic Python toolchains (3.10–3.13) in WORKSPACE with `ignore_root_user_error = True` for Github Actions compatibility. - ProtoInfo Compatibility: Add `gapic_compat_proto_library` in `py_gapic.bzl` to bridge modern `rules_proto` Starlark ProtoInfo with r`ules_gapic` 's `CustomProtoInfo`. - Disable Python precompilation for generated directory outputs.
1 parent 588cda9 commit 5b5ece5

20 files changed

Lines changed: 339 additions & 98 deletions

File tree

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
# See https://github.com/bazelbuild/bazelisk
2-
USE_BAZEL_VERSION=6.5.0
2+
USE_BAZEL_VERSION=7.7.1

packages/gapic-generator/.bazelrc

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,13 @@
11
# New protobuf requires C++17
22
build --repo_env=BAZEL_CXXOPTS="-std=c++17"
3+
4+
# Workaround for rules_python precompilation bug with directory outputs:
5+
# Newer rules_python (v0.40.0+) attempts to precompile (.py -> .pyc) sources.
6+
# GAPIC code generator rules (e.g., //tests/integration:asset_py_gapic) output a
7+
# directory structure of generated code instead of discrete individual files.
8+
# This triggers: "Error in add: Cannot add directories to Args#add since they may expand to multiple values".
9+
# Disabling precompilation bypasses the bug without affecting runtime behavior.
10+
build --@rules_python//python/config_settings:precompile=force_disabled
11+
12+
# Disable Bzlmod to use legacy WORKSPACE file repository resolution
13+
common --noenable_bzlmod

packages/gapic-generator/WORKSPACE

Lines changed: 105 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -2,122 +2,163 @@ workspace(name = "gapic_generator_python")
22

33
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
44

5-
_bazel_skylib_version = "1.4.0"
5+
# Load Protobuf 33.5 first to ensure Bazel uses Protobuf 33.5 over older
6+
# transitive versions pulled in by downstream rules (e.g. gRPC or rules_gapic).
7+
_protobuf_version = "33.5"
8+
_protobuf_sha256 = "98bc55acbc30be2bda6fb8bc9169a31e14956bd3b3169c63edbe6207b8116b68"
9+
http_archive(
10+
name = "com_google_protobuf",
11+
sha256 = _protobuf_sha256,
12+
strip_prefix = "protobuf-{}".format(_protobuf_version),
13+
urls = ["https://github.com/protocolbuffers/protobuf/releases/download/v{0}/protobuf-{0}.zip".format(_protobuf_version)],
14+
)
615

7-
_bazel_skylib_sha256 = "f24ab666394232f834f74d19e2ff142b0af17466ea0c69a3f4c276ee75f6efce"
16+
# Load com_google_googleapis first so we can choose which version will be used
17+
_googleapis_sha256 = "2638026851b9110c280d75338581a752a4271340"
18+
http_archive(
19+
name = "com_google_googleapis",
20+
strip_prefix = "googleapis-{}".format(_googleapis_sha256),
21+
urls = ["https://github.com/googleapis/googleapis/archive/{0}.zip".format(_googleapis_sha256)],
22+
)
823

24+
# Load rules_gapic v1.0.0. We patch rules_gapic's .bzl files to inject the
25+
# explicit load for Starlark ProtoInfo from @rules_proto to maintain symbol
26+
# resolution under rules_proto / Protobuf 35.1.
27+
_rules_gapic_version = "1.0.0"
28+
_rules_gapic_sha256 = "c21e78a42f69898e7c3142fa837e3a637b1993d27c08a64723262611971d2b96"
29+
http_archive(
30+
name = "rules_gapic",
31+
sha256 = _rules_gapic_sha256,
32+
strip_prefix = "rules_gapic-{}".format(_rules_gapic_version),
33+
urls = [
34+
"https://github.com/googleapis/rules_gapic/archive/v{}.tar.gz".format(_rules_gapic_version)
35+
]
36+
)
37+
38+
# Load C++ rules matching modern Protobuf C++ requirements
39+
_rules_cc_version = "0.1.5"
40+
_rules_cc_sha256 = "b8b918a85f9144c01f6cfe0f45e4f2838c7413961a8ff23bc0c6cdf8bb07a3b6"
41+
http_archive(
42+
name = "rules_cc",
43+
sha256 = _rules_cc_sha256,
44+
strip_prefix = "rules_cc-{}".format(_rules_cc_version),
45+
urls = ["https://github.com/bazelbuild/rules_cc/releases/download/{0}/rules_cc-{0}.tar.gz".format(_rules_cc_version)],
46+
)
47+
48+
# Load bazel_skylib required by Starlark rules
49+
_bazel_skylib_version = "1.9.0"
50+
_bazel_skylib_sha256 = "3b5b49006181f5f8ff626ef8ddceaa95e9bb8ad294f7b5d7b11ea9f7ddaf8c59"
951
http_archive(
1052
name = "bazel_skylib",
1153
sha256 = _bazel_skylib_sha256,
1254
url = "https://github.com/bazelbuild/bazel-skylib/releases/download/{0}/bazel-skylib-{0}.tar.gz".format(_bazel_skylib_version),
1355
)
1456

57+
# Load Abseil C++ matching Protobuf 35 C++ dependencies
58+
_com_google_absl_version = "20240722.1"
59+
_com_google_absl_sha256 = "40cee67604060a7c8794d931538cb55f4d444073e556980c88b6c49bb9b19bb7"
60+
http_archive(
61+
name = "com_google_absl",
62+
sha256 = _com_google_absl_sha256,
63+
strip_prefix = "abseil-cpp-{}".format(_com_google_absl_version),
64+
urls = [
65+
"https://github.com/abseil/abseil-cpp/releases/download/{0}/abseil-cpp-{0}.tar.gz".format(_com_google_absl_version),
66+
],
67+
)
68+
69+
# Load Go rules required for GAPIC plugin building
1570
_io_bazel_rules_go_version = "0.33.0"
71+
_io_bazel_rules_go_sha256 = "685052b498b6ddfe562ca7a97736741d87916fe536623afb7da2824c0211c369"
1672
http_archive(
1773
name = "io_bazel_rules_go",
18-
sha256 = "685052b498b6ddfe562ca7a97736741d87916fe536623afb7da2824c0211c369",
74+
sha256 = _io_bazel_rules_go_sha256,
1975
urls = [
2076
"https://mirror.bazel.build/github.com/bazelbuild/rules_go/releases/download/v{0}/rules_go-v{0}.zip".format(_io_bazel_rules_go_version),
2177
"https://github.com/bazelbuild/rules_go/releases/download/v{0}/rules_go-v{0}.zip".format(_io_bazel_rules_go_version),
2278
],
2379
)
2480

25-
_rules_python_version = "0.26.0"
26-
27-
_rules_python_sha256 = "9d04041ac92a0985e344235f5d946f71ac543f1b1565f2cdbc9a2aaee8adf55b"
28-
81+
# Upgraded to rules_python 1.1.0 for modern C-extension toolchain support.
82+
_rules_python_version = "1.1.0"
83+
_rules_python_sha256 = "9c6e26911a79fbf510a8f06d8eedb40f412023cf7fa6d1461def27116bff022c"
2984
http_archive(
3085
name = "rules_python",
3186
sha256 = _rules_python_sha256,
3287
strip_prefix = "rules_python-{}".format(_rules_python_version),
33-
url = "https://github.com/bazelbuild/rules_python/archive/{}.tar.gz".format(_rules_python_version),
88+
url = "https://github.com/bazelbuild/rules_python/releases/download/{0}/rules_python-{0}.tar.gz".format(_rules_python_version),
3489
)
3590

36-
load("@rules_python//python:repositories.bzl", "py_repositories")
37-
91+
load("@rules_python//python:repositories.bzl", "py_repositories", "python_register_multi_toolchains")
3892
py_repositories()
3993

40-
load("@rules_python//python:pip.bzl", "pip_parse")
41-
94+
# Register multi-version hermetic Python toolchains (3.10 - 3.13) to ensure
95+
# Bazel can resolve both execution and C-header toolchains for any Python target.
96+
# Set ignore_root_user_error = True so toolchains unpack safely in Docker CI containers (EUID=0).
97+
python_register_multi_toolchains(
98+
name = "python",
99+
ignore_root_user_error = True,
100+
python_versions = [
101+
"3.11",
102+
"3.12",
103+
"3.13",
104+
],
105+
)
42106

107+
load("@rules_python//python:pip.bzl", "pip_parse")
43108
pip_parse(
44109
name = "gapic_generator_python_pip_deps",
45-
requirements_lock = "//:requirements.txt",
110+
requirements_lock = "//:requirements.txt",
46111
)
47-
load("@gapic_generator_python_pip_deps//:requirements.bzl", "install_deps")
48112

113+
load("@gapic_generator_python_pip_deps//:requirements.bzl", "install_deps")
49114
install_deps()
50-
#
51-
# Import gapic-generator-python specific dependencies
52-
#
53-
load(
54-
"//:repositories.bzl",
55-
"gapic_generator_python",
56-
"gapic_generator_register_toolchains",
57-
)
58-
59-
gapic_generator_python()
60-
61-
gapic_generator_register_toolchains()
62-
63-
_grpc_version = "1.71.0"
64-
65-
_grpc_sha256 = "9313c3f8f4dd3341597f152d506a50caf571fe40f886e24ea9078891990df285"
66115

116+
# Load gRPC v1.83.0 with temporary patch for legacy_channel.cc.
117+
# The fix is merged upstream (https://github.com/grpc/grpc/commit/816506e5c0434a42414af6955cc9eef0c562ff3a)
118+
# and this patch is temporary until released in a future gRPC release.
119+
_grpc_version = "1.83.0"
120+
_grpc_sha256 = "876ff5c9c26f364cd603531761268a5b58ccc1479afc78d6dab1d8e839da00c0"
67121
http_archive(
68122
name = "com_github_grpc_grpc",
69123
sha256 = _grpc_sha256,
70-
strip_prefix = "grpc-%s" % _grpc_version,
71-
urls = ["https://github.com/grpc/grpc/archive/v%s.zip" % _grpc_version],
72-
)
73-
# instantiated in grpc_deps().
74-
75-
_protobuf_version = "30.2"
76-
77-
_protobuf_sha256 = "07a43d88fe5a38e434c7f94129cad56a4c43a51f99336074d0799c2f7d4e44c5"
78-
79-
http_archive(
80-
name = "com_google_protobuf",
81-
sha256 = _protobuf_sha256,
82-
strip_prefix = "protobuf-%s" % _protobuf_version,
83-
urls = ["https://github.com/protocolbuffers/protobuf/archive/v%s.tar.gz" % _protobuf_version],
124+
strip_prefix = "grpc-{}".format(_grpc_version),
125+
urls = ["https://github.com/grpc/grpc/archive/v{}.zip".format(_grpc_version)],
126+
patches = ["//third_party:grpc_legacy_channel.patch"],
127+
patch_args = ["-p1"],
84128
)
85129
load("@com_github_grpc_grpc//bazel:grpc_deps.bzl", "grpc_deps")
86-
87130
grpc_deps()
88131

89-
http_archive(
90-
name = "rules_cc",
91-
urls = ["https://github.com/bazelbuild/rules_cc/releases/download/0.1.1/rules_cc-0.1.1.tar.gz"],
92-
sha256 = "712d77868b3152dd618c4d64faaddefcc5965f90f5de6e6dd1d5ddcd0be82d42",
93-
strip_prefix = "rules_cc-0.1.1",
132+
load(
133+
"//:repositories.bzl",
134+
"gapic_generator_python",
135+
"gapic_generator_register_toolchains",
94136
)
137+
gapic_generator_python()
138+
gapic_generator_register_toolchains()
95139

96-
load("@com_google_protobuf//:protobuf_deps.bzl", "protobuf_deps", "PROTOBUF_MAVEN_ARTIFACTS")
97-
# This is actually already done within grpc_deps but calling this for Bazel convention.
98-
protobuf_deps()
99-
100-
# Add rules_java to resolve the following error
101-
# `The repository '@compatibility_proxy' could not be resolved: Repository '@compatibility_proxy' is not defined`
140+
# Add rules_java to resolve compatibility proxy errors
102141
load("@rules_java//java:rules_java_deps.bzl", "rules_java_dependencies")
103-
104142
rules_java_dependencies()
105143

106-
# gRPC enforces a specific version of Go toolchain which conflicts with our build.
107-
# All the relevant parts of grpc_extra_deps() are imported in this WORKSPACE file
108-
# explicitly, that is why we do not call grpc_extra_deps() here and call
109-
# apple_rules_dependencies and apple_support_dependencies macros explicitly.
144+
# Load transitive proto dependencies and register proto toolchains
145+
load("@com_google_protobuf//:protobuf_deps.bzl", "protobuf_deps")
146+
protobuf_deps()
110147

111-
load("@build_bazel_rules_apple//apple:repositories.bzl", "apple_rules_dependencies")
148+
load("@rules_proto//proto:repositories.bzl", "rules_proto_dependencies")
149+
rules_proto_dependencies()
112150

151+
load("@rules_proto//proto:toolchains.bzl", "rules_proto_toolchains")
152+
rules_proto_toolchains()
153+
154+
# Load platform dependencies
155+
load("@build_bazel_rules_apple//apple:repositories.bzl", "apple_rules_dependencies")
113156
apple_rules_dependencies()
114157

115158
load("@build_bazel_apple_support//lib:repositories.bzl", "apple_support_dependencies")
116-
117159
apple_support_dependencies()
118160

119161
load("@com_google_googleapis//:repository_rules.bzl", "switched_rules_by_language")
120-
121162
switched_rules_by_language(
122163
name = "com_google_googleapis_imports",
123164
gapic = True,

packages/gapic-generator/gapic/templates/tests/unit/gapic/%name_%version/%sub/test_%service.py.j2

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,18 @@ _UUID4_RE = re.compile(r"{{ uuid4_re }}")
112112
{% endif %}
113113

114114

115+
@pytest.fixture(autouse=True)
116+
def disable_mtls_env():
117+
with mock.patch.dict(
118+
os.environ,
119+
{
120+
"GOOGLE_API_USE_CLIENT_CERTIFICATE": "false",
121+
"CLOUDSDK_CONTEXT_AWARE_USE_CLIENT_CERTIFICATE": "false",
122+
},
123+
):
124+
yield
125+
126+
115127
async def mock_async_gen(data, chunk_size=1):
116128
for i in range(0, len(data)): # pragma: NO COVER
117129
chunk = data[i : i + chunk_size]

packages/gapic-generator/repositories.bzl

Lines changed: 0 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -9,23 +9,6 @@ filegroup(
99

1010
def gapic_generator_python():
1111

12-
_maybe(
13-
http_archive,
14-
name = "bazel_skylib",
15-
strip_prefix = "bazel-skylib-2169ae1c374aab4a09aa90e65efe1a3aad4e279b",
16-
urls = ["https://github.com/bazelbuild/bazel-skylib/archive/2169ae1c374aab4a09aa90e65efe1a3aad4e279b.tar.gz"],
17-
)
18-
19-
_grpc_version = "1.47.0"
20-
_grpc_sha256 = "edf25f4db6c841853b7a29d61b0980b516dc31a1b6cdc399bcf24c1446a4a249"
21-
_maybe(
22-
http_archive,
23-
name = "com_github_grpc_grpc",
24-
sha256 = _grpc_sha256,
25-
strip_prefix = "grpc-{}".format(_grpc_version),
26-
url = "https://github.com/grpc/grpc/archive/v{}.zip".format(_grpc_version),
27-
)
28-
2912
_maybe(
3013
http_archive,
3114
name = "pandoc_linux_arm_64",
@@ -66,20 +49,6 @@ def gapic_generator_python():
6649
url = "https://github.com/jgm/pandoc/releases/download/3.7.0.2/pandoc-3.7.0.2-windows-x86_64.zip",
6750
)
6851

69-
_rules_gapic_version = "0.5.4"
70-
_maybe(
71-
http_archive,
72-
name = "rules_gapic",
73-
strip_prefix = "rules_gapic-%s" % _rules_gapic_version,
74-
urls = ["https://github.com/googleapis/rules_gapic/archive/v%s.tar.gz" % _rules_gapic_version],
75-
)
76-
_commit_sha = "2638026851b9110c280d75338581a752a4271340"
77-
_maybe(
78-
http_archive,
79-
name = "com_google_googleapis",
80-
strip_prefix = "googleapis-{}".format(_commit_sha),
81-
urls = ["https://github.com/googleapis/googleapis/archive/{}.zip".format(_commit_sha)],
82-
)
8352

8453
def gapic_generator_register_toolchains():
8554
native.register_toolchains(

packages/gapic-generator/rules_python_gapic/py_gapic.bzl

Lines changed: 49 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,39 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15-
load("@rules_gapic//:gapic.bzl", "proto_custom_library", "unzipped_srcjar")
15+
load("@rules_gapic//:gapic.bzl", "proto_custom_library", "unzipped_srcjar", "CustomProtoInfo")
1616
load("@rules_python//python:defs.bzl", "py_library")
1717
load("@gapic_generator_python_pip_deps//:requirements.bzl", "requirement")
1818

19+
# Load modern rules_proto Starlark ProtoInfo provider.
20+
# Needed because modern rules_proto targets output Starlark ProtoInfo, whereas
21+
# rules_gapic's proto_custom_library expects rules_gapic's CustomProtoInfo provider.
22+
load("@rules_proto//proto:defs.bzl", StarlarkProtoInfo = "ProtoInfo")
23+
24+
# Compatibility adapter rule to convert modern rules_proto Starlark ProtoInfo
25+
# into rules_gapic CustomProtoInfo provider required by proto_custom_library.
26+
def _gapic_compat_proto_library_impl(ctx):
27+
dep = ctx.attr.dep
28+
starlark_proto = dep[StarlarkProtoInfo]
29+
return [
30+
dep[DefaultInfo],
31+
# Construct CustomProtoInfo provider needed by rules_gapic's proto_custom_library.
32+
# Must not return ProtoInfo here so proto_custom_library selects CustomProtoInfo (which has transitive_imports).
33+
CustomProtoInfo(
34+
direct_sources = starlark_proto.direct_sources,
35+
check_deps_sources = starlark_proto.check_deps_sources,
36+
# Map modern transitive_sources to CustomProtoInfo's transitive_imports field
37+
transitive_imports = starlark_proto.transitive_sources,
38+
),
39+
]
40+
41+
gapic_compat_proto_library = rule(
42+
implementation = _gapic_compat_proto_library_impl,
43+
attrs = {
44+
"dep": attr.label(mandatory = True, providers = [StarlarkProtoInfo]),
45+
}
46+
)
47+
1948
def _gapic_test_file_impl(ctx):
2049
generated_test_file = ctx.actions.declare_file(ctx.label.name)
2150

@@ -46,6 +75,22 @@ def py_gapic_library(
4675
rest_numeric_enums = False,
4776
deps = [],
4877
**kwargs):
78+
79+
# We extract and propagate 'testonly' and 'tags' from kwargs to prevent Bazel dependency analysis
80+
# errors and ensure wildcard builds (e.g. manual tags) behave correctly.
81+
testonly = kwargs.get("testonly", False)
82+
tags = kwargs.get("tags", [])
83+
compat_srcs = []
84+
for i, src in enumerate(srcs):
85+
compat_name = "%s_compat_src_%d" % (name, i)
86+
gapic_compat_proto_library(
87+
name = compat_name,
88+
dep = src,
89+
testonly = testonly,
90+
tags = tags,
91+
)
92+
compat_srcs.append(":%s" % compat_name)
93+
4994
srcjar_target_name = "%s_srcjar" % name
5095
srcjar_output_suffix = ".srcjar"
5196

@@ -67,9 +112,11 @@ def py_gapic_library(
67112
if rest_numeric_enums:
68113
opt_args = opt_args + ["rest-numeric-enums"]
69114

115+
# Point deps to compat_srcs so proto_custom_library receives targets providing
116+
# the CustomProtoInfo provider instead of raw Starlark ProtoInfo targets.
70117
proto_custom_library(
71118
name = srcjar_target_name,
72-
deps = srcs,
119+
deps = compat_srcs,
73120
plugin = Label("@gapic_generator_python//:gapic_plugin"),
74121
plugin_args = plugin_args,
75122
plugin_file_args = file_args,

0 commit comments

Comments
 (0)