From 589da6b2b1076c52a2c50de90c433a3c8497c111 Mon Sep 17 00:00:00 2001 From: Dmitriev Alexander <34693850+zoola969@users.noreply.github.com> Date: Sat, 22 Aug 2026 07:41:41 +0400 Subject: [PATCH] ci: cache .mypy_cache in the test matrix An Actions audit across every repo in the account found `finances` was the only one caching `.mypy_cache`. Here mypy runs cold six times per CI run, once per matrix entry. The key includes the interpreter version: mypy's results depend on the Python version it analyses under, so without it the six matrix jobs would race for a single cache entry. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01VHqcUw1PJ8Dvo2D5WUHbKM --- .github/workflows/tests.yml | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 8e0acdc..b374e31 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -33,6 +33,32 @@ jobs: - name: "Install dependencies" run: uv sync --locked --no-default-groups --no-install-project --group test + # Restoring `.mypy_cache` drops a cold mypy run to well under a second, + # because incremental mode re-checks only the files whose *contents* + # changed. Checkout gives every file a fresh mtime, which mypy tolerates + # -- it falls back to comparing hashes and finds the cached results still + # valid. + # + # The key carries the interpreter version because this is a matrix build: + # mypy's results depend on the Python version it analyses under, and + # without it the six jobs would race for one entry. `uv.lock` pins the + # mypy version and `pyproject.toml` holds its config, so either changing + # invalidates the cache rather than silently reusing results computed + # under different rules. `github.sha` keeps the key unique per run so each + # build refreshes the entry (Actions cache entries are immutable, so a key + # that already exists is never rewritten), while `restore-keys` falls back + # to the newest cache for the same version+lock+config. + # + # This pays off only because the workflow also runs on push to `master`: + # a cache written by a PR run is scoped to that PR, and only one written + # on the default branch is readable by every new branch. + - uses: actions/cache@v6 + with: + path: .mypy_cache + key: mypy-${{ runner.os }}-py${{ matrix.python-version }}-${{ hashFiles('uv.lock', 'pyproject.toml') }}-${{ github.sha }} + restore-keys: | + mypy-${{ runner.os }}-py${{ matrix.python-version }}-${{ hashFiles('uv.lock', 'pyproject.toml') }}- + - name: "Run mypy" run: uv run mypy ttlru_map