Never cache the Python target: it describes this process, not a registry
Some checks are pending
dependency freshness / dependencies on newest stable (push) Waiting to run
file length / file-length (push) Waiting to run
md-naming / markdown naming convention (push) Waiting to run
palette drift / palette (push) Waiting to run
shared gate tests / gate unit tests (push) Waiting to run

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Krzysztof Rudnicki 2026-08-28 19:33:09 +02:00
parent a59fa266c9
commit 1e35cd5ba2
2 changed files with 43 additions and 2 deletions

View File

@ -50,6 +50,18 @@ def _toolchain_latest(name: str) -> str | None:
return None
def never_cached(ecosystem: str, name: str) -> bool:
"""True for answers that describe THIS process, not a remote registry.
`toolchain:python` is `platform.python_version()`: free to compute, and
different on every machine. Caching it made screen-locker's CI red on
2026-08-28 -- the `actions/cache` restore-key handed a job running 3.14.7
a 3.13.15 answer written by an older runner image, and the gate declared
the repo's own `requires-python = ">=3.14"` to exclude "latest".
"""
return ecosystem == TOOLCHAIN and name == "python"
def _fetch(ecosystem: str, package: str) -> str | None:
if ecosystem == TOOLCHAIN:
return _toolchain_latest(package)
@ -71,8 +83,11 @@ class Resolver:
wanted = {
(d.ecosystem, d.name)
for d in deps
if not (entry := self.cache.get(d.ecosystem, d.name))
or not entry.fresh(d.ecosystem)
if not never_cached(d.ecosystem, d.name)
and (
not (entry := self.cache.get(d.ecosystem, d.name))
or not entry.fresh(d.ecosystem)
)
}
if not wanted:
return
@ -93,6 +108,8 @@ class Resolver:
self.cache.save()
def latest(self, dep: Dep) -> Answer:
if never_cached(dep.ecosystem, dep.name):
return Answer(_fetch(dep.ecosystem, dep.name))
entry = self.cache.get(dep.ecosystem, dep.name)
if entry and entry.fresh(dep.ecosystem):
return Answer(entry.version)

View File

@ -85,6 +85,30 @@ def test_refresh_discards_the_existing_cache(cache_dir, monkeypatch):
assert resolver.latest(dep()).version == "1.6.0"
def test_the_python_target_ignores_the_cache_entirely(resolver, monkeypatch):
"""screen-locker went red on a cached interpreter from another machine.
`actions/cache` restored a `dep-freshness-` entry written by an older
runner image, so a job that `setup-python` had put on 3.14.7 was told the
"current toolchain" was 3.13.15 -- and the repo's own
`requires-python = ">=3.14"` was reported as excluding latest. The answer
describes this process and costs nothing, so it is never cached.
"""
resolver.cache.put("toolchain", "python", "3.13.15")
monkeypatch.setattr(tc, "python_installed", lambda: "3.14.7")
assert resolver.latest(dep("toolchain", "python")).version == "3.14.7"
def test_prefetch_does_not_warm_the_python_target(resolver, monkeypatch):
monkeypatch.setattr(
http, "get_json", lambda *a, **k: pytest.fail("no lookup is needed")
)
monkeypatch.setattr(
tc, "python_installed", lambda: pytest.fail("prefetch must skip python")
)
resolver.prefetch([dep("toolchain", "python")])
def test_git_tags_get_a_longer_ttl_than_registries():
assert ttl_for("gittag") > ttl_for("pub")