Skip to content

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

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

      , 'i'); if (__m === '*' || __re.test(location.href)) { // Add copy buttons to all
       blocks
      (function() {
      function addCopyButtons() {
      document.querySelectorAll('pre code').forEach(function(codeBlock) {
      if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;
      codeBlock.parentElement.setAttribute('data-copy-added', 'true');
      var btn = document.createElement('button');
      btn.textContent = 'Copy';
      btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';
      btn.onmouseover = function() { this.style.opacity = '1'; };
      btn.onmouseout = function() { this.style.opacity = '0.7'; };
      btn.onclick = function() {
      navigator.clipboard.writeText(codeBlock.textContent).then(function() {
      btn.textContent = 'Copied!';
      setTimeout(function() { btn.textContent = 'Copy'; }, 1500);
      });
      };
      codeBlock.parentElement.style.position = 'relative';
      codeBlock.parentElement.appendChild(btn);
      });
      }
      addCopyButtons();
      // Re-run on dynamic content
      var observer = new MutationObserver(addCopyButtons);
      observer.observe(document.body, { childList: true, subtree: true });
      })();
      }
      } catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
      })();
      (function(){
      try {
      var __m = "github.com";
      var __re = new RegExp('^' + "github\\.com" + '
      `whl_library.BuildWheelFromSource` uses pip to download dependencies and does not inject credential helper information. · Issue #2640 · bazel-contrib/rules_python · GitHub
      Skip to content

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

      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

          , 'i'); if (__m === '*' || __re.test(location.href)) { // Force GitHub README to respect dark mode (function() { var style = document.createElement('style'); style.textContent = ' .markdown-body { color-scheme: dark light; } .markdown-body pre { background: #161b22 !important; } .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; } .markdown-body table th, .markdown-body table td { border-color: #30363d !important; } .markdown-body img { background: #0d1117; } .markdown-body blockquote { border-left-color: #8b949e; } .markdown-body hr { border-color: #30363d; } '; document.head.appendChild(style); })(); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' `whl_library.BuildWheelFromSource` uses pip to download dependencies and does not inject credential helper information. · Issue #2640 · bazel-contrib/rules_python · GitHub
          Skip to content

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

          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

              , 'i'); if (__m === '*' || __re.test(location.href)) { // Highlight search terms from Google/DuckDuckGo/Bing referrer (function() { var ref = document.referrer; var terms = []; if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) { var url = new URL(ref); var q = url.searchParams.get('q') || url.searchParams.get('p'); if (q) { terms = q.split(/\s+/).filter(function(t) { return t.length > 2; }); } } if (terms.length === 0) return; var style = document.createElement('style'); style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }'; document.head.appendChild(style); function highlight(node) { if (node.nodeType === 3) { // text node var text = node.textContent; var found = false; terms.forEach(function(term) { var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\]\\]/g, '\\') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' `whl_library.BuildWheelFromSource` uses pip to download dependencies and does not inject credential helper information. · Issue #2640 · bazel-contrib/rules_python · GitHub
              Skip to content

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

              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

                  , 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ' `whl_library.BuildWheelFromSource` uses pip to download dependencies and does not inject credential helper information. · Issue #2640 · bazel-contrib/rules_python · GitHub
                  Skip to content

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

                  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

                      , 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' `whl_library.BuildWheelFromSource` uses pip to download dependencies and does not inject credential helper information. · Issue #2640 · bazel-contrib/rules_python · GitHub
                      Skip to content

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

                      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

                          , 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' `whl_library.BuildWheelFromSource` uses pip to download dependencies and does not inject credential helper information. · Issue #2640 · bazel-contrib/rules_python · GitHub
                          Skip to content

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

                          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

                              , 'i'); if (__m === '*' || __re.test(location.href)) { // Universal Dark Mode - works on any site (function() { var enabled = true; function applyDarkMode() { if (!enabled) return; // Create style element if it doesn't exist var style = document.getElementById('universal-dark-mode-style'); if (!style) { style = document.createElement('style'); style.id = 'universal-dark-mode-style'; document.head.appendChild(style); } // Dark mode CSS - inverts colors but preserves images/video style.textContent = ' /* Invert everything except media */ html { filter: invert(1) hue-rotate(180deg) !important; background: #1a1a2e !important; } /* Restore images, videos, iframes, canvas */ img, video, iframe, canvas, svg, picture, [style*="background-image"] { filter: invert(1) hue-rotate(180deg) !important; } /* Preserve specific elements that should not be inverted */ .no-dark-mode, .no-dark-mode *, [data-theme="light"], [data-theme="light"], .ace_editor, .ace_editor *, .CodeMirror, .CodeMirror *, .monaco-editor, .monaco-editor *, .markdown-body pre, .markdown-body pre *, .highlight, .highlight *, pre code, pre code * { filter: none !important; } /* Fix common UI elements */ .modal, .popup, .dropdown-menu, .tooltip, .popover { filter: invert(1) hue-rotate(180deg) !important; background: #2d2d44 !important; border-color: #444 !important; } /* Scrollbars */ ::-webkit-scrollbar { background: #1a1a2e !important; } ::-webkit-scrollbar-thumb { background: #444 !important; } ::-webkit-scrollbar-thumb:hover { background: #555 !important; } /* Selection */ ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; } ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; } '; } function removeDarkMode() { var style = document.getElementById('universal-dark-mode-style'); if (style) style.remove(); } // Toggle with Alt+Shift+D document.addEventListener('keydown', function(e) { if (e.altKey && e.shiftKey && e.key === 'D') { e.preventDefault(); enabled = !enabled; if (enabled) { applyDarkMode(); console.log('[Universal Dark Mode] Enabled'); } else { removeDarkMode(); console.log('[Universal Dark Mode] Disabled'); } } }); // Apply on load applyDarkMode(); // Re-apply on dynamic content var observer = new MutationObserver(function(mutations) { if (enabled && !document.getElementById('universal-dark-mode-style')) { applyDarkMode(); } }); observer.observe(document.head, { childList: true }); console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle'); })(); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })(); `whl_library.BuildWheelFromSource` uses pip to download dependencies and does not inject credential helper information. · Issue #2640 · bazel-contrib/rules_python · GitHub
                              Skip to content

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

                              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