aboutsummaryrefslogtreecommitdiff
path: root/scripts/newos4-maintain.py
diff options
context:
space:
mode:
authorAgando <roduccomm@gmail.com>2026-10-27 17:18:30 +0100
committerAgando <roduccomm@gmail.com>2026-10-27 17:18:30 +0100
commit7165c9eeccce44d4cd83194de5a200973e80c45a (patch)
tree8cd17a397999c18c2008407e5eeff2acd1b2b9e3 /scripts/newos4-maintain.py
parent4251edccc2e4fa587b26e908b301283cc94ae651 (diff)
feat(docs): generate the changelog from git and keep it current in maintenance
The page at spaces/agando/downloads/changelog.html was hand-built from VFS notes by the in-page agent: 11 entries, huge honest holes ("v4.6.59 - v4.6.100 unknown"), and it had stopped at v4.6.101 while the app was running v4.6.119. A docs page that lags the release reads as current, which is worse than no page. - scripts/build-changelog.py derives every entry from git: it walks commits touching spaces/newos4, stamps each with the LATEST_VER that was live at that commit, and groups them into builds. Kinds map onto the page's own vocabulary (feat->release, fix->fix, test->review, docs->docs, chore/style/refactor->project), and a build's chip is its dominant kind. Commits whose prefix carries `backticks` render as <code>, escaped first. - The page is its own template: everything visible comes from the #changelog-data JSON island, so regeneration swaps the island and refreshes the two prose blocks that described the VFS-only source. No second copy of the CSS or the 296-line renderer. - Every unshowable thing is stated, not smoothed: commits before the first version stamp become one "before v4.6.10" bucket, build numbers that were bumped twice before a commit are called out as absent, and the page says entries summarise subjects, not diffs. - CHANGELOG.md is generated from the same data between markers (app-scoped; the root CHANGELOG.md documents the platform's 0.2.x line and is left alone). - newos4-maintain.py gains check_changelog(): FAIL when the page's build differs from LATEST_VER, regenerate under --fix, PASS when current. So the daily 07:15 job keeps the docs in step with the build instead of relying on someone remembering. Verification: - build: 68 entries, 158 commits, v4.6.10 - v4.6.119, page 63 327 bytes, CHANGELOG.md 15 840. - live page renders 68 entries with kind chips, search, per-build anchors ("Copy a direct link to v4.6.119"), "68 of 68". - stale detection proved by bumping LATEST_VER to v4.6.120 without rebuilding: "FAIL: changelog changelog stale: page says v4.6.119, build is v4.6.120"; --fix then "PASS: changelog regenerated: ... v4.6.10 - v4.6.120"; version reverted, page back to 119. - maintain: PASS node tests 20/20, PASS changelog current: v4.6.119 (68 entries), result OK. - mobile: verify-mobile.py at 360/390 px, light+dark -> ALL VIEWPORTS OK, 0 overflow.
Diffstat (limited to 'scripts/newos4-maintain.py')
-rw-r--r--scripts/newos4-maintain.py29
1 files changed, 28 insertions, 1 deletions
diff --git a/scripts/newos4-maintain.py b/scripts/newos4-maintain.py
index c28fb8b..8cc7c5a 100644
--- a/scripts/newos4-maintain.py
+++ b/scripts/newos4-maintain.py
@@ -119,6 +119,33 @@ def check_course():
r = run([sys.executable, 'scripts/course-validate.py'], cwd=ROOT)
add('PASS' if r.returncode == 0 else 'FAIL', 'course ' + ('valid' if r.returncode == 0 else 'INVALID: ' + r.stdout[-160:]))
+def check_changelog():
+ """The changelog page must describe the build that is actually running.
+
+ docs/changelog.html was hand-built from VFS notes and had stopped at v4.6.101 while
+ the app was on v4.6.119 -- a docs page that lags the release is worse than no page,
+ because it reads as current. build-changelog.py derives every entry from git, so the
+ only thing left to check is whether it has been run since the last version bump.
+ """
+ script = os.path.join(ROOT, 'scripts/build-changelog.py')
+ if not os.path.exists(script):
+ add('FAIL', 'changelog: scripts/build-changelog.py missing')
+ return
+ r = run([sys.executable, script, '--check'], cwd=ROOT)
+ if r.returncode == 0:
+ add('PASS', 'changelog: ' + (r.stdout.strip() or 'current'))
+ return
+ stale = (r.stdout or r.stderr).strip().splitlines()
+ stale = stale[-1][:150] if stale else 'stale'
+ if FIX:
+ r2 = run([sys.executable, script], cwd=ROOT)
+ if r2.returncode == 0:
+ add('PASS', 'changelog regenerated: ' + (r2.stdout.strip()[:130] or 'ok'))
+ return
+ add('FAIL', 'changelog regen failed: ' + (r2.stderr.strip()[:150] or '?'))
+ return
+ add('FAIL', 'changelog ' + stale)
+
def check_help_coverage():
"""Every command the code registers must appear in help.html (2026-10-22).
@@ -188,7 +215,7 @@ def check_links():
def main():
os.chdir(ROOT)
bad = syntax_failures() # computed once, gates the bundle rebuild
- check_versions(); check_syntax(bad); check_regression_tests(); check_bundles(bad); check_perms(); check_index(); check_data(); check_live(); check_atlas(); check_course(); check_help_coverage(); check_links()
+ check_versions(); check_syntax(bad); check_regression_tests(); check_bundles(bad); check_perms(); check_index(); check_data(); check_live(); check_atlas(); check_course(); check_help_coverage(); check_links(); check_changelog()
fails = [m for l, m in issues if l == 'FAIL']
print('newOS4 maintenance — ' + datetime.now(timezone.utc).strftime('%Y-%m-%d %H:%MZ') + (' [fix]' if FIX else '') + (' [deep]' if DEEP else ''))
for l, m in issues: print(f'{l}: {m}')