From 21b8ebfc8c47748e19a43d230ecc176d01e3cb83 Mon Sep 17 00:00:00 2001 From: Agando Date: Tue, 27 Oct 2026 17:28:56 +0100 Subject: feat(docs): tag builds, feed the changelog to machines, fail maintenance when it ages MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Tasks 3, 4, 5, 6, 7 of the changelog plan. - 67 build tags (v4.6.10 … v4.6.119) now exist, so a build is a ref instead of something that has to be re-inferred: `git log v4.6.118..v4.6.119` finally means something. - The generator prefers tags, but via ONE `git for-each-ref` pass rather than a `git describe` per commit. That matters: describe-per-commit made the build 2.4-2.7 s against a 1.0-1.45 s baseline — i.e. tags made it slower, which the plan's gate said to treat as "tags bought nothing". The right fix was a bulk lookup, not dropping the tags: now 0.80-1.04 s (median 0.84 s) with output byte-identical to the untagged baseline (68 entries, same version order). - changelog.json + feed.xml (Atom) are generated from the same page dict: 36 KB / 21 KB, 68/68 entries, both HTTP 200, item markup stripped so a reader gets text not HTML. - check_changelog() now also asserts the page was GENERATED recently, not merely that its version matches: a version match survives a dead cron forever. Seeded a 26-day-old timestamp -> "FAIL: changelog: generated 640h ago (>48h) - the daily job is not running", maintenance FAIL; restored -> "PASS: changelog age 0.1h", maintenance OK. - The exact cron pre-script was run end to end, not a stand-in: MAINTENANCE (--fix) block prints "PASS: changelog: changelog current: v4.6.119 (68 entries)" and "PASS: changelog age 0.2h", result OK, no second cron created. - Scale trigger written into the generator's docstring (split by year at ~150 builds), not built. - Mobile re-checked after the page gained the deep-link note: changelog + board both ALL VIEWPORTS OK at 360/390 px, light and dark. --- scripts/newos4-maintain.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'scripts/newos4-maintain.py') diff --git a/scripts/newos4-maintain.py b/scripts/newos4-maintain.py index 8cc7c5a..01cc986 100644 --- a/scripts/newos4-maintain.py +++ b/scripts/newos4-maintain.py @@ -5,6 +5,7 @@ import glob, json, os, re, subprocess, sys from datetime import datetime, timezone ROOT = '/var/www/webx11.duckdns.org/spaces/newos4' +PAGE = '/var/www/webx11.duckdns.org/spaces/agando/downloads/changelog.html' WEB = 'https://webx11.duckdns.org/spaces/newos4' FIX = '--fix' in sys.argv DEEP = '--deep' in sys.argv @@ -134,6 +135,23 @@ def check_changelog(): r = run([sys.executable, script, '--check'], cwd=ROOT) if r.returncode == 0: add('PASS', 'changelog: ' + (r.stdout.strip() or 'current')) + # A version match is not freshness: if the cron dies, the page and the build stay in + # agreement forever while the page stops being regenerated. + import datetime as _dt + m = re.search(r'"generated"\s*:\s*"([^"]+)"', open(PAGE, encoding='utf-8').read()) + if not m: + add('FAIL', 'changelog: page has no generated timestamp') + return + try: + gen = _dt.datetime.strptime(m.group(1), '%Y-%m-%dT%H:%M:%SZ').replace(tzinfo=_dt.timezone.utc) + except ValueError: + add('FAIL', 'changelog: unreadable generated timestamp ' + m.group(1)) + return + age_h = (_dt.datetime.now(_dt.timezone.utc) - gen).total_seconds() / 3600.0 + if age_h > 48: + add('FAIL', 'changelog: generated %.0fh ago (>48h) - the daily job is not running' % age_h) + else: + add('PASS', 'changelog age %.1fh' % age_h) return stale = (r.stdout or r.stderr).strip().splitlines() stale = stale[-1][:150] if stale else 'stale' -- cgit v1.2.3