Change prune-cache default to false (#967)
test / test-specific-version (map[expected-version:0.4.25 resolution-strategy:lowest version-input:>=0.4.25,<0.5]) (push) Failing after 37s
test / test-specific-version (map[expected-version:0.3.5 version-input:0.3]) (push) Failing after 37s
test / test-specific-version (map[expected-version:0.4.25 resolution-strategy:lowest version-input:>=0.4.25]) (push) Failing after 38s
test / test-specific-version (map[expected-version:0.4.30 version-input:>=0.4.25,<0.5]) (push) Failing after 40s
test / test-specific-version (map[expected-version:0.3.5 version-input:0.3.x]) (push) Failing after 40s
test / test-from-working-directory-version (map[expected-version:0.5.15 working-directory:__tests__/fixtures/uv-toml-project]) (push) Failing after 22s
test / test-uvx (push) Failing after 39s
test / test-activate-environment (ubuntu-latest) (push) Failing after 33s
test / test-setup-cache (auto, ubuntu-latest) (push) Failing after 30s
test / test-restore-cache-requirements-txt (push) Has been skipped
test / test-restore-cache-dependency-glob (push) Has been skipped
test / test-cache-key-os-version (ubuntu-22.04, ubuntu-22.04) (push) Failing after 48s
test / test-restore-cache-save-cache-false (push) Has been skipped
test / test-cache-local-cache-disabled-but-explicit-path (push) Failing after 36s
test / test-custom-manifest-file (push) Failing after 38s
test / test-absolute-path (push) Failing after 38s
test / test-default-version (ubuntu-latest) (push) Failing after 38s
test / test-latest-version (latest) (push) Failing after 40s
test / test-specific-version (map[expected-version:0.1.45 resolution-strategy:highest version-input:>=0.1,<0.2]) (push) Failing after 52s
test / test-specific-version (map[expected-version:0.3.2 version-input:0.3.2]) (push) Failing after 53s
test / test-specific-version (map[expected-version:0.1.0 resolution-strategy:lowest version-input:>=0.1.0,<0.2]) (push) Failing after 53s
test / test-version-file-version (map[expected-version:0.5.15 version-file:__tests__/fixtures/.tool-versions]) (push) Failing after 28s
test / test-malformed-pyproject-file-fallback (push) Failing after 34s
test / test-checksum (map[checksum:4d9279ad5ca596b1e2d703901d508430eb07564dc4d8837de9e2fca9c90f8ecd os:ubuntu-latest]) (push) Failing after 35s
test / test-with-explicit-token (push) Failing after 39s
test / test-tool-install (ubuntu-latest) (push) Failing after 37s
test / test-musl (push) Failing after 26s
test / test-debian-unstable (push) Failing after 31s
test / test-activate-environment-custom-path (ubuntu-latest) (push) Failing after 35s
test / test-python-version (ubuntu-latest) (push) Failing after 36s
test / test-specific-version (map[expected-version:0.3.0 version-input:0.3.0]) (push) Failing after 43s
test / test-uv-no-modify-path (push) Failing after 46s
test / test-latest-version (>=0.8) (push) Failing after 54s
test / test-from-working-directory-version (map[expected-version:0.5.14 working-directory:__tests__/fixtures/pyproject-toml-project]) (push) Failing after 55s
test / test-version-file-version (map[expected-version:0.6.17 version-file:__tests__/fixtures/uv-in-requirements-txt-project/requirements.txt]) (push) Failing after 34s
test / test-version-file-version (map[expected-version:0.8.3 version-file:__tests__/fixtures/uv-in-requirements-hash-txt-project/requirements.txt]) (push) Failing after 34s
test / test-setup-cache (true, ubuntu-latest) (push) Failing after 28s
test / test-setup-cache-requirements-txt (push) Failing after 28s
test / test-setup-cache-save-cache-false (push) Failing after 35s
test / test-restore-cache-restore-cache-false (push) Has been skipped
test / test-setup-cache-restore-cache-false (push) Failing after 35s
test / test-cache-prune-force (push) Failing after 32s
test / test-activate-environment-no-project (push) Failing after 37s
test / test-setup-cache (false, ubuntu-latest) (push) Failing after 22s
test / lint (push) Failing after 1m50s
CodeQL / Analyze (TypeScript) (push) Failing after 1m51s
test / test-setup-cache-dependency-glob (push) Failing after 32s
test / test-cache-local (map[expected-cache-dir:/home/runner/work/_temp/setup-uv-cache os:ubuntu-latest]) (push) Failing after 35s
test / test-cache-local-cache-disabled (push) Failing after 35s
test / test-no-python-version (push) Failing after 40s
test / test-download-from-astral-mirror-false (push) Failing after 38s
test / test-cache-python-missing-managed-install-dir (push) Failing after 29s
test / test-cache-dir-from-file (push) Failing after 38s
test / test-python-install-dir (map[expected-python-dir:/home/runner/work/_temp/uv-python-dir os:ubuntu-latest]) (push) Failing after 30s
test / test-act (push) Failing after 29s
test / test-relative-path (push) Failing after 41s
test / test-cache-python-installs (push) Failing after 35s
test / test-restore-python-installs (push) Has been skipped
test / validate-typings (push) Successful in 43s
test / test-default-version (macos-14) (push) Has been cancelled
test / test-default-version (macos-latest) (push) Has been cancelled
test / test-default-version (windows-latest) (push) Has been cancelled
test / test-checksum (map[checksum:a70cbfbf3bb5c08b2f84963b4f12c94e08fbb2468ba418a3bfe1066fbe9e7218 os:macos-latest]) (push) Has been cancelled
test / test-tool-install (macos-14) (push) Has been cancelled
test / test-tool-install (macos-latest) (push) Has been cancelled
test / test-tool-install (windows-latest) (push) Has been cancelled
test / test-python-version (macos-latest) (push) Has been cancelled
test / test-python-version (windows-latest) (push) Has been cancelled
test / test-activate-environment (macos-latest) (push) Has been cancelled
test / test-activate-environment (windows-latest) (push) Has been cancelled
test / test-activate-environment-custom-path (macos-latest) (push) Has been cancelled
test / test-activate-environment-custom-path (windows-latest) (push) Has been cancelled
test / test-cache-key-os-version (macos-14, macos-14) (push) Has been cancelled
test / test-cache-key-os-version (macos-15, macos-15) (push) Has been cancelled
test / test-cache-key-os-version (ubuntu-24.04, ubuntu-24.04) (push) Has been cancelled
test / test-cache-key-os-version (windows-2022, windows-2022) (push) Has been cancelled
test / test-cache-key-os-version (windows-2025, windows-2025) (push) Has been cancelled
test / test-setup-cache (auto, windows-latest) (push) Has been cancelled
test / test-setup-cache (false, windows-latest) (push) Has been cancelled
test / test-setup-cache (true, windows-latest) (push) Has been cancelled
test / test-restore-cache (auto, ubuntu-latest) (push) Has been cancelled
test / test-restore-cache (auto, windows-latest) (push) Has been cancelled
test / test-restore-cache (false, ubuntu-latest) (push) Has been cancelled
test / test-restore-cache (false, windows-latest) (push) Has been cancelled
test / test-restore-cache (true, ubuntu-latest) (push) Has been cancelled
test / test-restore-cache (true, windows-latest) (push) Has been cancelled
test / test-cache-local (map[expected-cache-dir:D:\a\_temp\setup-uv-cache os:windows-latest]) (push) Has been cancelled
test / test-python-install-dir (map[expected-python-dir:D:\a\_temp\uv-python-dir os:windows-latest]) (push) Has been cancelled
test / all-tests-passed (push) Has been cancelled
Release Drafter / ✏️ Draft release (push) Has been cancelled

## Summary

This changes the default for `prune-cache` from `true` to `false`,
motivated by [#745](https://github.com/astral-sh/setup-uv/issues/745).
Users that want the existing behavior can continue to set `prune-cache:
true` explicitly.

Some history: I originally added [`uv cache prune
--ci`](https://github.com/astral-sh/uv/pull/5391) after looking at a
workload where the uv cache was ~2.2 GB, almost entirely due to the
enormous pre-built `torch` and `nvidia_cudnn_cu12` wheels ([original
analysis](https://github.com/actions/setup-python/issues/822#issuecomment-2248728264)).
Persisting and restoring thousands of extracted files through the GitHub
Actions cache could be slower than downloading the wheels again. In
contrast, wheels built from source can be very expensive to recreate.
The intent was to remove pre-built wheels while retaining locally-built
wheels.

`setup-uv` subsequently made pruning configurable, but defaulted
`prune-cache` to `true`; it also later enabled caching by default on
GitHub-hosted runners. As a result, the default configuration repeatedly
downloads pre-built wheels from PyPI even on a cache hit. That tradeoff
has become more important as uv adoption has grown: [the PyPI analysis
in
#745](https://github.com/astral-sh/setup-uv/issues/745#issuecomment-3867334064)
estimates that uv accounts for roughly half of reported CI downloads
from PyPI, and roughly 65-75% for `boto3`.

I ran the comparison across a few different workloads:

| Workload | PR | Packages | Cache: keep / prune / prune-ci | Warm
restore+sync: keep / prune / prune-ci | Downloads: prune / prune-ci |
|---|---:|---:|---:|---:|---:|
| Tiny | [#1](https://github.com/astral-sh/setup-uv-benchmarks/pull/1) |
19 | 6 / 6 / 2 MB | 0.3-0.4 / 0.3 / 0.4-0.5 s | 0 / 2 |
| Web | [#2](https://github.com/astral-sh/setup-uv-benchmarks/pull/2) |
65 | 43 / 43 / 7 MB | 0.6-1.0 / 0.5-0.6 / 1.5-1.7 s | 0 / 6 |
| Scientific |
[#3](https://github.com/astral-sh/setup-uv-benchmarks/pull/3) | 118 |
586 / 586 / 8 MB | 8.2-16.0 / 7.0-8.2 / 8.9-12.1 s | 0 / 19 |
| PySpark |
[#4](https://github.com/astral-sh/setup-uv-benchmarks/pull/4) | 19 |
1820 / 1820 / 436 MB | 9.9-21.1 / 10.5-11.0 / 5.0-7.0 s | 0 / 4 |
| CPU PyTorch |
[#5](https://github.com/astral-sh/setup-uv-benchmarks/pull/5) | 14 | 182
/ 182 / 1 MB | 3.0-6.0 / 3.6-4.0 / 5.7-6.4 s | 0 / 6 |
| CPU-PyTorch ML |
[#6](https://github.com/astral-sh/setup-uv-benchmarks/pull/6) | 137 |
346 / 346 / 10 MB | 7.4-18.0 / 8.8-8.9 / 9.7-11.9 s | 0 / 20 |
| CUDA PyTorch |
[#7](https://github.com/astral-sh/setup-uv-benchmarks/pull/7) | 201 |
2316 / 2315 / 16 MB | 30.2-67.9 / 31.0-63.6 / 33.3-36.7 s | 0 / 40 |

The CUDA workload intentionally reproduces the original `torch==2.1.1`
example. Keeping wheels again produces a ~2.3 GB Actions cache. Across
nine warm runs, restoring that cache ranged from slightly faster than
re-downloading to roughly twice as slow; pruning consistently
re-downloaded 40 distributions in ~33-37 seconds ([original
runs](https://github.com/astral-sh/setup-uv-benchmarks/actions/runs/29750292738),
[additional
runs](https://github.com/astral-sh/setup-uv-benchmarks/actions/runs/29761705492)).

I also tried running `uv cache prune --force` without `--ci` across
every workload, to see if it provided a useful middle ground. It did not
meaningfully reduce any of the caches: plain prune took 11-21 ms and
left the extracted cache and file count unchanged, including PySpark. On
these fresh caches, there are no dangling entries to remove; without
`--ci`, the pre-built wheels and unpacked source/build artifacts are
retained. The per-workload runs are linked in the table above.

So the original motivation still holds for very large CUDA or
source-heavy workloads, but it is not representative of the common case.
For smaller workloads, keeping pre-built wheels is generally faster and
avoids repeated PyPI traffic. This changes the default accordingly,
while retaining `prune-cache: true` as an opt-in for workloads where the
smaller cache is worthwhile.

Closes https://github.com/astral-sh/setup-uv/issues/745.
This commit is contained in:
Charlie Marsh
2026-07-20 14:25:19 -04:00
committed by GitHub
parent 71966eff34
commit 47a7f4fb2e
5 changed files with 18 additions and 19 deletions
+1 -1
View File
@@ -100,7 +100,7 @@ Have a look under [Advanced Configuration](#advanced-configuration) for detailed
cache-local-path: "" cache-local-path: ""
# Prune cache before saving # Prune cache before saving
prune-cache: "true" prune-cache: "false"
# Upload managed Python installations to the GitHub Actions cache # Upload managed Python installations to the GitHub Actions cache
cache-python: "false" cache-python: "false"
+2 -2
View File
@@ -62,13 +62,13 @@ describe("restoreCache", () => {
expect(cacheKey).toContain("-tests-3.10%2C3.11"); expect(cacheKey).toContain("-tests-3.10%2C3.11");
}); });
it("keeps cache keys unchanged for exact Python versions and simple suffixes", async () => { it("uses an unpruned cache key by default", async () => {
const inputs = createSetupInputs({ cacheSuffix: "tests-3.11" }); const inputs = createSetupInputs({ cacheSuffix: "tests-3.11" });
await restoreCache(inputs, "3.11"); await restoreCache(inputs, "3.11");
expect(cacheKeyOutput()).toBe( expect(cacheKeyOutput()).toBe(
"setup-uv-2-x86_64-unknown-linux-gnu-ubuntu-24.04-3.11-pruned-dependencyhash-tests-3.11", "setup-uv-2-x86_64-unknown-linux-gnu-ubuntu-24.04-3.11-dependencyhash-tests-3.11",
); );
}); });
}); });
+1 -1
View File
@@ -20,7 +20,7 @@ export function createSetupInputs(
ignoreEmptyWorkdir: false, ignoreEmptyWorkdir: false,
ignoreNothingToCache: false, ignoreNothingToCache: false,
noProject: false, noProject: false,
pruneCache: true, pruneCache: false,
pythonDir: "/tmp/uv-python-dir", pythonDir: "/tmp/uv-python-dir",
pythonVersion: "", pythonVersion: "",
quiet: false, quiet: false,
+1 -1
View File
@@ -61,7 +61,7 @@ inputs:
default: "" default: ""
prune-cache: prune-cache:
description: "Prune cache before saving." description: "Prune cache before saving."
default: "true" default: "false"
cache-python: cache-python:
description: "Upload managed Python installations to the Github Actions cache." description: "Upload managed Python installations to the Github Actions cache."
default: "false" default: "false"
+13 -14
View File
@@ -33,8 +33,8 @@ The computed cache key is available as the `cache-key` output:
## Enable caching ## Enable caching
> [!NOTE] > [!NOTE]
> The cache is pruned before it is uploaded to the GitHub Actions cache. This can lead to > The entire uv cache is uploaded to the GitHub Actions cache by default. To reduce the cache size,
> a small or empty cache. See [Disable cache pruning](#disable-cache-pruning) for more details. > see [Enable cache pruning](#enable-cache-pruning).
If you enable caching, the [uv cache](https://docs.astral.sh/uv/concepts/cache/) will be uploaded to If you enable caching, the [uv cache](https://docs.astral.sh/uv/concepts/cache/) will be uploaded to
the GitHub Actions cache. This can speed up runs that reuse the cache by several minutes. the GitHub Actions cache. This can speed up runs that reuse the cache by several minutes.
@@ -173,30 +173,29 @@ It defaults to `setup-uv-cache` in the `TMP` dir, `D:\a\_temp\setup-uv-cache` on
cache-local-path: "/path/to/cache" cache-local-path: "/path/to/cache"
``` ```
## Disable cache pruning ## Enable cache pruning
By default, the uv cache is pruned after every run, removing pre-built wheels, but retaining any By default, the entire uv cache is persisted across runs. On GitHub-hosted runners, it's typically
wheels that were built from source. On GitHub-hosted runners, it's typically faster to omit those faster to prune the cache before saving it, removing pre-built wheels, but retaining any wheels that
pre-built wheels from the cache (and instead re-download them from the registry on each run). were built from source. The pre-built wheels are then re-downloaded from the registry on each run.
However, on self-hosted or local runners, preserving the cache may be more efficient. See See the [documentation](https://docs.astral.sh/uv/concepts/cache/#caching-in-continuous-integration)
the [documentation](https://docs.astral.sh/uv/concepts/cache/#caching-in-continuous-integration) for for more information.
more information.
If you want to persist the entire cache across runs, disable cache pruning with the `prune-cache` If you want to prune the cache before saving it, enable cache pruning with the `prune-cache` input.
input.
```yaml ```yaml
- name: Don't prune the cache before saving it - name: Prune the cache before saving it
uses: astral-sh/setup-uv@11f9893b081a58869d3b5fccaea48c9e9e46f990 # v8.3.2 uses: astral-sh/setup-uv@11f9893b081a58869d3b5fccaea48c9e9e46f990 # v8.3.2
with: with:
enable-cache: true enable-cache: true
prune-cache: false prune-cache: true
``` ```
## Cache Python installs ## Cache Python installs
By default, the Python install dir (`uv python dir` / `UV_PYTHON_INSTALL_DIR`) is not cached, By default, the Python install dir (`uv python dir` / `UV_PYTHON_INSTALL_DIR`) is not cached,
for the same reason that the dependency cache is pruned. for the same reason that pruning the dependency cache can improve performance on GitHub-hosted
runners.
If you want to cache Python installs along with your dependencies, set the `cache-python` input to `true`. If you want to cache Python installs along with your dependencies, set the `cache-python` input to `true`.
Note that this only caches Python versions that uv actually installs into `UV_PYTHON_INSTALL_DIR` Note that this only caches Python versions that uv actually installs into `UV_PYTHON_INSTALL_DIR`