From 7c03cc01de94a4b64e3c4de39f6d44e401b7db60 Mon Sep 17 00:00:00 2001 From: Agando Date: Sun, 18 Oct 2026 17:01:52 +0200 Subject: newOS4 v4.6.37: bug-report pipeline (report.php, bug command, HTML generator, telemetry-loop fix) --- scripts/gen-bug-report.py | 132 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 132 insertions(+) create mode 100644 scripts/gen-bug-report.py (limited to 'scripts/gen-bug-report.py') diff --git a/scripts/gen-bug-report.py b/scripts/gen-bug-report.py new file mode 100644 index 0000000..f995bfc --- /dev/null +++ b/scripts/gen-bug-report.py @@ -0,0 +1,132 @@ +#!/usr/bin/env python3 +"""Generate a deterministic BUG-REPORT.html from data/reports/*.json. + +Every field is HTML-escaped; the page is self-contained (no external assets). +Output is stable for a given set of reports — no wall-clock timestamps. +""" +import glob +import html +import json +import os +import sys + +ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) +REPORTS_DIR = os.path.join(ROOT, "data", "reports") +OUT_FILE = os.path.join(ROOT, "downloads", "bugs", "BUG-REPORT.html") +MAX_REPORTS = 200 + + +def esc(value): + return html.escape("" if value is None else str(value), quote=True) + + +def load_reports(): + rows = [] + for path in sorted(glob.glob(os.path.join(REPORTS_DIR, "RPT-*.json"))): + try: + with open(path, encoding="utf-8") as fh: + rec = json.load(fh) + if isinstance(rec, dict) and rec.get("id"): + rows.append(rec) + except (OSError, ValueError): + continue + rows.sort(key=lambda r: (str(r.get("created_at", "")), str(r.get("id", ""))), reverse=True) + return rows[:MAX_REPORTS] + + +def pretty(value, limit=6000): + try: + text = json.dumps(value, indent=2, ensure_ascii=False) + except (TypeError, ValueError): + text = str(value) + if len(text) > limit: + text = text[:limit] + "\n… (truncated)" + return esc(text) + + +def render(rows): + total = len(rows) + latest = esc(rows[0].get("created_at", "—")) if rows else "—" + cards = [] + + for rec in rows: + diag = rec.get("diagnostics") if isinstance(rec.get("diagnostics"), dict) else {} + errors = diag.get("errors") if isinstance(diag.get("errors"), list) else [] + cards.append( + f"""
+
+

{esc(rec.get('title', '(untitled)'))}

+ {esc(rec.get('id', ''))} +
+

{esc(rec.get('created_at', ''))} · version {esc(diag.get('version', 'unknown'))} · {len(errors)} error(s)

+ {f'

{esc(rec.get("body"))}

' if rec.get('body') else ''} +
+ Diagnostics +
{pretty(diag)}
+
+
""" + ) + + if not cards: + cards.append('

No reports yet. Run bug <title> in newOS4.

') + + return f""" + + + + +newOS4 — Bug Reports + + + +
+

🐞 newOS4 Bug Reports

+

Generated from data/reports/*.json — no manual edits.

+
+
{total}reports
+
{esc(latest)}latest report
+
+{chr(10).join(cards)} +
+ + +""" + + +def main(): + rows = load_reports() + page = render(rows) + os.makedirs(os.path.dirname(OUT_FILE), exist_ok=True) + with open(OUT_FILE, "w", encoding="utf-8") as fh: + fh.write(page) + os.chmod(OUT_FILE, 0o664) + print(f"wrote {OUT_FILE} ({len(rows)} report(s), {len(page)} bytes)") + return 0 + + +if __name__ == "__main__": + sys.exit(main()) -- cgit v1.2.3