From d56b936b48ea5e63d96391d6819a67197fe63592 Mon Sep 17 00:00:00 2001 From: Krzysztof kuhy Rudnicki Date: Sat, 12 Sep 2026 18:16:51 +0200 Subject: [PATCH] Cache pre-commit hooks per package, and pip, so CI stops reinstalling Measured on 6154dc0: the three pre-commit jobs took 41-59s, of which 38-49s was pre-commit installing hook environments and ~11s was an uncached pip. The cache was not merely cold, it was miskeyed. pre-commit/action@v3.0.1 keys on hashFiles('.pre-commit-config.yaml') -- the repo ROOT's config -- but the hooks it installs come from the per-package config passed in extra_args. Four different configs, one cache key: the three package jobs raced to overwrite each other's hook sets, and editing a per-package config never invalidated the key, so the restored cache was silently wrong rather than missing. Three 68MB entries in the cache list are the symptom. So the action is replaced with a direct `pre-commit run`, which keeps the same --config/--all-files behaviour plus --show-diff-on-failure, wrapped in an actions/cache keyed on the config that actually drives the install. pre-commit is already an exact pin in each requirements.txt. setup-python gains cache: pip keyed on each requirements.txt, for the test jobs too. The two crdt-sync workflows now list their own file in `paths`, which the other four already did -- a workflow edit should re-run its own gate. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_019kMvSMtsVMB3d2uoZ56pbp --- .github/workflows/crdt-sync-precommit.yml | 24 +++++++++++++++++++---- .github/workflows/crdt-sync-tests.yml | 6 ++++-- .github/workflows/freedays-precommit.yml | 20 +++++++++++++++++-- .github/workflows/freedays-tests.yml | 2 ++ .github/workflows/gatelock-precommit.yml | 20 +++++++++++++++++-- .github/workflows/gatelock-tests.yml | 2 ++ 6 files changed, 64 insertions(+), 10 deletions(-) diff --git a/.github/workflows/crdt-sync-precommit.yml b/.github/workflows/crdt-sync-precommit.yml index 20dd47d..0866ef9 100644 --- a/.github/workflows/crdt-sync-precommit.yml +++ b/.github/workflows/crdt-sync-precommit.yml @@ -3,10 +3,10 @@ name: crdt-sync pre-commit on: push: branches: [main] - paths: ['crdt-sync/**'] + paths: ['crdt-sync/**', '.github/workflows/crdt-sync-precommit.yml'] pull_request: branches: [main] - paths: ['crdt-sync/**'] + paths: ['crdt-sync/**', '.github/workflows/crdt-sync-precommit.yml'] jobs: pre-commit: @@ -16,9 +16,25 @@ jobs: - uses: actions/setup-python@v5 with: python-version: "3.x" + cache: pip + cache-dependency-path: crdt-sync/requirements.txt - name: Install dependencies working-directory: crdt-sync run: pip install -r requirements.txt - - uses: pre-commit/action@v3.0.1 + + # Keyed on THIS package's config. pre-commit/action@v3.0.1 caches on + # hashFiles('.pre-commit-config.yaml') -- the repo ROOT's -- so all three + # package jobs shared one key, raced to overwrite it with hook sets built + # from four different configs, and editing a per-package config did not + # invalidate it. The cache was therefore silently wrong rather than + # missing, and the hooks reinstalled from scratch on every run (38-49s). + - uses: actions/cache@v4 with: - extra_args: --config crdt-sync/.pre-commit-config.yaml --all-files + path: ~/.cache/pre-commit + key: >- + pre-commit-crdt-sync-${{ env.pythonLocation }}-${{ + hashFiles('crdt-sync/.pre-commit-config.yaml') }} + - name: Run the hooks + run: >- + pre-commit run --config crdt-sync/.pre-commit-config.yaml + --all-files --show-diff-on-failure diff --git a/.github/workflows/crdt-sync-tests.yml b/.github/workflows/crdt-sync-tests.yml index 6275cb7..dba9b49 100644 --- a/.github/workflows/crdt-sync-tests.yml +++ b/.github/workflows/crdt-sync-tests.yml @@ -3,10 +3,10 @@ name: crdt-sync tests on: push: branches: [main] - paths: ['crdt-sync/**'] + paths: ['crdt-sync/**', '.github/workflows/crdt-sync-tests.yml'] pull_request: branches: [main] - paths: ['crdt-sync/**'] + paths: ['crdt-sync/**', '.github/workflows/crdt-sync-tests.yml'] jobs: test: @@ -21,6 +21,8 @@ jobs: uses: actions/setup-python@v5 with: python-version: "3.x" + cache: pip + cache-dependency-path: crdt-sync/requirements.txt - name: Install dependencies run: pip install -r requirements.txt diff --git a/.github/workflows/freedays-precommit.yml b/.github/workflows/freedays-precommit.yml index 7c8ff1e..1ed99b8 100644 --- a/.github/workflows/freedays-precommit.yml +++ b/.github/workflows/freedays-precommit.yml @@ -19,11 +19,27 @@ jobs: - uses: actions/setup-python@v5 with: python-version: "3.x" + cache: pip + cache-dependency-path: freedays/requirements.txt - name: Install the sibling package run: pip install ./crdt-sync - name: Install dependencies working-directory: freedays run: pip install -r requirements.txt - - uses: pre-commit/action@v3.0.1 + + # Keyed on THIS package's config. pre-commit/action@v3.0.1 caches on + # hashFiles('.pre-commit-config.yaml') -- the repo ROOT's -- so all three + # package jobs shared one key, raced to overwrite it with hook sets built + # from four different configs, and editing a per-package config did not + # invalidate it. The cache was therefore silently wrong rather than + # missing, and the hooks reinstalled from scratch on every run (38-49s). + - uses: actions/cache@v4 with: - extra_args: --config freedays/.pre-commit-config.yaml --all-files + path: ~/.cache/pre-commit + key: >- + pre-commit-freedays-${{ env.pythonLocation }}-${{ + hashFiles('freedays/.pre-commit-config.yaml') }} + - name: Run the hooks + run: >- + pre-commit run --config freedays/.pre-commit-config.yaml + --all-files --show-diff-on-failure diff --git a/.github/workflows/freedays-tests.yml b/.github/workflows/freedays-tests.yml index a70f7c9..040901c 100644 --- a/.github/workflows/freedays-tests.yml +++ b/.github/workflows/freedays-tests.yml @@ -24,6 +24,8 @@ jobs: uses: actions/setup-python@v5 with: python-version: "3.x" + cache: pip + cache-dependency-path: freedays/requirements.txt # crdt-sync is a sibling in this repo, so it installs from the checkout # rather than from a tag -- CI must test what is on this branch, not diff --git a/.github/workflows/gatelock-precommit.yml b/.github/workflows/gatelock-precommit.yml index 51d904c..7118321 100644 --- a/.github/workflows/gatelock-precommit.yml +++ b/.github/workflows/gatelock-precommit.yml @@ -18,9 +18,25 @@ jobs: - uses: actions/setup-python@v5 with: python-version: "3.x" + cache: pip + cache-dependency-path: gatelock/requirements.txt - name: Install dependencies working-directory: gatelock run: pip install -r requirements.txt - - uses: pre-commit/action@v3.0.1 + + # Keyed on THIS package's config. pre-commit/action@v3.0.1 caches on + # hashFiles('.pre-commit-config.yaml') -- the repo ROOT's -- so all three + # package jobs shared one key, raced to overwrite it with hook sets built + # from four different configs, and editing a per-package config did not + # invalidate it. The cache was therefore silently wrong rather than + # missing, and the hooks reinstalled from scratch on every run (38-49s). + - uses: actions/cache@v4 with: - extra_args: --config gatelock/.pre-commit-config.yaml --all-files + path: ~/.cache/pre-commit + key: >- + pre-commit-gatelock-${{ env.pythonLocation }}-${{ + hashFiles('gatelock/.pre-commit-config.yaml') }} + - name: Run the hooks + run: >- + pre-commit run --config gatelock/.pre-commit-config.yaml + --all-files --show-diff-on-failure diff --git a/.github/workflows/gatelock-tests.yml b/.github/workflows/gatelock-tests.yml index 5ec7b91..f645964 100644 --- a/.github/workflows/gatelock-tests.yml +++ b/.github/workflows/gatelock-tests.yml @@ -23,6 +23,8 @@ jobs: uses: actions/setup-python@v5 with: python-version: "3.x" + cache: pip + cache-dependency-path: gatelock/requirements.txt - name: Install dependencies run: pip install -r requirements.txt