Skip to content

Commit 46452da

Browse files
albertodonatoclaude
andcommitted
feat: add an optional uv cache to run-script and fix its pre-commit cache
### what - Add a `uv-cache` input (default false) that restores uv's cache on every run, falling back to the newest one when `uv.lock` moved, and prunes it with `uv cache prune --ci` and saves it off pull requests. - Key the pre-commit cache on the mise config and lockfiles and the selected `mise-env` as well as `.pre-commit-config.yaml`. - Export `PREK_HOME` from `$HOME` in the script instead of setting it in the step's `env:`. ### why Hook environments are built with the toolchains mise installs, so a Python bump restored environments built against the old interpreter. `PREK_HOME` was the literal string `~/.cache/pre-commit`, since `env:` values don't expand `~`, so prek wrote its environments to a `~` directory in the checkout and the cache step saved an empty one. ### testing actionlint, zizmor, ruff and codespell pass (`prek run --all-files`). This repository's CI uses `pre-commit-cache`, so it exercises the new key and `PREK_HOME`. ### docs The README's `run-script` section describes both caches. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 parent f9275f2 commit 46452da

2 files changed

Lines changed: 47 additions & 7 deletions

File tree

‎.github/workflows/run-script.yml‎

Lines changed: 42 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@ on:
1010
description: "Restore the pre-commit cache, saving it on non-PR events"
1111
type: boolean
1212
default: false
13+
uv-cache:
14+
description: "Restore uv's cache, saving it on non-PR events"
15+
type: boolean
16+
default: false
1317
full-git-history:
1418
type: boolean
1519
description: "Whether to fetch full git history rather than just current HEAD"
@@ -87,32 +91,63 @@ jobs:
8791
minimum_release_age: 7d
8892
cache: true
8993

90-
# Always read the cache, it's safe to do so even on untrusted PRs.
94+
# Always read the caches, it's safe to do so even on untrusted PRs.
95+
#
96+
# Hook environments are built with the toolchains mise installs (Python,
97+
# Node, ...), so the key covers the mise config and lockfiles and the
98+
# selected environment as well as the hook pins: a toolchain bump must
99+
# not restore environments built against the old one.
91100
- name: Restore pre-commit cache
92101
if: inputs.pre-commit-cache
93102
id: pre-commit-cache
94103
uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
95104
with:
96105
path: ~/.cache/pre-commit
97-
key: pre-commit-${{ runner.os }}-${{ hashFiles('.pre-commit-config.yaml') }}
106+
key: pre-commit-${{ runner.os }}-${{ runner.arch }}-${{ inputs.mise-env }}-${{ hashFiles('.pre-commit-config.yaml', 'mise.toml', 'mise.lock', 'mise.*.toml', 'mise.*.lock') }}
107+
108+
# uv verifies what it installs against uv.lock's hashes, so a stale entry
109+
# only costs a download; restore the newest cache when the lock moved.
110+
- name: Restore uv cache
111+
if: inputs.uv-cache
112+
id: uv-cache
113+
uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
114+
with:
115+
path: ~/.cache/uv
116+
key: uv-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('uv.lock') }}
117+
restore-keys: |
118+
uv-${{ runner.os }}-${{ runner.arch }}-
98119
99120
- name: Run
100121
# Some tools reject an empty GH_TOKEN (e.g. zizmor), so unset it rather
101122
# than leaving it empty.
102123
run: | # zizmor: ignore[template-injection] caller-provided script
103124
[ -n "$GH_TOKEN" ] || unset GH_TOKEN
125+
# Point prek at the pre-commit cache path so the cache step covers
126+
# both. Exported here because `env:` values don't expand `~`.
127+
export PREK_HOME="$HOME/.cache/pre-commit"
104128
${{ inputs.run }}
105129
env:
106130
GH_TOKEN: ${{ inputs.github-token && github.token || '' }}
107-
# Point prek at the pre-commit cache path so the cache step covers both.
108-
PREK_HOME: ~/.cache/pre-commit
109131

110-
# Cache ssave is gated to non-PR events: an untrusted PR run must not be
111-
# able to write a hook-environment cache that a later trusted build
112-
# restores and executes (cache poisoning).
132+
# Cache saves are gated to non-PR events: an untrusted PR run must not be
133+
# able to write a cache that a later trusted build restores and executes
134+
# (cache poisoning).
113135
- name: Save pre-commit cache
114136
if: inputs.pre-commit-cache && github.event_name != 'pull_request' && steps.pre-commit-cache.outputs.cache-hit != 'true'
115137
uses: actions/cache/save@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
116138
with:
117139
path: ~/.cache/pre-commit
118140
key: ${{ steps.pre-commit-cache.outputs.cache-primary-key }}
141+
142+
# Keep only what's slow to rebuild: --ci drops pre-built wheels, which
143+
# download again quickly, and keeps wheels built from source.
144+
- name: Prune uv cache
145+
if: inputs.uv-cache && github.event_name != 'pull_request' && steps.uv-cache.outputs.cache-hit != 'true'
146+
run: uv cache prune --ci
147+
148+
- name: Save uv cache
149+
if: inputs.uv-cache && github.event_name != 'pull_request' && steps.uv-cache.outputs.cache-hit != 'true'
150+
uses: actions/cache/save@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
151+
with:
152+
path: ~/.cache/uv
153+
key: ${{ steps.uv-cache.outputs.cache-primary-key }}

‎README.md‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,11 @@ are loaded on top of the default config.
5757
just lint
5858
```
5959
60+
Set `pre-commit-cache` to keep pre-commit's (or prek's) hook environments between
61+
runs, and `uv-cache` to keep uv's cache. Both are restored on every run but saved only
62+
off pull requests, so an untrusted pull request can't write a cache a later trusted run
63+
restores.
64+
6065
The job runs with exactly the permissions the caller grants, so grant at least
6166
`contents: read`.
6267

0 commit comments

Comments
 (0)