mirror of
https://github.com/kuhyx/utils.git
synced 2026-11-10 21:27:14 +01:00
Two things that were fine in utils and would not have been in the next forty repos. **The allowlist is now fleet-wide plus per-repo.** `typescript-eslint` blocks TS 7 in EVERY repo that pins typescript -- eight of them and counting -- and a repo-only allowlist meant hand-copying one entry into eight files that then rot independently. That is the four-way fork of the 250-line cap, reproduced inside the mechanism built to avoid it. `~/utils/dependency-freshness.allowlist.yaml` is inherited by every repo; a repo entry for the same `ecosystem:package` overrides it. Inherited entries are exempt from the no-longer-needed check everywhere except the repo that owns the file. Without that carve-out a fleet-wide hold on typescript exits 2 in every Flutter app -- it excuses nothing there, which is the normal case, not rot -- and those repos become uncommittable. Confirmed against punchme, which now exits 0 while utils still reports the entry as in use. **`quarantine.py` bypassed the cache entirely.** It ran for every npm finding and fetched the FULL packument -- 7MB for react, 16MB for typescript -- with no TTL and no reuse, inside a pre-commit hook. One finding in utils, but the JS repos ahead have 16 to 37 each. Now cached under the normal 6h TTL, keyed `<name>@<dist-tag>`: the tag has to be part of the key rather than clamped afterwards, because clamping returns the ceiling and the ceiling is frequently the very release the quarantine is excluding. **Both cache and shared allowlist are now redirected by AUTOUSE fixtures.** A quarantine test had already seeded a fake answer for package "x" into the real ~/.cache/dep-freshness/registry.json, and the next run read its own pollution back and passed for the wrong reason. Removed the entry; the fixture makes it unrepeatable. 292 tests, 100% branch coverage on every module. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CRykabMwPgDzFHcARoqpaK
218 lines
7.8 KiB
Python
218 lines
7.8 KiB
Python
"""pnpm 11 refuses freshly-published packages; the gate must agree.
|
|
|
|
Reporting a repo as behind a version its package manager will not install is a
|
|
finding nobody can act on -- the pre-commit hook would fail, and the fix the
|
|
message asks for would fail too.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from datetime import datetime, timedelta, timezone
|
|
|
|
import pytest
|
|
|
|
from dep_freshness import check, quarantine
|
|
from dep_freshness.models import Dep, Finding, Severity
|
|
from dep_freshness.tests.conftest import write
|
|
|
|
NOW = datetime(2026, 8, 28, 12, 0, tzinfo=timezone.utc)
|
|
|
|
|
|
def _stamp(hours_ago: float) -> str:
|
|
return (NOW - timedelta(hours=hours_ago)).isoformat().replace("+00:00", "Z")
|
|
|
|
|
|
PACKUMENT = {
|
|
"time": {
|
|
"created": _stamp(9000),
|
|
"modified": _stamp(1),
|
|
"16.3.0": _stamp(900),
|
|
"16.3.2": _stamp(400),
|
|
"16.3.3": _stamp(18), # inside the 24h window
|
|
}
|
|
}
|
|
|
|
|
|
@pytest.fixture
|
|
def packument(monkeypatch):
|
|
def install(payload):
|
|
monkeypatch.setattr(quarantine, "get_json", lambda *_a, **_k: payload)
|
|
return install
|
|
|
|
|
|
def test_a_release_inside_the_window_is_not_installable(packument):
|
|
packument(PACKUMENT)
|
|
assert quarantine.installable_latest("x", "16.3.3", now=NOW) == "16.3.2"
|
|
|
|
|
|
def test_a_release_outside_the_window_is_installable(packument):
|
|
packument(PACKUMENT)
|
|
assert quarantine.installable_latest("x", "16.3.2", now=NOW) == "16.3.2"
|
|
|
|
|
|
def test_versions_above_the_dist_tag_are_ignored(packument):
|
|
"""npm lets a maintenance release outrank `latest` numerically."""
|
|
payload = {"time": {**PACKUMENT["time"], "17.0.0": _stamp(500)}}
|
|
packument(payload)
|
|
assert quarantine.installable_latest("x", "16.3.3", now=NOW) == "16.3.2"
|
|
|
|
|
|
def test_the_created_and_modified_keys_are_not_versions(packument):
|
|
packument({"time": {"created": _stamp(900), "modified": _stamp(1)}})
|
|
assert quarantine.installable_latest("x", "1.0.0", now=NOW) is None
|
|
|
|
|
|
def test_an_unparseable_timestamp_is_skipped(packument):
|
|
packument({"time": {"1.0.0": "not a date", "0.9.0": _stamp(500)}})
|
|
assert quarantine.installable_latest("x", "1.0.0", now=NOW) == "0.9.0"
|
|
|
|
|
|
def test_an_unparseable_ceiling_stops_narrowing_but_the_window_still_applies(
|
|
packument,
|
|
):
|
|
packument(PACKUMENT)
|
|
# No version ceiling to apply, but 16.3.3 is still 18h old.
|
|
assert quarantine.installable_latest("x", "latest", now=NOW) == "16.3.2"
|
|
|
|
|
|
def test_a_registry_without_a_time_map_is_undeterminable(packument):
|
|
packument({"versions": {"1.0.0": {}}})
|
|
assert quarantine.installable_latest("x", "1.0.0", now=NOW) is None
|
|
|
|
|
|
def test_a_missing_package_is_undeterminable(packument):
|
|
packument(None)
|
|
assert quarantine.installable_latest("x", "1.0.0", now=NOW) is None
|
|
|
|
|
|
def test_offline_is_undeterminable(monkeypatch):
|
|
from dep_freshness.registries.http import Offline
|
|
|
|
def down(*_a, **_k):
|
|
raise Offline("no network")
|
|
|
|
monkeypatch.setattr(quarantine, "get_json", down)
|
|
assert quarantine.installable_latest("x", "1.0.0") is None
|
|
|
|
|
|
def test_the_cutoff_defaults_to_now():
|
|
assert quarantine.cutoff() < datetime.now(timezone.utc)
|
|
|
|
|
|
def _dep(ecosystem="npm", pinned="16.3.2", constraint="16.3.2") -> Dep:
|
|
from pathlib import Path
|
|
return Dep(ecosystem=ecosystem, name="@testing-library/react",
|
|
constraint=constraint, path=Path("package.json"), line=1,
|
|
pinned=pinned)
|
|
|
|
|
|
def test_a_finding_only_caused_by_a_quarantined_release_is_dropped(monkeypatch):
|
|
monkeypatch.setattr(check, "installable_latest",
|
|
lambda _n, _c: "16.3.2")
|
|
finding = Finding(_dep(), Severity.STALE, "16.3.3")
|
|
assert check._unquarantine(finding) is None
|
|
|
|
|
|
def test_a_finding_that_survives_the_narrowing_is_kept(monkeypatch):
|
|
monkeypatch.setattr(check, "installable_latest", lambda _n, _c: "16.3.2")
|
|
finding = Finding(_dep(pinned="16.1.0"), Severity.STALE, "16.3.3")
|
|
survivor = check._unquarantine(finding)
|
|
assert survivor is not None
|
|
assert survivor.latest == "16.3.2"
|
|
|
|
|
|
def test_non_npm_findings_are_never_narrowed(monkeypatch):
|
|
monkeypatch.setattr(check, "installable_latest", _explode)
|
|
finding = Finding(_dep(ecosystem="pub"), Severity.STALE, "1.0.0")
|
|
assert check._unquarantine(finding) is finding
|
|
|
|
|
|
def test_a_finding_with_no_latest_is_never_narrowed(monkeypatch):
|
|
monkeypatch.setattr(check, "installable_latest", _explode)
|
|
finding = Finding(_dep(), Severity.UNKNOWN, None)
|
|
assert check._unquarantine(finding) is finding
|
|
|
|
|
|
def test_an_undeterminable_narrowing_leaves_the_finding_alone(monkeypatch):
|
|
monkeypatch.setattr(check, "installable_latest", lambda _n, _c: None)
|
|
finding = Finding(_dep(pinned="16.1.0"), Severity.STALE, "16.3.3")
|
|
assert check._unquarantine(finding) is finding
|
|
|
|
|
|
def test_a_clean_run_never_pays_for_the_full_document(repo, monkeypatch,
|
|
cache_dir):
|
|
"""The full packument is 7MB for react; it must not be fetched when
|
|
everything is already current."""
|
|
monkeypatch.setattr(check, "installable_latest", _explode)
|
|
monkeypatch.setattr("dep_freshness.resolve._fetch",
|
|
lambda _e, _n: "19.2.8")
|
|
write(repo, "package.json", '{"dependencies": {"react": "19.2.8"}}')
|
|
monkeypatch.chdir(repo)
|
|
assert check.main(["--all"]) == 0
|
|
|
|
|
|
def _explode(*_args):
|
|
raise AssertionError("the full packument must not be fetched here")
|
|
|
|
|
|
def test_a_repo_pinned_to_the_newest_installable_version_passes(
|
|
repo, monkeypatch, cache_dir
|
|
):
|
|
"""End to end: the only finding is a release pnpm would refuse, so the
|
|
gate must exit 0 rather than demand a version that cannot be installed."""
|
|
monkeypatch.setattr("dep_freshness.resolve._fetch", lambda _e, _n: "16.3.3")
|
|
monkeypatch.setattr(check, "installable_latest", lambda _n, _c: "16.3.2")
|
|
write(repo, "package.json",
|
|
'{"dependencies": {"@testing-library/react": "16.3.2"}}')
|
|
monkeypatch.chdir(repo)
|
|
assert check.main(["--all"]) == 0
|
|
|
|
|
|
def test_the_answer_is_cached_so_a_second_run_makes_no_request(packument,
|
|
cache_dir):
|
|
"""A 7MB packument per npm finding, per run, inside a pre-commit hook is
|
|
exactly what the 6h cache exists to prevent."""
|
|
from dep_freshness.cache import Cache
|
|
|
|
store = Cache(cache_dir / "registry.json")
|
|
packument(PACKUMENT)
|
|
assert quarantine.installable_latest("x", "16.3.3", now=NOW,
|
|
cache=store) == "16.3.2"
|
|
|
|
packument(None) # any further fetch would now answer "no such package"
|
|
assert quarantine.installable_latest("x", "16.3.3", now=NOW,
|
|
cache=store) == "16.3.2"
|
|
|
|
|
|
def test_a_different_dist_tag_is_a_different_cache_entry(packument, cache_dir):
|
|
"""The ceiling is part of the key: clamping a cached answer to it would
|
|
return the ceiling, which is often the release being excluded."""
|
|
from dep_freshness.cache import Cache
|
|
|
|
store = Cache(cache_dir / "registry.json")
|
|
packument(PACKUMENT)
|
|
assert quarantine.installable_latest("x", "16.3.2", now=NOW,
|
|
cache=store) == "16.3.2"
|
|
assert store.get(quarantine.CACHE_ECOSYSTEM, "x@16.3.3") is None
|
|
|
|
|
|
def test_a_stale_cache_entry_is_served_when_the_registry_is_down(packument,
|
|
cache_dir):
|
|
from dep_freshness.cache import Cache
|
|
from dep_freshness.registries.http import Offline
|
|
|
|
store = Cache(cache_dir / "registry.json")
|
|
store.put(quarantine.CACHE_ECOSYSTEM, "x@16.3.3", "16.3.2")
|
|
store._data[f"{quarantine.CACHE_ECOSYSTEM}/x@16.3.3"]["fetched_at"] = 0.0
|
|
|
|
def down(*_a, **_k):
|
|
raise Offline("no network")
|
|
|
|
monkey = down
|
|
import dep_freshness.quarantine as q
|
|
original, q.get_json = q.get_json, monkey
|
|
try:
|
|
assert q.installable_latest("x", "16.3.3", cache=store) == "16.3.2"
|
|
finally:
|
|
q.get_json = original
|