Stop installing linters the pre-commit jobs never use, and add cache fallbacks

Two follow-ups measured on the warm-cache run of d56b936, where the three
pre-commit jobs were 39-44s split as: 4s runner setup, 9s pip, 2s cache
restore, 23s hooks.

The 9s pip was pure waste. Every linting hook runs in its own isolated env
-- ruff, mypy, pylint, bandit and codespell each come from their own
repo+rev, mypy and pylint declaring their own additional_dependencies -- and
the only local hooks in the pre-commit stage need bash and python3. The
pytest-coverage hook, the one thing that would need the real dependency set,
is stages: [pre-push] and never runs here. Verified by running all three
configs green in a venv containing pre-commit and nothing else. The pin is
grepped out of requirements.txt so it cannot drift from the
dependency-freshness gate.

restore-keys is added because the exact key includes the config hash, so the
next hook-rev bump -- this session did one -- would have been a total miss
and reinstalled everything. A prefix hit rebuilds only the changed hook.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019kMvSMtsVMB3d2uoZ56pbp
This commit is contained in:
Krzysztof Rudnicki 2026-09-12 18:22:39 +02:00
parent d56b936b48
commit a473e91485
3 changed files with 57 additions and 17 deletions

View File

@ -16,11 +16,17 @@ 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
# Only pre-commit itself. Every linting hook runs in its own isolated
# env -- ruff, mypy, pylint, bandit and codespell each come from their
# own repo+rev, and the local hooks need nothing beyond bash and
# python3 -- so installing the full requirements.txt spent 9s a run on
# packages no pre-commit-stage hook imports. Verified by running all
# three configs green in a venv holding pre-commit and nothing else.
# The pin is read out of requirements.txt rather than repeated here, so
# it cannot drift from what the dependency-freshness gate governs.
- name: Install pre-commit
run: |
pip install "$(grep '^pre-commit==' crdt-sync/requirements.txt)"
# 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
@ -34,6 +40,14 @@ jobs:
key: >-
pre-commit-crdt-sync-${{ env.pythonLocation }}-${{
hashFiles('crdt-sync/.pre-commit-config.yaml') }}
# Prefix fallback, or this fix would evaporate on the very
# event that motivated it: bumping a hook rev changes the
# exact key, and a total miss means reinstalling every hook
# again. pre-commit's store is keyed internally by hook
# repo+rev, so a superseded entry is ignored disk rather
# than a wrong hook, and cache still re-saves under the new
# exact key after a prefix-only hit.
restore-keys: pre-commit-crdt-sync-${{ env.pythonLocation }}-
- name: Run the hooks
run: >-
pre-commit run --config crdt-sync/.pre-commit-config.yaml

View File

@ -19,13 +19,17 @@ 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
# Only pre-commit itself. Every linting hook runs in its own isolated
# env -- ruff, mypy, pylint, bandit and codespell each come from their
# own repo+rev, and the local hooks need nothing beyond bash and
# python3 -- so installing the full requirements.txt spent 9s a run on
# packages no pre-commit-stage hook imports. Verified by running all
# three configs green in a venv holding pre-commit and nothing else.
# The pin is read out of requirements.txt rather than repeated here, so
# it cannot drift from what the dependency-freshness gate governs.
- name: Install pre-commit
run: |
pip install "$(grep '^pre-commit==' freedays/requirements.txt)"
# 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
@ -39,6 +43,14 @@ jobs:
key: >-
pre-commit-freedays-${{ env.pythonLocation }}-${{
hashFiles('freedays/.pre-commit-config.yaml') }}
# Prefix fallback, or this fix would evaporate on the very
# event that motivated it: bumping a hook rev changes the
# exact key, and a total miss means reinstalling every hook
# again. pre-commit's store is keyed internally by hook
# repo+rev, so a superseded entry is ignored disk rather
# than a wrong hook, and cache still re-saves under the new
# exact key after a prefix-only hit.
restore-keys: pre-commit-freedays-${{ env.pythonLocation }}-
- name: Run the hooks
run: >-
pre-commit run --config freedays/.pre-commit-config.yaml

View File

@ -18,11 +18,17 @@ 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
# Only pre-commit itself. Every linting hook runs in its own isolated
# env -- ruff, mypy, pylint, bandit and codespell each come from their
# own repo+rev, and the local hooks need nothing beyond bash and
# python3 -- so installing the full requirements.txt spent 9s a run on
# packages no pre-commit-stage hook imports. Verified by running all
# three configs green in a venv holding pre-commit and nothing else.
# The pin is read out of requirements.txt rather than repeated here, so
# it cannot drift from what the dependency-freshness gate governs.
- name: Install pre-commit
run: |
pip install "$(grep '^pre-commit==' gatelock/requirements.txt)"
# 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
@ -36,6 +42,14 @@ jobs:
key: >-
pre-commit-gatelock-${{ env.pythonLocation }}-${{
hashFiles('gatelock/.pre-commit-config.yaml') }}
# Prefix fallback, or this fix would evaporate on the very
# event that motivated it: bumping a hook rev changes the
# exact key, and a total miss means reinstalling every hook
# again. pre-commit's store is keyed internally by hook
# repo+rev, so a superseded entry is ignored disk rather
# than a wrong hook, and cache still re-saves under the new
# exact key after a prefix-only hit.
restore-keys: pre-commit-gatelock-${{ env.pythonLocation }}-
- name: Run the hooks
run: >-
pre-commit run --config gatelock/.pre-commit-config.yaml