Skip to content

Commit 14d536b

Browse files
committed
fix(runfiles): Don't write to runfiles
In remote execution contexts, runfiles aren't always writable.
1 parent c964fb4 commit 14d536b

File tree

4 files changed

+31
-29
lines changed

4 files changed

+31
-29
lines changed

py/private/py_binary.bzl

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -26,25 +26,14 @@ def _py_binary_rule_impl(ctx):
2626
pth_lines.use_param_file("%s", use_always = True)
2727
pth_lines.set_param_file_format("multiline")
2828

29-
# The venv is created at the root in the runfiles tree, in 'VENV_NAME', the full path is "${RUNFILES_DIR}/${VENV_NAME}",
30-
# but depending on if we are running as the top level binary or a tool, then $RUNFILES_DIR may be absolute or relative.
31-
# Paths in the .pth are relative to the site-packages folder where they reside.
32-
# All "import" paths from `py_library` start with the workspace name, so we need to go back up the tree for
33-
# each segment from site-packages in the venv to the root of the runfiles tree.
34-
# Five .. will get us back to the root of the venv:
35-
# {name}.runfiles/.{name}.venv/lib/python{version}/site-packages/first_party.pth
36-
# If the target is defined with a slash, it adds to the level of nesting
37-
target_depth = len(ctx.label.name.split("/")) - 1
38-
escape = "/".join(([".."] * (4 + target_depth)))
39-
4029
# A few imports rely on being able to reference the root of the runfiles tree as a Python module,
4130
# the common case here being the @rules_python//python/runfiles target that adds the runfiles helper,
4231
# which ends up in bazel_tools/tools/python/runfiles/runfiles.py, but there are no imports attrs that hint we
4332
# should be adding the root to the PYTHONPATH
4433
# Maybe in the future we can opt out of this?
45-
pth_lines.add(escape)
34+
pth_lines.add(".")
4635

47-
pth_lines.add_all(imports_depset, format_each = "{}/%s".format(escape))
36+
pth_lines.add_all(imports_depset)
4837

4938
site_packages_pth_file = ctx.actions.declare_file("{}.venv.pth".format(ctx.attr.name))
5039
ctx.actions.write(

py/private/run.tmpl.sh

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ runfiles_export_envvars
1111
set -o errexit -o nounset -o pipefail
1212

1313
PWD="$(pwd)"
14+
TEMPORARY_DIRECTORY="$(mktemp -d)"
1415

1516
# Returns an absolute path to the given location if the path is relative, otherwise return
1617
# the path unchanged.
@@ -23,6 +24,10 @@ function alocation {
2324
fi
2425
}
2526

27+
function cleanup {
28+
rm -rf "${TEMPORARY_DIRECTORY}"
29+
}
30+
2631
function python_location {
2732
local PYTHON="{{ARG_PYTHON}}"
2833
local RUNFILES_INTERPRETER="{{RUNFILES_INTERPRETER}}"
@@ -34,14 +39,18 @@ function python_location {
3439
fi
3540
}
3641

42+
trap cleanup EXIT
43+
3744
VENV_TOOL="$(rlocation {{VENV_TOOL}})"
38-
VIRTUAL_ENV="$(alocation "${RUNFILES_DIR}/{{ARG_VENV_NAME}}")"
45+
VIRTUAL_ENV="$(alocation "${TEMPORARY_DIRECTORY}/{{ARG_VENV_NAME}}")"
46+
3947
export VIRTUAL_ENV
4048

4149
"${VENV_TOOL}" \
4250
--location "${VIRTUAL_ENV}" \
4351
--python "$(python_location)" \
4452
--pth-file "$(rlocation {{ARG_PTH_FILE}})" \
53+
--pth-entry-prefix "$(alocation ${RUNFILES_DIR})" \
4554
--collision-strategy "{{ARG_COLLISION_STRATEGY}}" \
4655
--venv-name "{{ARG_VENV_NAME}}"
4756

@@ -58,4 +67,4 @@ if [ -n "${BASH:-}" -o -n "${ZSH_VERSION:-}" ] ; then
5867
hash -r 2> /dev/null
5968
fi
6069

61-
exec "{{EXEC_PYTHON_BIN}}" {{INTERPRETER_FLAGS}} "$(rlocation {{ENTRYPOINT}})" "$@"
70+
"{{EXEC_PYTHON_BIN}}" {{INTERPRETER_FLAGS}} "$(rlocation {{ENTRYPOINT}})" "$@"

py/tests/py_image_layer/my_app_layers_listing.yaml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2471,7 +2471,7 @@ files:
24712471
- drwxr-xr-x 0 0 0 0 Jan 1 2023 ./py/tests/
24722472
- drwxr-xr-x 0 0 0 0 Jan 1 2023 ./py/tests/py_image_layer/
24732473
- -rwxr-xr-x 0 0 0 204 Jan 1 2023 ./py/tests/py_image_layer/__main__.py
2474-
- -rwxr-xr-x 0 0 0 2895 Jan 1 2023 ./py/tests/py_image_layer/my_app_bin
2474+
- -rwxr-xr-x 0 0 0 3067 Jan 1 2023 ./py/tests/py_image_layer/my_app_bin
24752475
- drwxr-xr-x 0 0 0 0 Jan 1 2023 ./py/tests/py_image_layer/my_app_bin.runfiles/
24762476
- drwxr-xr-x 0 0 0 0 Jan 1 2023 ./py/tests/py_image_layer/my_app_bin.runfiles/aspect_rules_py/
24772477
- drwxr-xr-x 0 0 0 0 Jan 1 2023 ./py/tests/py_image_layer/my_app_bin.runfiles/aspect_rules_py/py/
@@ -2484,13 +2484,13 @@ files:
24842484
- -rwxr-xr-x 0 0 0 204 Jan 1 2023 ./py/tests/py_image_layer/my_app_bin.runfiles/aspect_rules_py/py/tests/py_image_layer/__main__.py
24852485
- drwxr-xr-x 0 0 0 0 Jan 1 2023 ./py/tests/py_image_layer/my_app_bin.runfiles/aspect_rules_py/py/tests/py_image_layer/branding/
24862486
- -rwxr-xr-x 0 0 0 42 Jan 1 2023 ./py/tests/py_image_layer/my_app_bin.runfiles/aspect_rules_py/py/tests/py_image_layer/branding/__init__.py
2487-
- -rwxr-xr-x 0 0 0 2895 Jan 1 2023 ./py/tests/py_image_layer/my_app_bin.runfiles/aspect_rules_py/py/tests/py_image_layer/my_app_bin
2488-
- -rwxr-xr-x 0 0 0 183 Jan 1 2023 ./py/tests/py_image_layer/my_app_bin.runfiles/aspect_rules_py/py/tests/py_image_layer/my_app_bin.venv.pth
2487+
- -rwxr-xr-x 0 0 0 3067 Jan 1 2023 ./py/tests/py_image_layer/my_app_bin.runfiles/aspect_rules_py/py/tests/py_image_layer/my_app_bin
2488+
- -rwxr-xr-x 0 0 0 125 Jan 1 2023 ./py/tests/py_image_layer/my_app_bin.runfiles/aspect_rules_py/py/tests/py_image_layer/my_app_bin.venv.pth
24892489
- drwxr-xr-x 0 0 0 0 Jan 1 2023 ./py/tests/py_image_layer/my_app_bin.runfiles/aspect_rules_py/py/tools/
24902490
- drwxr-xr-x 0 0 0 0 Jan 1 2023 ./py/tests/py_image_layer/my_app_bin.runfiles/bazel_tools/
24912491
- drwxr-xr-x 0 0 0 0 Jan 1 2023 ./py/tests/py_image_layer/my_app_bin.runfiles/bazel_tools/tools/
24922492
- drwxr-xr-x 0 0 0 0 Jan 1 2023 ./py/tests/py_image_layer/my_app_bin.runfiles/bazel_tools/tools/bash/
24932493
- drwxr-xr-x 0 0 0 0 Jan 1 2023 ./py/tests/py_image_layer/my_app_bin.runfiles/bazel_tools/tools/bash/runfiles/
24942494
- -rwxr-xr-x 0 0 0 21622 Jan 1 2023 ./py/tests/py_image_layer/my_app_bin.runfiles/bazel_tools/tools/bash/runfiles/runfiles.bash
24952495
- drwxr-xr-x 0 0 0 0 Jan 1 2023 ./py/tests/py_image_layer/my_app_bin.runfiles/pypi_colorama/
2496-
- -rwxr-xr-x 0 0 0 183 Jan 1 2023 ./py/tests/py_image_layer/my_app_bin.venv.pth
2496+
- -rwxr-xr-x 0 0 0 125 Jan 1 2023 ./py/tests/py_image_layer/my_app_bin.venv.pth

py/tools/py/src/pth.rs

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ def _FindPythonRunfilesRoot():
1919
# bazel-bin/py/tests/external-deps/foo.runfiles/.foo.venv/lib/python3.9/site-packages/runfiles
2020
# ╰─────────────────────┬─────────────────────╯╰───┬───╯╰─────────────┬─────────────╯╰───┬───╯
2121
# bazel runfiles root venv root Python packages root Python package
22-
22+
2323
for _ in range("rules_python/python/runfiles/runfiles.py".count("/") + 3):
2424
root = os.path.dirname(root)
2525
return root
@@ -94,15 +94,19 @@ impl PthFile {
9494

9595
match entry.file_name() {
9696
Some(name) if name == "site-packages" => {
97-
let src_dir = dest
98-
.join(entry.clone())
99-
.canonicalize()
100-
.into_diagnostic()
101-
.wrap_err(format!(
102-
"Unable to get full source dir path for {} relative to {}",
103-
entry.display(),
104-
dest.display(),
105-
))?;
97+
let src_dir = if entry.is_absolute() {
98+
entry.clone()
99+
} else {
100+
dest.join(&entry)
101+
}
102+
.canonicalize()
103+
.into_diagnostic()
104+
.wrap_err(format!(
105+
"Unable to get full source dir path for {} relative to {}",
106+
entry.display(),
107+
dest.display(),
108+
))?;
109+
106110
create_symlinks(&src_dir, &src_dir, &dest, &opts.collision_strategy)?;
107111
}
108112
_ => {

0 commit comments

Comments
 (0)