From 0fc1bcd093d8df2ef51f64742fb22dcf6d4256f6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 28 Sep 2026 03:22:17 +0000 Subject: [PATCH 1/3] build(deps): bump idna from 3.19 to 3.20 in /tools/publish (#4170) Bumps [idna](https://github.com/kjd/idna) from 3.19 to 3.20.
Release notes

Sourced from idna's releases.

v3.20

Changelog

Sourced from idna's changelog.

3.20 (2026-09-17)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=idna&package-manager=pip&previous-version=3.19&new-version=3.20)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- tools/publish/requirements_darwin.txt | 6 +++--- tools/publish/requirements_linux.txt | 6 +++--- tools/publish/requirements_universal.txt | 6 +++--- tools/publish/requirements_windows.txt | 6 +++--- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/tools/publish/requirements_darwin.txt b/tools/publish/requirements_darwin.txt index eb97048d1b..9368554310 100644 --- a/tools/publish/requirements_darwin.txt +++ b/tools/publish/requirements_darwin.txt @@ -192,9 +192,9 @@ id==1.6.1 \ --hash=sha256:d0732d624fb46fd4e7bc4e5152f00214450953b9e772c182c1c22964def1a069 \ --hash=sha256:f5ec41ed2629a508f5d0988eda142e190c9c6da971100612c4de9ad9f9b237ca # via twine -idna==3.19 \ - --hash=sha256:5e0811a4383b21dc5838069f801c4fb62113b7447663d2530d2bd6e77b49bf15 \ - --hash=sha256:815e7be7a7806d54abb586dc943addc79e8b2ee16915059658cbeff4b1b43bf4 +idna==3.20 \ + --hash=sha256:a7db850025b95ded1eae8a46181a1a6c56c92c96f0e2b005d9ff8dc0210cab44 \ + --hash=sha256:ab7ae7122974553370f0bdb919e1a960b2cd1bc1ef0276416d896db81c14582c # via requests importlib-metadata==9.0.1 \ --hash=sha256:ab830580bc0ef3db61ce8fae716389e5462b67e033018bab6d8f80ef17172f99 \ diff --git a/tools/publish/requirements_linux.txt b/tools/publish/requirements_linux.txt index a9caddb0c0..bb67382b12 100644 --- a/tools/publish/requirements_linux.txt +++ b/tools/publish/requirements_linux.txt @@ -342,9 +342,9 @@ id==1.6.1 \ --hash=sha256:d0732d624fb46fd4e7bc4e5152f00214450953b9e772c182c1c22964def1a069 \ --hash=sha256:f5ec41ed2629a508f5d0988eda142e190c9c6da971100612c4de9ad9f9b237ca # via twine -idna==3.19 \ - --hash=sha256:5e0811a4383b21dc5838069f801c4fb62113b7447663d2530d2bd6e77b49bf15 \ - --hash=sha256:815e7be7a7806d54abb586dc943addc79e8b2ee16915059658cbeff4b1b43bf4 +idna==3.20 \ + --hash=sha256:a7db850025b95ded1eae8a46181a1a6c56c92c96f0e2b005d9ff8dc0210cab44 \ + --hash=sha256:ab7ae7122974553370f0bdb919e1a960b2cd1bc1ef0276416d896db81c14582c # via requests importlib-metadata==9.0.1 \ --hash=sha256:ab830580bc0ef3db61ce8fae716389e5462b67e033018bab6d8f80ef17172f99 \ diff --git a/tools/publish/requirements_universal.txt b/tools/publish/requirements_universal.txt index a0a28091ac..7113fad355 100644 --- a/tools/publish/requirements_universal.txt +++ b/tools/publish/requirements_universal.txt @@ -342,9 +342,9 @@ id==1.6.1 \ --hash=sha256:d0732d624fb46fd4e7bc4e5152f00214450953b9e772c182c1c22964def1a069 \ --hash=sha256:f5ec41ed2629a508f5d0988eda142e190c9c6da971100612c4de9ad9f9b237ca # via twine -idna==3.19 \ - --hash=sha256:5e0811a4383b21dc5838069f801c4fb62113b7447663d2530d2bd6e77b49bf15 \ - --hash=sha256:815e7be7a7806d54abb586dc943addc79e8b2ee16915059658cbeff4b1b43bf4 +idna==3.20 \ + --hash=sha256:a7db850025b95ded1eae8a46181a1a6c56c92c96f0e2b005d9ff8dc0210cab44 \ + --hash=sha256:ab7ae7122974553370f0bdb919e1a960b2cd1bc1ef0276416d896db81c14582c # via requests importlib-metadata==9.0.1 ; python_full_version < '3.12' and platform_machine != 'ppc64le' and platform_machine != 's390x' \ --hash=sha256:ab830580bc0ef3db61ce8fae716389e5462b67e033018bab6d8f80ef17172f99 \ diff --git a/tools/publish/requirements_windows.txt b/tools/publish/requirements_windows.txt index 95de3ce933..cc9a4d9910 100644 --- a/tools/publish/requirements_windows.txt +++ b/tools/publish/requirements_windows.txt @@ -192,9 +192,9 @@ id==1.6.1 \ --hash=sha256:d0732d624fb46fd4e7bc4e5152f00214450953b9e772c182c1c22964def1a069 \ --hash=sha256:f5ec41ed2629a508f5d0988eda142e190c9c6da971100612c4de9ad9f9b237ca # via twine -idna==3.19 \ - --hash=sha256:5e0811a4383b21dc5838069f801c4fb62113b7447663d2530d2bd6e77b49bf15 \ - --hash=sha256:815e7be7a7806d54abb586dc943addc79e8b2ee16915059658cbeff4b1b43bf4 +idna==3.20 \ + --hash=sha256:a7db850025b95ded1eae8a46181a1a6c56c92c96f0e2b005d9ff8dc0210cab44 \ + --hash=sha256:ab7ae7122974553370f0bdb919e1a960b2cd1bc1ef0276416d896db81c14582c # via requests importlib-metadata==9.0.1 \ --hash=sha256:ab830580bc0ef3db61ce8fae716389e5462b67e033018bab6d8f80ef17172f99 \ From fa8a0e8e118639449c74ef400c1696e836138b51 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 28 Sep 2026 03:22:22 +0000 Subject: [PATCH 2/3] build(deps): bump urllib3 from 2.7.0 to 2.8.0 in /tools/publish (#4169) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [urllib3](https://github.com/urllib3/urllib3) from 2.7.0 to 2.8.0.
Release notes

Sourced from urllib3's releases.

2.8.0

🚀 urllib3 is fundraising for HTTP/2 support

urllib3 is raising ~$40,000 USD to release HTTP/2 support and ensure long-term sustainable maintenance of the project. If your company or organization uses Python and would benefit from HTTP/2 support in Requests, pip, cloud SDKs, and thousands of other projects please consider contributing financially to ensure HTTP/2 support is developed sustainably and maintained for the long-haul.

Thank you for your support.

Security

Fixed the following security issues:

  • The TLS configuration for HTTPS proxies could be ignored or overridden. (High severity, GHSA-8988-9cw3-xx77)
  • HTTPResponse.stream() and read_chunked() could buffer a chunk-size line of unbounded length in memory. (High severity, GHSA-vxq7-64xx-v4gw)
  • Chunked Deflate streaming could enter an infinite loop. (Medium severity, GHSA-gh4c-6fx4-qh6g)

[!IMPORTANT] urllib3 2.8.0 fixes HTTPS proxy TLS configuration being ignored or overridden by destination settings. Configurations relying on that behavior may require changes.

Configure proxy CA certificates and client certificates in proxy_ssl_context, and proxy identity checks with proxy_assert_hostname or proxy_assert_fingerprint. Destination client certificates and identity overrides no longer apply to HTTPS forwarding proxy connections.

[!NOTE] CVE IDs had not yet been assigned to these advisories at the time of release due to a backlog at GitHub's CNA.

Deprecations & Removals

  • Deprecated using an empty collection as the Retry option allowed_methods to retry any verb. (#5044)

Features

  • Added Url.auth_decoded and Url.auth_decoded_joined convenience properties to the result of parse_url(). (#4945)
  • Added basic_auth_encoding and proxy_basic_auth_encoding parameters to urllib3.util.make_headers(). (#5092)

Bugfixes

  • Fixed response header handling to replace obsolete folded header lines (obs-fold) with spaces in accordance with RFC 9112, preventing raw CRLF sequences from appearing in header values such as Set-Cookie. (#1362)

  • Fixed usage of proxy_ssl_context with ProxyManager when use_forwarding_for_https=True. Passing ssl_context instead of proxy_ssl_context for HTTPS proxies in this configuration now emits a FutureWarning and will raise an error in v3.0. (#2577)

  • Changed behavior of the default ConnectionPool.pool initialization. LifoQueue is now resolved from the queue module after the ConnectionPool is instantiated instead of using the default cached QueueCls class property. This is done because sometimes the queue.LifoQueue is monkey-patched late in the program, such as by gevent. (#3289)

  • Raised UnrewindableBodyError instead of ValueError when retrying a request whose body had tell() but not seek(). (#3779)

  • Decoded percent-encoded SOCKS proxy credentials before authenticating with the proxy server. (#3785)

  • Fixed HTTPResponse.drain_conn() to discard unread response data in 64 KiB chunks (same as the default amt when doing HTTPResponse.stream(...)). (#5019)

  • Fixed is_ipaddress() to detect non-standard IPv4 forms accepted by socket.connect, such as hex (0x7f000001), octal (0177.0.0.1), and decimal integers (2130706433), ensuring SSL certificate verification uses the correct mode for these addresses. (#5029)

  • Fixed HTTPConnectionPool.urlopen raising a misleading FullPoolError instead of ValueError when called with an invalid timeout argument on a pool created with block=True. (#5059)

  • Fixed port-zero handling to preserve explicit :0 values instead of substituting the default ports 80 or 443 in URL parsing, pool selection, proxy configuration, connection_from_url(), and HTTP/2 request authority. (#5071, #5101)

  • Fixed a bug where PoolManager passed the assert_hostname and assert_fingerprint parameters to HTTP connection pools. (#5077)

  • Fixed HTTPConnectionPool.urlopen() and HTTP proxy forwarding to strip URL fragments from absolute request targets before sending requests. (#5079)

  • Added safeguards to the proxy tunneling code to prevent potential security issues when handling invalid characters in the proxy host and HTTP headers. This change affects users of Python 3.10, Python 3.11, and Python 3.12 when the standard library does not contain the fix; those on newer Python versions should upgrade to 3.13.14+ or 3.14.5+ to get the same security fixes. (#5091)

  • Fixed HTTPSConnection.connect() overriding ProxyConfig.ssl_context's certificate policy and proxy identity checks with the target connection's TLS settings when forwarding through an HTTPS proxy.

    HTTPSConnection no longer applies target SNI, assertions, or client credentials to forwarding proxy handshakes and continues to use its ssl_context as a fallback when an HTTPS proxy forwards an HTTP target. (#5093)

  • Fixed URL parsing to more strictly enforce RFC 3986 host syntax, rejecting invalid host input such as raw spaces and control characters, malformed percent-encodings, and percent-encoded control characters in HTTP(S) hosts and IPv6 zone identifiers, including proxy CONNECT tunnel targets. Host normalization now also follows RFC 3986 normalization rules for percent-encoded octets by decoding percent-encoded unreserved characters and uppercasing the hexadecimal digits of retained percent-encoded octets. (#5095)

... (truncated)

Changelog

Sourced from urllib3's changelog.

2.8.0 (2026-09-15)

Security

Fixed the following security issues:

  • The TLS configuration for HTTPS proxies could be ignored or overridden. (High severity, GHSA-8988-9cw3-xx77 <https://github.com/urllib3/urllib3/security/advisories/GHSA-8988-9cw3-xx77>__)
  • HTTPResponse.stream() and read_chunked() could buffer a chunk-size line of unbounded length in memory. (High severity, GHSA-vxq7-64xx-v4gw <https://github.com/urllib3/urllib3/security/advisories/GHSA-vxq7-64xx-v4gw>__)
  • Chunked Deflate streaming could enter an infinite loop. (Medium severity, GHSA-gh4c-6fx4-qh6g <https://github.com/urllib3/urllib3/security/advisories/GHSA-gh4c-6fx4-qh6g>__)

.. caution::

urllib3 2.8.0 fixes HTTPS proxy TLS configuration being
ignored or
overridden by destination settings. Configurations relying on that
behavior may require changes.

Configure proxy CA certificates and client certificates in proxy_ssl_context, and proxy identity checks with proxy_assert_hostname or proxy_assert_fingerprint. Destination client certificates and identity overrides no longer apply to HTTPS forwarding proxy connections.

Deprecations & Removals

  • Deprecated using an empty collection as the Retry option allowed_methods to retry any verb. ([#5044](https://github.com/urllib3/urllib3/issues/5044) <https://github.com/urllib3/urllib3/issues/5044>__)

Features

  • Added Url.auth_decoded and Url.auth_decoded_joined convenience properties to the result of parse_url(). ([#4945](https://github.com/urllib3/urllib3/issues/4945) <https://github.com/urllib3/urllib3/issues/4945>__)
  • Added basic_auth_encoding and proxy_basic_auth_encoding parameters to urllib3.util.make_headers(). ([#5092](https://github.com/urllib3/urllib3/issues/5092) <https://github.com/urllib3/urllib3/issues/5092>__)

Bugfixes

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=urllib3&package-manager=pip&previous-version=2.7.0&new-version=2.8.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- tools/publish/requirements_darwin.txt | 6 +++--- tools/publish/requirements_linux.txt | 6 +++--- tools/publish/requirements_universal.txt | 6 +++--- tools/publish/requirements_windows.txt | 6 +++--- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/tools/publish/requirements_darwin.txt b/tools/publish/requirements_darwin.txt index 9368554310..8504cd82de 100644 --- a/tools/publish/requirements_darwin.txt +++ b/tools/publish/requirements_darwin.txt @@ -295,9 +295,9 @@ twine==7.0.0 \ --hash=sha256:85cdb29c518efef867360ae4acd4b0dfd61c8654a22fca08e6f8539f05022177 \ --hash=sha256:b854164df26db268af05f49aa5c0344b10e27a494343ff05b1e0bad3b135f5a7 # via rules-python-publish-deps (pyproject.toml) -urllib3==2.7.0 \ - --hash=sha256:231e0ec3b63ceb14667c67be60f2f2c40a518cb38b03af60abc813da26505f4c \ - --hash=sha256:9fb4c81ebbb1ce9531cce37674bbc6f1360472bc18ca9a553ede278ef7276897 +urllib3==2.8.0 \ + --hash=sha256:0cf3cae568d36aa9576b28dfb35f11328f1cb974ca7647d9475ebb86c75ac6e3 \ + --hash=sha256:63bf2ead4c879426ebf22ef2a781eeb4aa3b4ae798a0435506f8687fd5bb9b63 # via # id # requests diff --git a/tools/publish/requirements_linux.txt b/tools/publish/requirements_linux.txt index bb67382b12..7ea7999787 100644 --- a/tools/publish/requirements_linux.txt +++ b/tools/publish/requirements_linux.txt @@ -459,9 +459,9 @@ twine==7.0.0 \ --hash=sha256:85cdb29c518efef867360ae4acd4b0dfd61c8654a22fca08e6f8539f05022177 \ --hash=sha256:b854164df26db268af05f49aa5c0344b10e27a494343ff05b1e0bad3b135f5a7 # via rules-python-publish-deps (pyproject.toml) -urllib3==2.7.0 \ - --hash=sha256:231e0ec3b63ceb14667c67be60f2f2c40a518cb38b03af60abc813da26505f4c \ - --hash=sha256:9fb4c81ebbb1ce9531cce37674bbc6f1360472bc18ca9a553ede278ef7276897 +urllib3==2.8.0 \ + --hash=sha256:0cf3cae568d36aa9576b28dfb35f11328f1cb974ca7647d9475ebb86c75ac6e3 \ + --hash=sha256:63bf2ead4c879426ebf22ef2a781eeb4aa3b4ae798a0435506f8687fd5bb9b63 # via # id # requests diff --git a/tools/publish/requirements_universal.txt b/tools/publish/requirements_universal.txt index 7113fad355..d71645e10f 100644 --- a/tools/publish/requirements_universal.txt +++ b/tools/publish/requirements_universal.txt @@ -463,9 +463,9 @@ twine==7.0.0 \ --hash=sha256:85cdb29c518efef867360ae4acd4b0dfd61c8654a22fca08e6f8539f05022177 \ --hash=sha256:b854164df26db268af05f49aa5c0344b10e27a494343ff05b1e0bad3b135f5a7 # via rules-python-publish-deps (pyproject.toml) -urllib3==2.7.0 \ - --hash=sha256:231e0ec3b63ceb14667c67be60f2f2c40a518cb38b03af60abc813da26505f4c \ - --hash=sha256:9fb4c81ebbb1ce9531cce37674bbc6f1360472bc18ca9a553ede278ef7276897 +urllib3==2.8.0 \ + --hash=sha256:0cf3cae568d36aa9576b28dfb35f11328f1cb974ca7647d9475ebb86c75ac6e3 \ + --hash=sha256:63bf2ead4c879426ebf22ef2a781eeb4aa3b4ae798a0435506f8687fd5bb9b63 # via # id # requests diff --git a/tools/publish/requirements_windows.txt b/tools/publish/requirements_windows.txt index cc9a4d9910..a3009479d8 100644 --- a/tools/publish/requirements_windows.txt +++ b/tools/publish/requirements_windows.txt @@ -299,9 +299,9 @@ twine==7.0.0 \ --hash=sha256:85cdb29c518efef867360ae4acd4b0dfd61c8654a22fca08e6f8539f05022177 \ --hash=sha256:b854164df26db268af05f49aa5c0344b10e27a494343ff05b1e0bad3b135f5a7 # via rules-python-publish-deps (pyproject.toml) -urllib3==2.7.0 \ - --hash=sha256:231e0ec3b63ceb14667c67be60f2f2c40a518cb38b03af60abc813da26505f4c \ - --hash=sha256:9fb4c81ebbb1ce9531cce37674bbc6f1360472bc18ca9a553ede278ef7276897 +urllib3==2.8.0 \ + --hash=sha256:0cf3cae568d36aa9576b28dfb35f11328f1cb974ca7647d9475ebb86c75ac6e3 \ + --hash=sha256:63bf2ead4c879426ebf22ef2a781eeb4aa3b4ae798a0435506f8687fd5bb9b63 # via # id # requests From 6efa7c319433c30eecdbfc090952d2a8369f03f4 Mon Sep 17 00:00:00 2001 From: Kristian Hartikainen Date: Mon, 28 Sep 2026 03:32:22 +0000 Subject: [PATCH 3/3] fix(uv): Reuse the `uv` cache in runnable lock targets (#4180) This PR lets `.run` targets reuse the caller's `uv` cache by moving `--no-cache` from the shared arguments to the build-action arguments. Repeated runs can reuse registry metadata, Git checkouts, and build metadata. Build actions retain cache isolation, and callers can still pass `--no-cache`. The lock tests use a sandbox-writable `UV_CACHE_DIR` and verify that `.run` creates it. Closes #4179. --------- Co-authored-by: Richard Levasseur --- news/4179.fixed.md | 5 ++ python/uv/private/lock.bzl | 14 ++++- tests/integration/uv_lock/BUILD.bazel | 7 +++ tests/integration/uv_lock_test.py | 49 +++++++++++++++ tests/uv/lock/BUILD.bazel | 3 + tests/uv/lock/cache_tests.bzl | 90 +++++++++++++++++++++++++++ tests/uv/lock/lock_run_test.py | 3 +- 7 files changed, 168 insertions(+), 3 deletions(-) create mode 100644 news/4179.fixed.md create mode 100644 tests/uv/lock/cache_tests.bzl diff --git a/news/4179.fixed.md b/news/4179.fixed.md new file mode 100644 index 0000000000..3225cfb421 --- /dev/null +++ b/news/4179.fixed.md @@ -0,0 +1,5 @@ +(uv) The {obj}`lock` macro's `.run` target uses the `uv` cache and honors +`UV_CACHE_DIR` and `UV_NO_CACHE`. Pass `--refresh` to refresh cached data or +`--no-cache` to disable caching. Lock build actions, including those used by +`.update`, disable the `uv` cache. +([#4179](https://github.com/bazel-contrib/rules_python/issues/4179)) diff --git a/python/uv/private/lock.bzl b/python/uv/private/lock.bzl index 33c301d49c..3d39788d9d 100644 --- a/python/uv/private/lock.bzl +++ b/python/uv/private/lock.bzl @@ -143,7 +143,9 @@ def _common_lock(ctx, locker): srcs, output_filename, mnemonic, progress_message = locker(args, output) args.add("--no-python-downloads") - args.add("--no-cache") + + # Build actions must not depend on the host cache but `.run` may reuse it. + args.add_run_shell("--no-cache") project = ctx.attr.project if not project: @@ -607,7 +609,11 @@ def lock( to the same command that would be run in the `name` action. This will update the source copy of the requirements file. You can customize the args via the command line, but it requires being able to run `uv` (and - possibly `python`) directly on your host. + possibly `python`) directly on your host. This target uses the `uv` + cache and inherits its cache settings from the environment, including + `UV_CACHE_DIR` and `UV_NO_CACHE`. Pass `--refresh` to refresh cached + data or `--no-cache` to disable caching. Build actions, including those + used by `name.update`, disable the `uv` cache. - `name.update`: a target that can be run to update the source-tree version of the requirements lock file. The output can be fed to the {obj}`pip.parse` bzlmod extension tag class. Note, you can use @@ -622,6 +628,10 @@ def lock( All of the targets have `manual` tags as locking results cannot be cached. ::: + :::{versionchanged} VERSION_NEXT_PATCH + The `name.run` target uses the `uv` cache by default. + ::: + Args: name: {type}`str` The prefix of all targets created by this macro. srcs: {type}`list[Label]` The sources that will be used. Add all of the diff --git a/tests/integration/uv_lock/BUILD.bazel b/tests/integration/uv_lock/BUILD.bazel index 01c90d356b..27ee012709 100644 --- a/tests/integration/uv_lock/BUILD.bazel +++ b/tests/integration/uv_lock/BUILD.bazel @@ -24,3 +24,10 @@ diff_test( file1 = ":requirements", file2 = ":requirements.txt", ) + +lock( + name = "project_lock", + srcs = ["pyproject.toml"], + out = "uv.lock", + tags = ["no-remote-exec"], +) diff --git a/tests/integration/uv_lock_test.py b/tests/integration/uv_lock_test.py index 8efd3cb84f..8ac95ca9f1 100644 --- a/tests/integration/uv_lock_test.py +++ b/tests/integration/uv_lock_test.py @@ -185,6 +185,55 @@ def _assert_lock_file(self, result): self.assertIn("my-local-pkg", contents) self.assertIn("--hash=sha256:", contents) + def _run_cached_lock(self, target, *args, check=True): + return self.run_bazel( + "run", + target, + "--", + "--default-index=" + self.server_url + "/simple/", + *args, + check=check, + ) + + def test_run_reuses_cache_offline(self): + for target, filename in ( + ("//:requirements.run", "requirements.txt"), + ( + "//:project_lock.run", + "bazel-bin/project_lock.run.runfiles/_main/uv.lock", + ), + ): + with self.subTest(target=target): + self.bazel_env["UV_CACHE_DIR"] = str( + self.test_tmp_dir / (Path(filename).name + ".cache") + ) + output = self.repo_root / filename + + output.unlink(missing_ok=True) + cold = self._run_cached_lock(target, "--offline", check=False) + self.assertNotEqual(cold.exit_code, 0, cold.describe()) + + self._run_cached_lock(target) + expected = output.read_text() + self.assertIn("my-local-pkg", expected) + + output.unlink() + self._run_cached_lock(target, "--offline") + self.assertEqual(expected, output.read_text()) + + output.unlink() + bypass = self._run_cached_lock( + target, "--offline", "--no-cache", check=False + ) + self.assertNotEqual(bypass.exit_code, 0, bypass.describe()) + + self.bazel_env["UV_NO_CACHE"] = "true" + try: + bypass_env = self._run_cached_lock(target, "--offline", check=False) + self.assertNotEqual(bypass_env.exit_code, 0, bypass_env.describe()) + finally: + del self.bazel_env["UV_NO_CACHE"] + def test_lock_update_with_custom_index(self): self._assert_server_requires_auth() self._assert_simple_api_sha256() diff --git a/tests/uv/lock/BUILD.bazel b/tests/uv/lock/BUILD.bazel index 60d680bde8..156b9dbe6f 100644 --- a/tests/uv/lock/BUILD.bazel +++ b/tests/uv/lock/BUILD.bazel @@ -1,3 +1,4 @@ +load(":cache_tests.bzl", "cache_test_suite") load(":lock_tests.bzl", "lock_test_suite") load(":uv_lock_to_requirements_tests.bzl", "uv_lock_to_requirements_test_suite") @@ -13,3 +14,5 @@ lock_test_suite( uv_lock_to_requirements_test_suite( name = "uv_lock_to_requirements_tests", ) + +cache_test_suite(name = "cache_tests") diff --git a/tests/uv/lock/cache_tests.bzl b/tests/uv/lock/cache_tests.bzl new file mode 100644 index 0000000000..a1e528d5dc --- /dev/null +++ b/tests/uv/lock/cache_tests.bzl @@ -0,0 +1,90 @@ +"""Cache policy tests for build actions and runnable lock targets.""" + +load("@rules_testing//lib:analysis_test.bzl", "analysis_test") +load("@rules_testing//lib:test_suite.bzl", "test_suite") +load("//python/uv:lock.bzl", "lock") +load("//tests/support/platforms:platforms.bzl", "platform_targets") + +def _cache_tests(name, is_windows, extension): + if is_windows: + platform = platform_targets.WINDOWS_X86_64 + else: + platform = platform_targets.LINUX_X86_64 + config_settings = { + "//command_line_option:platforms": [platform], + } + for no_cache in [False, True]: + subject = name + ("_no_cache" if no_cache else "_default") + lock( + name = subject, + srcs = ["testdata/pyproject.toml"], + args = ["--no-cache"] if no_cache else [], + out = subject + extension, + ) + analysis_test( + name = subject + "_build_test", + impl = _test_windows_build_impl if is_windows else _test_build_impl, + target = subject, + config_settings = config_settings, + ) + analysis_test( + name = subject + "_run_test", + impl = _test_no_cache_run_impl if no_cache else _test_run_impl, + target = subject + ".run", + config_settings = config_settings, + ) + native.test_suite( + name = name, + tests = [ + name + mode + kind + for mode in ["_default", "_no_cache"] + for kind in ["_build_test", "_run_test"] + ], + ) + +def _test_build_impl(env, target): + output = target[DefaultInfo].files.to_list()[0] + env.expect.that_target(target).action_generating( + output.short_path, + ).argv().contains("--no-cache") + +def _test_windows_build_impl(env, target): + env.expect.that_target(target).action_generating( + "{package}/{name}_lock.bat", + ).content().contains("--no-cache") + +def _run_script(env, target): + executable = target[DefaultInfo].files_to_run.executable + return env.expect.that_target(target).action_generating( + executable.short_path, + ).content() + +def _test_run_impl(env, target): + _run_script(env, target).split("--no-cache").has_size(1) + +def _test_no_cache_run_impl(env, target): + _run_script(env, target).contains("--no-cache") + +def _test_requirements_cache(name): + _cache_tests(name, is_windows = False, extension = ".txt") + +def _test_uv_lock_cache(name): + _cache_tests(name, is_windows = False, extension = ".lock") + +def _test_windows_requirements_cache(name): + _cache_tests(name, is_windows = True, extension = ".txt") + +def _test_windows_uv_lock_cache(name): + _cache_tests(name, is_windows = True, extension = ".lock") + +def cache_test_suite(name): + """Check cache defaults and explicit `--no-cache` for both lock formats.""" + test_suite( + name = name, + tests = [ + _test_requirements_cache, + _test_uv_lock_cache, + _test_windows_requirements_cache, + _test_windows_uv_lock_cache, + ], + ) diff --git a/tests/uv/lock/lock_run_test.py b/tests/uv/lock/lock_run_test.py index 139d8bb2c8..d2d18e69f7 100644 --- a/tests/uv/lock/lock_run_test.py +++ b/tests/uv/lock/lock_run_test.py @@ -51,6 +51,7 @@ class LockTests(unittest.TestCase): def _subprocess_env(self, workspace_dir: Path) -> dict[str, str]: env = { "BUILD_WORKSPACE_DIRECTORY": str(workspace_dir), + "UV_CACHE_DIR": str(workspace_dir / "uv-cache"), } # Inherit specific env vars needed for finding runfiles on Windows for key in ( @@ -249,7 +250,7 @@ def test_requirements_run_script_has_expected_args(self): self.assertIn("--generate-hashes", content) self.assertIn("--no-strip-extras", content) self.assertIn("--no-python-downloads", content) - self.assertIn("--no-cache", content) + self.assertNotIn("--no-cache", content) self.assertIn("--no-progress", content) self.assertIn("--quiet", content) self.assertIn("--output-file", content)