Skip to content

Commit 7719529

Browse files
authored
fix: delete BUILD et al files from pypi sourced dependencies (#3029)
Sometimes wheels mistakenly contain BUILD files (or other special Bazel files). When extracted, these interfere with how we expected the repo to look. In particular, globs no longer match correctly because BUILD files create a Bazel package boundary. To fix, delete these files. They aren't generally usable, since they can't know what version of Bazel, rule_python, or similar, is consuming them. Fixes #2782
1 parent e5ef69b commit 7719529

File tree

26 files changed

+123
-3
lines changed

26 files changed

+123
-3
lines changed

.bazelrc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44
# (Note, we cannot use `common --deleted_packages` because the bazel version command doesn't support it)
55
# To update these lines, execute
66
# `bazel run @rules_bazel_integration_test//tools:update_deleted_packages`
7-
build --deleted_packages=examples/build_file_generation,examples/build_file_generation/random_number_generator,examples/bzlmod,examples/bzlmod_build_file_generation,examples/bzlmod_build_file_generation/other_module/other_module/pkg,examples/bzlmod_build_file_generation/runfiles,examples/bzlmod/entry_points,examples/bzlmod/entry_points/tests,examples/bzlmod/libs/my_lib,examples/bzlmod/other_module,examples/bzlmod/other_module/other_module/pkg,examples/bzlmod/patches,examples/bzlmod/py_proto_library,examples/bzlmod/py_proto_library/example.com/another_proto,examples/bzlmod/py_proto_library/example.com/proto,examples/bzlmod/runfiles,examples/bzlmod/tests,examples/bzlmod/tests/other_module,examples/bzlmod/whl_mods,examples/multi_python_versions/libs/my_lib,examples/multi_python_versions/requirements,examples/multi_python_versions/tests,examples/pip_parse,examples/pip_parse_vendored,examples/pip_repository_annotations,examples/py_proto_library,examples/py_proto_library/example.com/another_proto,examples/py_proto_library/example.com/proto,gazelle,gazelle/manifest,gazelle/manifest/generate,gazelle/manifest/hasher,gazelle/manifest/test,gazelle/modules_mapping,gazelle/python,gazelle/pythonconfig,gazelle/python/private,tests/integration/compile_pip_requirements,tests/integration/compile_pip_requirements_test_from_external_repo,tests/integration/custom_commands,tests/integration/ignore_root_user_error,tests/integration/ignore_root_user_error/submodule,tests/integration/local_toolchains,tests/integration/pip_parse,tests/integration/pip_parse/empty,tests/integration/py_cc_toolchain_registered,tests/modules/another_module,tests/modules/other,tests/modules/other/nspkg_delta,tests/modules/other/nspkg_gamma,tests/modules/other/nspkg_single,tests/modules/other/simple_v1,tests/modules/other/simple_v2,tests/modules/other/with_external_data
8-
query --deleted_packages=examples/build_file_generation,examples/build_file_generation/random_number_generator,examples/bzlmod,examples/bzlmod_build_file_generation,examples/bzlmod_build_file_generation/other_module/other_module/pkg,examples/bzlmod_build_file_generation/runfiles,examples/bzlmod/entry_points,examples/bzlmod/entry_points/tests,examples/bzlmod/libs/my_lib,examples/bzlmod/other_module,examples/bzlmod/other_module/other_module/pkg,examples/bzlmod/patches,examples/bzlmod/py_proto_library,examples/bzlmod/py_proto_library/example.com/another_proto,examples/bzlmod/py_proto_library/example.com/proto,examples/bzlmod/runfiles,examples/bzlmod/tests,examples/bzlmod/tests/other_module,examples/bzlmod/whl_mods,examples/multi_python_versions/libs/my_lib,examples/multi_python_versions/requirements,examples/multi_python_versions/tests,examples/pip_parse,examples/pip_parse_vendored,examples/pip_repository_annotations,examples/py_proto_library,examples/py_proto_library/example.com/another_proto,examples/py_proto_library/example.com/proto,gazelle,gazelle/manifest,gazelle/manifest/generate,gazelle/manifest/hasher,gazelle/manifest/test,gazelle/modules_mapping,gazelle/python,gazelle/pythonconfig,gazelle/python/private,tests/integration/compile_pip_requirements,tests/integration/compile_pip_requirements_test_from_external_repo,tests/integration/custom_commands,tests/integration/ignore_root_user_error,tests/integration/ignore_root_user_error/submodule,tests/integration/local_toolchains,tests/integration/pip_parse,tests/integration/pip_parse/empty,tests/integration/py_cc_toolchain_registered,tests/modules/another_module,tests/modules/other,tests/modules/other/nspkg_delta,tests/modules/other/nspkg_gamma,tests/modules/other/nspkg_single,tests/modules/other/simple_v1,tests/modules/other/simple_v2,tests/modules/other/with_external_data
7+
build --deleted_packages=examples/build_file_generation,examples/build_file_generation/random_number_generator,examples/bzlmod,examples/bzlmod_build_file_generation,examples/bzlmod_build_file_generation/other_module/other_module/pkg,examples/bzlmod_build_file_generation/runfiles,examples/bzlmod/entry_points,examples/bzlmod/entry_points/tests,examples/bzlmod/libs/my_lib,examples/bzlmod/other_module,examples/bzlmod/other_module/other_module/pkg,examples/bzlmod/patches,examples/bzlmod/py_proto_library,examples/bzlmod/py_proto_library/example.com/another_proto,examples/bzlmod/py_proto_library/example.com/proto,examples/bzlmod/runfiles,examples/bzlmod/tests,examples/bzlmod/tests/other_module,examples/bzlmod/whl_mods,examples/multi_python_versions/libs/my_lib,examples/multi_python_versions/requirements,examples/multi_python_versions/tests,examples/pip_parse,examples/pip_parse_vendored,examples/pip_repository_annotations,examples/py_proto_library,examples/py_proto_library/example.com/another_proto,examples/py_proto_library/example.com/proto,gazelle,gazelle/manifest,gazelle/manifest/generate,gazelle/manifest/hasher,gazelle/manifest/test,gazelle/modules_mapping,gazelle/python,gazelle/pythonconfig,gazelle/python/private,tests/integration/compile_pip_requirements,tests/integration/compile_pip_requirements_test_from_external_repo,tests/integration/custom_commands,tests/integration/ignore_root_user_error,tests/integration/ignore_root_user_error/submodule,tests/integration/local_toolchains,tests/integration/pip_parse,tests/integration/pip_parse/empty,tests/integration/py_cc_toolchain_registered,tests/modules/another_module,tests/modules/other,tests/modules/other/nspkg_delta,tests/modules/other/nspkg_gamma,tests/modules/other/nspkg_single,tests/modules/other/simple_v1,tests/modules/other/simple_v2,tests/modules/other/with_external_data,tests/whl_with_build_files/testdata,tests/whl_with_build_files/testdata/somepkg,tests/whl_with_build_files/testdata/somepkg-1.0.dist-info,tests/whl_with_build_files/testdata/somepkg/subpkg
8+
query --deleted_packages=examples/build_file_generation,examples/build_file_generation/random_number_generator,examples/bzlmod,examples/bzlmod_build_file_generation,examples/bzlmod_build_file_generation/other_module/other_module/pkg,examples/bzlmod_build_file_generation/runfiles,examples/bzlmod/entry_points,examples/bzlmod/entry_points/tests,examples/bzlmod/libs/my_lib,examples/bzlmod/other_module,examples/bzlmod/other_module/other_module/pkg,examples/bzlmod/patches,examples/bzlmod/py_proto_library,examples/bzlmod/py_proto_library/example.com/another_proto,examples/bzlmod/py_proto_library/example.com/proto,examples/bzlmod/runfiles,examples/bzlmod/tests,examples/bzlmod/tests/other_module,examples/bzlmod/whl_mods,examples/multi_python_versions/libs/my_lib,examples/multi_python_versions/requirements,examples/multi_python_versions/tests,examples/pip_parse,examples/pip_parse_vendored,examples/pip_repository_annotations,examples/py_proto_library,examples/py_proto_library/example.com/another_proto,examples/py_proto_library/example.com/proto,gazelle,gazelle/manifest,gazelle/manifest/generate,gazelle/manifest/hasher,gazelle/manifest/test,gazelle/modules_mapping,gazelle/python,gazelle/pythonconfig,gazelle/python/private,tests/integration/compile_pip_requirements,tests/integration/compile_pip_requirements_test_from_external_repo,tests/integration/custom_commands,tests/integration/ignore_root_user_error,tests/integration/ignore_root_user_error/submodule,tests/integration/local_toolchains,tests/integration/pip_parse,tests/integration/pip_parse/empty,tests/integration/py_cc_toolchain_registered,tests/modules/another_module,tests/modules/other,tests/modules/other/nspkg_delta,tests/modules/other/nspkg_gamma,tests/modules/other/nspkg_single,tests/modules/other/simple_v1,tests/modules/other/simple_v2,tests/modules/other/with_external_data,tests/whl_with_build_files/testdata,tests/whl_with_build_files/testdata/somepkg,tests/whl_with_build_files/testdata/somepkg-1.0.dist-info,tests/whl_with_build_files/testdata/somepkg/subpkg
99

1010
test --test_output=errors
1111

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,9 @@ END_UNRELEASED_TEMPLATE
6464
* (pypi) Fixes an issue where builds using a `bazel vendor` vendor directory
6565
would fail if the constraints file contained environment markers. Fixes
6666
[#2996](https://github.com/bazel-contrib/rules_python/issues/2996).
67+
* (pypi) Wheels with BUILD.bazel (or other special Bazel files) no longer
68+
result in missing files at runtime
69+
([#2782](https://github.com/bazel-contrib/rules_python/issues/2782)).
6770

6871
{#v0-0-0-added}
6972
### Added

MODULE.bazel

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,8 @@ use_repo(
103103
internal_dev_deps,
104104
"buildkite_config",
105105
"rules_python_runtime_env_tc_info",
106+
"somepkg_with_build_files",
107+
"whl_with_build_files",
106108
)
107109

108110
# Add gazelle plugin so that we can run the gazelle example as an e2e integration

python/private/internal_dev_deps.bzl

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
"""Module extension for internal dev_dependency=True setup."""
1515

1616
load("@bazel_ci_rules//:rbe_repo.bzl", "rbe_preconfig")
17+
load("//python/private/pypi:whl_library.bzl", "whl_library")
18+
load("//tests/support/whl_from_dir:whl_from_dir_repo.bzl", "whl_from_dir_repo")
1719
load(":runtime_env_repo.bzl", "runtime_env_repo")
1820

1921
def _internal_dev_deps_impl(mctx):
@@ -28,6 +30,17 @@ def _internal_dev_deps_impl(mctx):
2830
)
2931
runtime_env_repo(name = "rules_python_runtime_env_tc_info")
3032

33+
whl_from_dir_repo(
34+
name = "whl_with_build_files",
35+
root = "//tests/whl_with_build_files:testdata/BUILD.bazel",
36+
output = "somepkg-1.0-any-none-any.whl",
37+
)
38+
whl_library(
39+
name = "somepkg_with_build_files",
40+
whl_file = "@whl_with_build_files//:somepkg-1.0-any-none-any.whl",
41+
requirement = "somepkg",
42+
)
43+
3144
internal_dev_deps = module_extension(
3245
implementation = _internal_dev_deps_impl,
3346
doc = "This extension creates internal rules_python dev dependencies.",

python/private/pypi/whl_library.bzl

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,7 @@ def _whl_library_impl(rctx):
249249

250250
whl_path = None
251251
if rctx.attr.whl_file:
252+
rctx.watch(rctx.attr.whl_file)
252253
whl_path = rctx.path(rctx.attr.whl_file)
253254

254255
# Simulate the behaviour where the whl is present in the current directory.
@@ -471,8 +472,26 @@ def _whl_library_impl(rctx):
471472
],
472473
)
473474

474-
rctx.file("BUILD.bazel", build_file_contents)
475+
# Delete these in case the wheel had them. They generally don't cause
476+
# a problem, but let's avoid the chance of that happening.
477+
rctx.file("WORKSPACE")
478+
rctx.file("WORKSPACE.bazel")
479+
rctx.file("MODULE.bazel")
480+
rctx.file("REPO.bazel")
481+
482+
paths = list(rctx.path(".").readdir())
483+
for _ in range(10000000):
484+
if not paths:
485+
break
486+
path = paths.pop()
487+
488+
# BUILD files interfere with globbing and Bazel package boundaries.
489+
if path.basename in ("BUILD", "BUILD.bazel"):
490+
rctx.delete(path)
491+
elif path.is_dir:
492+
paths.extend(path.readdir())
475493

494+
rctx.file("BUILD.bazel", build_file_contents)
476495
return
477496

478497
def _generate_entry_point_contents(

tests/support/support.bzl

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
# rules_testing or as config_setting values, which don't support Label in some
2020
# places.
2121

22+
load("//python/private:bzlmod_enabled.bzl", "BZLMOD_ENABLED") # buildifier: disable=bzl-visibility
2223
load("//python/private:util.bzl", "IS_BAZEL_7_OR_HIGHER") # buildifier: disable=bzl-visibility
2324

2425
MAC = Label("//tests/support:mac")
@@ -48,3 +49,8 @@ SUPPORTS_BOOTSTRAP_SCRIPT = select({
4849
"@platforms//os:windows": ["@platforms//:incompatible"],
4950
"//conditions:default": [],
5051
}) if IS_BAZEL_7_OR_HIGHER else ["@platforms//:incompatible"]
52+
53+
SUPPORTS_BZLMOD_UNIXY = select({
54+
"@platforms//os:windows": ["@platforms//:incompatible"],
55+
"//conditions:default": [],
56+
}) if BZLMOD_ENABLED else ["@platforms//:incompatible"]

tests/support/whl_from_dir/BUILD.bazel

Whitespace-only changes.
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
"""Creates a whl file from a directory tree.
2+
3+
Used to test wheels. Avoids checking in prebuilt files and their associated
4+
security risks.
5+
"""
6+
7+
load("//python/private:repo_utils.bzl", "repo_utils") # buildifier: disable=bzl-visibility
8+
9+
def _whl_from_dir_repo(rctx):
10+
root = rctx.path(rctx.attr.root).dirname
11+
repo_utils.watch_tree(rctx, root)
12+
13+
output = rctx.path(rctx.attr.output)
14+
repo_utils.execute_checked(
15+
rctx,
16+
# cd to root so zip recursively takes everything there.
17+
working_directory = str(root),
18+
op = "WhlFromDir",
19+
arguments = [
20+
"zip",
21+
"-0", # Skip compressing
22+
"-X", # Don't store file time or metadata
23+
str(output),
24+
"-r",
25+
".",
26+
],
27+
)
28+
rctx.file("BUILD.bazel", 'exports_files(glob(["*"]))')
29+
30+
whl_from_dir_repo = repository_rule(
31+
implementation = _whl_from_dir_repo,
32+
attrs = {
33+
"output": attr.string(
34+
doc = """
35+
Output file name to write. Should match the wheel filename format:
36+
`pkg-version-pyversion-abi-platform.whl`. Typically a value like
37+
`mypkg-1.0-any-none-any.whl` is whats used for testing.
38+
39+
For the full format, see
40+
https://packaging.python.org/en/latest/specifications/binary-distribution-format/#file-name-convention
41+
""",
42+
),
43+
"root": attr.label(
44+
doc = """
45+
A file whose directory will be put into the output wheel. All files
46+
are included verbatim.
47+
""",
48+
),
49+
},
50+
)
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
load("//python:py_test.bzl", "py_test")
2+
load("//tests/support:support.bzl", "SUPPORTS_BZLMOD_UNIXY")
3+
4+
py_test(
5+
name = "verify_files_test",
6+
srcs = ["verify_files_test.py"],
7+
target_compatible_with = SUPPORTS_BZLMOD_UNIXY,
8+
deps = ["@somepkg_with_build_files//:pkg"],
9+
)

tests/whl_with_build_files/testdata/BUILD

Whitespace-only changes.

0 commit comments

Comments
 (0)