"""How far behind origin/main the running build is. Hits Gitea's compare endpoint with a short per-SHA cache. Network errors return None and the footer just hides the status — the SHA itself still renders, so a flaky git host never breaks the page. """ import logging import time import requests _GITEA_REPO_API = "https://git.moritz.run/api/v1/repos/moritz/lazyflat" _CACHE_TTL = 60.0 _HTTP_TIMEOUT = 1.5 _cache: dict[str, tuple[int, float]] = {} logger = logging.getLogger("web.version") def commits_behind_main(sha: str) -> int | None: """Return how many commits `sha` is behind origin/main, or None on error/dev.""" if not sha or sha == "dev": return None now = time.monotonic() cached = _cache.get(sha) if cached and (now - cached[1]) < _CACHE_TTL: return cached[0] try: r = requests.get(f"{_GITEA_REPO_API}/compare/{sha}...main", timeout=_HTTP_TIMEOUT) r.raise_for_status() behind = int(r.json().get("total_commits", 0)) except (requests.RequestException, ValueError, KeyError) as e: logger.debug("commits_behind_main fetch failed: %s", e) return cached[0] if cached else None _cache[sha] = (behind, now) return behind