Skip to content

fix(pre-commit-advisory): key hook-env cache on the resolved Python patch - #53

Merged
blairham merged 1 commit into
mainfrom
fix/pre-commit-cache-key-python-patch
Aug 12, 2026
Merged

fix(pre-commit-advisory): key hook-env cache on the resolved Python patch#53
blairham merged 1 commit into
mainfrom
fix/pre-commit-cache-key-python-patch

Conversation

@blairham

Copy link
Copy Markdown
Contributor

Symptom

pre-commit / advisory fails with every language: python hook erroring, while the C#/gitleaks/local hooks pass:

trim trailing whitespace...................................................Error
[ERROR] hook execution error: fork/exec /home/runner/.cache/pre-commit/repo19a2f5a8ec50638c/py_env-default/bin/trailing-whitespace-fixer: no such file or directory
fix end of files...........................................................Error
check for merge conflicts..................................................Error
detect private key.........................................................Error

Because the advisory reports as a ❌ on the PR, this reads as a problem with the author's diff. It isn't — the diff is never at fault.

Cause

The hook-env cache key interpolated the python-version input, which callers give as a bare X.Y ("3.13"). The venvs go-pre-commit builds under ~/.cache/pre-commit/repo*/py_env-* bind the interpreter by full patch path (/opt/hostedtoolcache/Python/X.Y.Z).

So when a runner-image refresh bumps the patch, the key still matches exactly and restores venvs whose interpreter no longer exists. fork/exec is Go's os/exec error — go-pre-commit is reporting the dangling interpreter, not causing it.

Fix

Key on steps.setup-python.outputs.python-version (the resolved X.Y.Z) instead of the input, in both key and restore-keys.

The patch has to be in the prefix too. A restore-keys ending at X.Y just falls through to the next stale sibling, which is why partial cache purges don't clear it.

Evidence

Observed on trading#3262, 3.13.14 → 3.13.15. Three cache entries shared key go-pre-commit-Linux-py3.13-f7a835d9…, branch-scoped separately. All three had to be deleted before a re-run went green (passing job, 1m42s).

Tradeoff

A Python patch bump now costs one cold rebuild per branch scope instead of a silently broken restore. A .pre-commit-config.yaml edit still reuses same-interpreter envs via the prefix.

Verification

actionlint clean locally. Blast radius is every caller repo, and the first run on each branch scope after merge will be a cold rebuild by design.

Not included, as a separate concern: blairham/go-pre-commit is pinned at v4.6.1; v4.6.2 shipped 2026-08-06.

…atch

The hook-env cache key interpolated the `python-version` input, which
callers give as a bare X.Y ("3.13"). The venvs go-pre-commit builds under
~/.cache/pre-commit/repo*/py_env-* bind the interpreter by full patch path
(/opt/hostedtoolcache/Python/X.Y.Z), so a runner-image patch bump left the
key matching exactly while restoring venvs whose interpreter was gone —
every `language: python` hook then failed with

  [ERROR] hook execution error: fork/exec .../bin/<hook>: no such file or directory

Key on steps.setup-python.outputs.python-version (a full X.Y.Z) instead,
in both `key` and `restore-keys`. The patch must be in the prefix too: a
restore-keys ending at X.Y just falls through to the next stale sibling,
so purging one entry doesn't clear the wedge.

Observed on trading#3262 (3.13.14 -> 3.13.15): all four pre-commit-hooks
entries errored while the csharpier/gitleaks hooks passed, which reads as
a diff problem rather than a cache one. Three cache entries shared the key
and all three needed deleting before a re-run went green.

Costs one cold rebuild per branch scope on a patch bump; a
.pre-commit-config.yaml edit still reuses same-interpreter envs.
@blairham
blairham merged commit 8d630d0 into main Aug 12, 2026
2 checks passed
@blairham
blairham deleted the fix/pre-commit-cache-key-python-patch branch August 12, 2026 23:12
blairham added a commit that referenced this pull request Aug 15, 2026
…ss-env wipe fix (#60)

v4.6.6 (blairham/go-pre-commit#40) wipes a leftover hook environment
that has no install-state marker before installing over it. The
advisory workflow restores hook envs from actions/cache (#50/#53), so
a cache entry missing its install_state_v2 previously poisoned the run:
golang envs failed with "go install ./...: directory go_env-default/
pkg/mod/... outside main module". With the wipe, a bad cache entry
costs one reinstall instead of a red job.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant