Files
setup-uv/docs/caching.md
Charlie Marsh 47a7f4fb2e Change prune-cache default to false (#967)
## 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.
2026-07-20 20:25:19 +02:00

7.6 KiB

Caching

This document covers all caching-related configuration options for setup-uv.

Cache key

The cache key is automatically generated based on:

  • Architecture: CPU architecture (e.g., x86_64, aarch64)
  • Platform: OS platform type (e.g., unknown-linux-gnu, unknown-linux-musl, apple-darwin, pc-windows-msvc)
  • OS version: OS name and version (e.g., ubuntu-22.04, macos-14, windows-2022)
  • Python version: The Python version in use
  • Cache options: Whether pruning and Python caching are enabled
  • Dependency hash: Hash of files matching cache-dependency-glob
  • Suffix: Optional cache-suffix if provided

Including the OS version ensures that caches are not shared between different OS versions, preventing binary incompatibility issues when runner images change.

The computed cache key is available as the cache-key output:

- name: Setup uv
  id: setup-uv
  uses: astral-sh/setup-uv@11f9893b081a58869d3b5fccaea48c9e9e46f990 # v8.3.2
  with:
    enable-cache: true
- name: Print cache key
  run: echo "Cache key: ${{ steps.setup-uv.outputs.cache-key }}"

Enable caching

Note

The entire uv cache is uploaded to the GitHub Actions cache by default. To reduce the cache size, see Enable cache pruning.

If you enable caching, the uv cache will be uploaded to the GitHub Actions cache. This can speed up runs that reuse the cache by several minutes. Caching is enabled by default on GitHub-hosted runners.

Tip

On self-hosted runners this is usually not needed since the cache generated by uv on the runner's filesystem is not removed after a run. For more details see Local cache path.

You can optionally define a custom cache key suffix.

- name: Enable caching and define a custom cache key suffix
  id: setup-uv
  uses: astral-sh/setup-uv@11f9893b081a58869d3b5fccaea48c9e9e46f990 # v8.3.2
  with:
    enable-cache: true
    cache-suffix: "optional-suffix"

When the cache was successfully restored, the output cache-hit will be set to true and you can use it in subsequent steps. For example, to use the cache in the above case:

- name: Do something if the cache was restored
  if: steps.setup-uv.outputs.cache-hit == 'true'
  run: echo "Cache was restored"

Cache dependency glob

If you want to control when the GitHub Actions cache is invalidated, specify a glob pattern with the cache-dependency-glob input. The GitHub Actions cache will be invalidated if any file matching the glob pattern changes. If you use relative paths, they are relative to the working directory.

Note

You can look up supported patterns here

The default is

cache-dependency-glob: |
  **/*requirements*.txt
  **/*requirements*.in
  **/*constraints*.txt
  **/*constraints*.in
  **/pyproject.toml
  **/uv.lock
  **/*.py.lock
- name: Define a cache dependency glob
  uses: astral-sh/setup-uv@11f9893b081a58869d3b5fccaea48c9e9e46f990 # v8.3.2
  with:
    enable-cache: true
    cache-dependency-glob: "**/pyproject.toml"
- name: Define a list of cache dependency globs
  uses: astral-sh/setup-uv@11f9893b081a58869d3b5fccaea48c9e9e46f990 # v8.3.2
  with:
    enable-cache: true
    cache-dependency-glob: |
      **/requirements*.txt
      **/pyproject.toml
- name: Define an absolute cache dependency glob
  uses: astral-sh/setup-uv@11f9893b081a58869d3b5fccaea48c9e9e46f990 # v8.3.2
  with:
    enable-cache: true
    cache-dependency-glob: "/tmp/my-folder/requirements*.txt"
- name: Never invalidate the cache
  uses: astral-sh/setup-uv@11f9893b081a58869d3b5fccaea48c9e9e46f990 # v8.3.2
  with:
    enable-cache: true
    cache-dependency-glob: ""

Restore cache

Restoring an existing cache can be enabled or disabled with the restore-cache input. By default, the cache will be restored.

- name: Don't restore an existing cache
  uses: astral-sh/setup-uv@11f9893b081a58869d3b5fccaea48c9e9e46f990 # v8.3.2
  with:
    enable-cache: true
    restore-cache: false

Save cache

You can also disable saving the cache after the run with the save-cache input. This can be useful to save cache storage when you know you will not use the cache of the run again. By default, the cache will be saved.

- name: Don't save the cache after the run
  uses: astral-sh/setup-uv@11f9893b081a58869d3b5fccaea48c9e9e46f990 # v8.3.2
  with:
    enable-cache: true
    save-cache: false

Local cache path

If caching is enabled, this action controls where uv stores its cache on the runner's filesystem by setting UV_CACHE_DIR.

It defaults to setup-uv-cache in the TMP dir, D:\a\_temp\setup-uv-cache on Windows and /tmp/setup-uv-cache on Linux/macOS. You can change the default by specifying the path with the cache-local-path input.

Note

If the environment variable UV_CACHE_DIR is already set this action will not override it. If you configured cache-dir in your config file then it is also respected and this action will not set UV_CACHE_DIR.

Note

If caching is disabled, you can still use cache-local-path so this action sets UV_CACHE_DIR to your desired path.

- name: Define a custom uv cache path
  uses: astral-sh/setup-uv@11f9893b081a58869d3b5fccaea48c9e9e46f990 # v8.3.2
  with:
    cache-local-path: "/path/to/cache"

Enable cache pruning

By default, the entire uv cache is persisted across runs. On GitHub-hosted runners, it's typically faster to prune the cache before saving it, removing pre-built wheels, but retaining any wheels that were built from source. The pre-built wheels are then re-downloaded from the registry on each run. See the documentation for more information.

If you want to prune the cache before saving it, enable cache pruning with the prune-cache input.

- name: Prune the cache before saving it
  uses: astral-sh/setup-uv@11f9893b081a58869d3b5fccaea48c9e9e46f990 # v8.3.2
  with:
    enable-cache: true
    prune-cache: true

Cache Python installs

By default, the Python install dir (uv python dir / UV_PYTHON_INSTALL_DIR) is not cached, 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.

Note that this only caches Python versions that uv actually installs into UV_PYTHON_INSTALL_DIR (i.e. managed Python installs). If uv uses a system Python, there may be nothing to cache. To force managed Python installs, set UV_PYTHON_PREFERENCE=only-managed.

- name: Cache Python installs
  uses: astral-sh/setup-uv@11f9893b081a58869d3b5fccaea48c9e9e46f990 # v8.3.2
  with:
    enable-cache: true
    cache-python: true

Ignore nothing to cache

By default, the action will fail if caching is enabled but there is nothing to upload (the uv cache directory does not exist) with an error like

Error: Cache path /home/runner/.cache/uv does not exist on disk. This likely indicates that there are no dependencies to cache. Consider disabling the cache input if it is not needed.

If you want to ignore this, set the ignore-nothing-to-cache input to true.

- name: Ignore nothing to cache
  uses: astral-sh/setup-uv@11f9893b081a58869d3b5fccaea48c9e9e46f990 # v8.3.2
  with:
    enable-cache: true
    ignore-nothing-to-cache: true