Skip to content
Latchkey

pre-commit in GitHub Actions: A Caching Workflow

A GitHub Actions job runs pre-commit run --all-files after restoring a cache of ~/.cache/pre-commit.

The whole job is: check out, set up the interpreter, restore the pre-commit cache keyed on the config hash, then run all hooks. The cache is what keeps the job fast.

What it does

The workflow installs pre-commit, restores the hook-environment cache so envs are not rebuilt, and runs every hook against the whole repo. The official pre-commit/action does the caching for you, or you wire actions/cache yourself.

Common usage

.github/workflows/lint.yml
- uses: actions/setup-python@v5
  with:
    python-version: "3.11"
- uses: actions/cache@v4
  with:
    path: ~/.cache/pre-commit
    key: pre-commit-${{ hashFiles('.pre-commit-config.yaml') }}
- run: pip install pre-commit
- run: pre-commit run --all-files --show-diff-on-failure

Pieces

StepWhy
setup-pythonProvides the interpreter the python hooks need
cache ~/.cache/pre-commitReuse hook environments between runs
key: hashFiles(config)Invalidate the cache when hooks change
run --all-filesCheck the whole repo, not just a diff
--show-diff-on-failureSurface what autofixers would change

In CI

Key the cache on the hash of .pre-commit-config.yaml so it busts whenever a rev or hook changes. Without the cache, every run logs "[INFO] Initializing environment" and reinstalls every hook, adding minutes. The pre-commit/action@v3 action bundles this caching if you prefer not to manage it.

Common errors in CI

Slow jobs that always print "[INFO] Initializing environment for ..." mean the cache is not being restored: check the cache path is exactly ~/.cache/pre-commit and the key is stable. "[ERROR] Executable python3.11 not found" means setup-python ran with a different version than default_language_version pins. A job that passes locally but fails on CI is usually catching files that were never staged locally.

Related guides

Run this faster and cheaper on Latchkey managed runners. Start free →