Skip to content

Commit ab6379f

Browse files
alexkromanclaude
andauthored
Cache uv and Go binaries in CI workflows (#224)
## Summary Optimize CI performance by caching the `uv` package manager and Go-built gate binaries (`actionlint`, `gitleaks`) across workflow runs, reducing redundant downloads and compilation. ## Key Changes - **Replace manual `uv` installation with `astral-sh/setup-uv` action** across three jobs (`ci`, `test-e2e`, `docs-snapshot`): - Uses the official setup action (v8.2.0) with caching enabled - Caches the uv download cache (`~/.cache/uv`) keyed on `uv.lock`, avoiding re-downloads of locked dependencies including Rust-backed sdists (pydantic-core, jiter, cryptography) - Simplifies the install step from `python -m pip install uv` to a declarative action - **Add caching for Go gate binaries** in the `ci` job: - New `actions/cache` step caches `~/go/bin` keyed on `scripts/gate_tool_pins.sh` - Conditional `go install` only runs on cache miss, skipping from-source compilation when binaries are cached - Uses environment variable to safely pass cache-hit output to the script (avoiding template-injection risk) - **Separate `uv sync --frozen` into its own step** in the `docs-snapshot` job for clarity ## Implementation Details - All cache keys are deterministic and tied to their respective lock/pin files, ensuring cache invalidation when dependencies change - The Go binary caching uses a conditional check (`if [ "$CACHE_HIT" != "true" ]`) to skip compilation entirely on cache hits - Cache-hit output is mapped to an environment variable rather than expanded directly in the script, following security best practices (zizmor template-injection rule) https://claude.ai/code/session_01Wboq6L5ujSodPxqbewP3tx Co-authored-by: Claude <noreply@anthropic.com>
1 parent b468637 commit ab6379f

1 file changed

Lines changed: 38 additions & 13 deletions

File tree

.github/workflows/ci.yml

Lines changed: 38 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -61,22 +61,41 @@ jobs:
6161
npm install -g "markdownlint-cli@${MARKDOWNLINT_VERSION}" "prettier@${PRETTIER_VERSION}"
6262
6363
# check.sh runs every tool through `uv run` / `uv build` for a locked,
64-
# reproducible env, so only uv must be on PATH (installed from PyPI to match
65-
# the repo's pip-based, no-new-action posture). `uv run` itself syncs the
66-
# project + dev group into .venv, so no `pip install -e .` is needed here.
67-
- name: Install
68-
run: python -m pip install uv
64+
# reproducible env, so only uv must be on PATH. setup-uv caches the uv
65+
# download cache (~/.cache/uv) keyed on uv.lock, so the locked env — incl.
66+
# the Rust-backed sdists (pydantic-core/jiter/cryptography) — isn't
67+
# re-downloaded/rebuilt every run. `uv run` itself syncs the project + dev
68+
# group into .venv, so no `pip install -e .` is needed here.
69+
- name: Install uv (cached)
70+
uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0
71+
with:
72+
enable-cache: true
73+
cache-dependency-glob: uv.lock
6974

7075
# actionlint and gitleaks are Go binaries (no PyPI wheel), so check.sh self-skips
7176
# them locally like shellcheck. Build them here with the runner's preinstalled Go,
7277
# pinned via scripts/gate_tool_pins.sh (shared with the web session-start hook),
7378
# and put GOPATH/bin on PATH so check.sh enforces them.
7479
# (gitleaks v8's Go module path is still github.com/zricethezav/gitleaks/v8.)
80+
# Cache the built binaries keyed on the pin file so a cache hit skips the
81+
# from-source `go install` compile entirely.
82+
- name: Cache Go gate binaries (actionlint, gitleaks)
83+
id: cache-go-bin
84+
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
85+
with:
86+
path: ~/go/bin
87+
key: go-gate-bins-${{ runner.os }}-${{ hashFiles('scripts/gate_tool_pins.sh') }}
7588
- name: Workflow + secret scanners (actionlint, gitleaks)
89+
env:
90+
# Map the cache-hit output to an env var rather than expanding the
91+
# `${{ }}` directly into the script (zizmor template-injection rule).
92+
CACHE_HIT: ${{ steps.cache-go-bin.outputs.cache-hit }}
7693
run: |
7794
source scripts/gate_tool_pins.sh
78-
go install "$ACTIONLINT_MODULE"
79-
go install "$GITLEAKS_MODULE"
95+
if [ "$CACHE_HIT" != "true" ]; then
96+
go install "$ACTIONLINT_MODULE"
97+
go install "$GITLEAKS_MODULE"
98+
fi
8099
echo "$(go env GOPATH)/bin" >> "$GITHUB_PATH"
81100
82101
- name: Lint, typecheck, test
@@ -155,8 +174,11 @@ jobs:
155174
}
156175
ffmpeg -version
157176
158-
- name: Install uv
159-
run: python -m pip install uv
177+
- name: Install uv (cached)
178+
uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0
179+
with:
180+
enable-cache: true
181+
cache-dependency-glob: uv.lock
160182

161183
# `uv run` syncs the locked project + dev group into .venv, then runs the default
162184
# suite (e2e/install excluded via addopts).
@@ -225,10 +247,13 @@ jobs:
225247
# resolve the LOCKED dependency versions (uv.lock) rather than the newest
226248
# release `pip install` would pull — which is what keeps the byte-exact
227249
# `--help` snapshots stable. Install uv and materialize the frozen env here.
228-
- name: Install
229-
run: |
230-
python -m pip install --upgrade pip uv
231-
uv sync --frozen
250+
- name: Install uv (cached)
251+
uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0
252+
with:
253+
enable-cache: true
254+
cache-dependency-glob: uv.lock
255+
- name: Sync frozen env
256+
run: uv sync --frozen
232257

233258
- uses: pre-commit/action@2c7b3805fd2a0fd8c1884dcaebf91fc102a13ecd # v3.0.1
234259

0 commit comments

Comments
 (0)