E406 `whl_library.BuildWheelFromSource` uses pip to download dependencies and does not inject credential helper information. · Issue #2640 · bazel-contrib/rules_python · GitHub
[go: up one dir, main page]

Skip to content

whl_library.BuildWheelFromSource uses pip to download dependencies and does not inject credential helper information. #2640

@dougthor42

Description

@dougthor42

🐞 bug report

Affected Rule

pip.parse and the underlying code

Is this a regression?

Not that I can tell.

Description

When using python package index that requires authentication, whl_library.BuildWheelFromSource will pass that index arg to the pip wheel command.

This is a problem when using the Bazel downloader (experimental_index_url et. al.). Bazel can authenticate to the package index via a credential helper header injection and can successfully download the source tarball. However, rules_python then tries to create a wheel from that tarball and uses pip wheel --index-url "${INDEX_NEEDING_AUTH}" .... Thus building the wheel fails because pip can't auth to the private index.

🔬 Minimal Reproduction

Hard to repro if you don't have a private index readily available, but the gist is:

  1. Use only package indexes that require authentication
  2. Use experimental Bazel downloader experimental_index_url
  3. Attempt to install a package that fits both of these requirements. pygraphviz is a good example of such a package.
    1. Does not have a wheel available on the package index
    2. Requires an additional package (such as setuptools) in order to build a wheel.

🔥 Exception or Error

root@b4337bd118dd:/bazel_starter# time bazel build --nobuild --config=local --remote_cache= --bes_backend= //...
INFO: Repository rules_python~~pip~pypi_312_pygraphviz_sdist_8b0b9207 instantiated at:
  <builtin>: in <toplevel>
Repository rule whl_library defined at:
  /root/.cache/bazel/_bazel_root/dd66987607986e0bbc3aa1b8af741d50/external/rules_python~/python/private/pypi/whl_library.bzl:469:30: in <toplevel>
INFO: repository @@rules_python~~pip~pypi_312_pygraphviz_sdist_8b0b9207' used the following cache hits instead of downloading the corresponding file.
 * Hash '8b0b9207954012f3b670e53b8f8f448a28d12bdbbcf69249313bd8dbe680152f' for https://REDACTED_1/pygraphviz/pygraphviz-1.12.tar.gz
If the definition of 'repository @@rules_python~~pip~pypi_312_pygraphviz_sdist_8b0b9207' was updated, verify that the hashes were also updated.
ERROR: /root/.cache/bazel/_bazel_root/dd66987607986e0bbc3aa1b8af741d50/external/rules_python~/python/private/repo_utils.bzl:79:16: An error occurred during the fetch of repository 'rules_python~~pip~pypi_312_pygraphviz_sdist_8b0b9207':
   Traceback (most recent call last):
        File "/root/.cache/bazel/_bazel_root/dd66987607986e0bbc3aa1b8af741d50/external/rules_python~/python/private/pypi/whl_library.bzl", line 245, column 40, in _whl_library_impl
                pypi_repo_utils.execute_checked(
        File "/root/.cache/bazel/_bazel_root/dd66987607986e0bbc3aa1b8af741d50/external/rules_python~/python/private/pypi/pypi_repo_utils.bzl", line 133, column 38, in _execute_checked
                return repo_utils.execute_checked(
        File "/root/.cache/bazel/_bazel_root/dd66987607986e0bbc3aa1b8af741d50/external/rules_python~/python/private/repo_utils.bzl", line 216, column 29, in _execute_checked
                return _execute_internal(fail_on_error = True, *args, **kwargs)
        File "/root/.cache/bazel/_bazel_root/dd66987607986e0bbc3aa1b8af741d50/external/rules_python~/python/private/repo_utils.bzl", line 147, column 27, in _execute_internal
                return logger.fail((
        File "/root/.cache/bazel/_bazel_root/dd66987607986e0bbc3aa1b8af741d50/external/rules_python~/python/private/repo_utils.bzl", line 89, column 39, in lambda
                fail = lambda message_cb: _log(-1, "FAIL", message_cb, fail),
        File "/root/.cache/bazel/_bazel_root/dd66987607986e0bbc3aa1b8af741d50/external/rules_python~/python/private/repo_utils.bzl", line 79, column 16, in _log
                printer("\nrules_python:{} {}:".format(
Error in fail:
rules_python:whl_library(@@rules_python~~pip~pypi_312_pygraphviz_sdist_8b0b9207) FAIL: repo.execute: whl_library.BuildWheelFromSource(rules_python~~pip~pypi_312_pygraphviz_sdist_8b0b9207, pygraphviz==1.12): end: failure:
  command: /root/.cache/bazel/_bazel_root/dd66987607986e0bbc3aa1b8af741d50/external/rules_python~~python~python_3_12_2_host/python -m python.private.pypi.whl_installer.wheel_installer --requirement pygraphviz==1.12 --isolated --extra_pip_args "{\"arg\":[\"--index-url\",\"https://oauth2accesstoken@REDACTED_2/simple\",\"--extra-index-url\",\"https://oauth2accesstoken@REDACTED_1/simple\",\"--find-links\",\".\"]}" --pip_data_exclude "{\"arg\":[]}" --environment "{\"arg\":{}}"
  return code: 1
  working dir: <default: /root/.cache/bazel/_bazel_root/dd66987607986e0bbc3aa1b8af741d50/external/rules_python~~pip~pypi_312_pygraphviz_sdist_8b0b9207>
  timeout: 600
  environment:
PYTHONPATH="/root/.cache/bazel/_bazel_root/dd66987607986e0bbc3aa1b8af741d50/external/rules_python~:/root/.cache/bazel/_bazel_root/dd66987607986e0bbc3aa1b8af741d50/external/rules_python~~internal_deps~pypi__build:/root/.cache/bazel/_bazel_root/dd66987607986e0bbc3aa1b8af741d50/external/rules_python~~internal_deps~pypi__click:/root/.cache/bazel/_bazel_root/dd66987607986e0bbc3aa1b8af741d50/external/rules_python~~internal_deps~py
pi__colorama:/root/.cache/bazel/_bazel_root/dd66987607986e0bbc3aa1b8af741d50/external/rules_python~~internal_deps~pypi__importlib_metadata:/root/.cache/bazel/_bazel_root/dd66987607986e0bbc3aa1b8af741d50/external/rules_python~~internal_deps~pypi__installer:/root/.cache/bazel/_bazel_root/dd66987607986e0bbc3aa1b8af741d50/external/rules_python~~internal_deps~pypi__more_itertools:/root/.cache/bazel/_bazel_root/dd66987607986e0bbc3
aa1b8af741d50/external/rules_python~~internal_deps~pypi__packaging:/root/.cache/bazel/_bazel_root/dd66987607986e0bbc3aa1b8af741d50/external/rules_python~~internal_deps~pypi__pep517:/root/.cache/bazel/_bazel_root/dd66987607986e0bbc3aa1b8af741d50/external/rules_python~~internal_deps~pypi__pip:/root/.cache/bazel/_bazel_root/dd66987607986e0bbc3aa1b8af741d50/external/rules_python~~internal_deps~pypi__pip_tools:/root/.cache/bazel/
_bazel_root/dd66987607986e0bbc3aa1b8af741d50/external/rules_python~~internal_deps~pypi__pyproject_hooks:/root/.cache/bazel/_bazel_root/dd66987607986e0bbc3aa1b8af741d50/external/rules_python~~internal_deps~pypi__setuptools:/root/.cache/bazel/_bazel_root/dd66987607986e0bbc3aa1b8af741d50/external/rules_python~~internal_deps~pypi__tomli:/root/.cache/bazel/_bazel_root/dd66987607986e0bbc3aa1b8af741d50/external/rules_python~~intern
al_deps~pypi__wheel:/root/.cache/bazel/_bazel_root/dd66987607986e0bbc3aa1b8af741d50/external/rules_python~~internal_deps~pypi__zipp"
CPPFLAGS="-isystem /root/.cache/bazel/_bazel_root/dd66987607986e0bbc3aa1b8af741d50/external/rules_python~~python~python_3_12_2_host/include/python3.12"
===== stdout start =====
Looking in indexes: https://****@REDACTED_2/simple, https://****@REDACTED_1/simple                                                                                                                                                                                                                                                                                         Looking in links: .
Processing ./pygraphviz-1.12.tar.gz (from -r /tmp/tmp192c1dbh (line 1))
  File was already downloaded /root/.cache/bazel/_bazel_root/dd66987607986e0bbc3aa1b8af741d50/external/rules_python~~pip~pypi_312_pygraphviz_sdist_8b0b9207/pygraphviz-1.12.tar.gz
  Installing build dependencies: started
  Installing build dependencies: finished with status 'error'
===== stdout end =====
===== stderr start =====
WARNING: 401 Error, Credentials not correct for https://REDACTED_2/simple/pygraphviz/
WARNING: 401 Error, Credentials not correct for https://REDACTED_1/simple/pygraphviz/
  error: subprocess-exited-with-error

  × pip subprocess to install build dependencies did not run successfully.
  │ exit code: 1
  ╰─> [6 lines of output]
      Looking in indexes: https://****@REDACTED_2/simple, https://****@REDACTED_1/simple
      Looking in links: .
      WARNING: 401 Error, Credentials not correct for https://REDACTED_2/simple/setuptools/
      WARNING: 401 Error, Credentials not correct for https://REDACTED_1/simple/setuptools/
      ERROR: Could not find a version that satisfies the requirement setuptools>=61.2 (from versions: none)
      ERROR: No matching distribution found for setuptools>=61.2
      [end of output]

  note: This error originates from a subprocess, and is likely not a problem with pip.
error: subprocess-exited-with-error

× pip subprocess to install build dependencies did not run successfully.
│ exit code: 1
╰─> See above for output.

note: This error originates from a subprocess, and is likely not a problem with pip.
Traceback (most recent call last):
  File "<frozen runpy>", line 198, in _run_module_as_main
  File "<frozen runpy>", line 88, in _run_code
  File "/root/.cache/bazel/_bazel_root/dd66987607986e0bbc3aa1b8af741d50/external/rules_python~/python/private/pypi/whl_installer/wheel_installer.py", line 205, in <module>
    main()
  File "/root/.cache/bazel/_bazel_root/dd66987607986e0bbc3aa1b8af741d50/external/rules_python~/python/private/pypi/whl_installer/wheel_installer.py", line 190, in main
    subprocess.run(pip_args, check=True, env=env)
  File "/root/.cache/bazel/_bazel_root/dd66987607986e0bbc3aa1b8af741d50/external/rules_python~~python~python_3_12_2_x86_64-unknown-linux-gnu/lib/python3.12/subprocess.py", line 571, in run
    raise CalledProcessError(retcode, process.args,
subprocess.CalledProcessError: Command '['/root/.cache/bazel/_bazel_root/dd66987607986e0bbc3aa1b8af741d50/external/rules_python~~python~python_3_12_2_host/python', '-m', 'pip', '--isolated', 'wheel', '--no-deps', '--index-url', 'https://oauth2accesstoken@REDACTED_2/simple', '--extra-index-url', 'https://oauth2accesstoken@REDACTED_1/simple', '--find-links', '.',
 '-r', '/tmp/tmp192c1dbh']' returned non-zero exit status 1.
===== stderr end =====

🌍 Your Environment

Operating System:

gLinux (based on Debian testing)

Output of bazel version:

$ bazel version
Bazelisk version: v1.20.0
Starting local Bazel server and connecting to it...
Build label: 7.4.1
Build target: @@//src/main/java/com/google/devtools/build/lib/bazel:BazelServer
Build time: Mon Nov 11 21:24:53 2024 (1731360293)
Build timestamp: 1731360293
Build timestamp as int: 1731360293

Rules_python version:

1.1.0

Anything else relevant?

Internal bug: b/399782261

I think I see a couple potential paths forward:

  1. support keyring when building wheels
    • At least with some private registries, they support using keyring as an auth provider. This may allow the internal pip wheel command to auth to the registry.
  2. support using the Bazel downloader, and thus the credential helper, when building wheels
    • Manually replacing pip wheel's downloading action with a separate Bazel download task might work, but only if people are using the Bazel downloader
  3. support passing a secret value (the access token) down to the pip wheel command and injecting that secret into the (extra) index url.
    • As far as I know, all package indexes support auth via URL credential injection a-la https://oauth2accesstoken:${SECRET}@private_index.com/simple. It might be possible to add an attribute to pip.parse that injects that secret.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

      0