release 1.13.4: monpages race-proof publish and content checks

Avoid false TOP/content ERRORs from mid-publish races: atomic HTML
write, rsync --delay-updates + settle, monpages fetch retries with
larger head windows, pre-publish soft content, bootstrap markers.
This commit is contained in:
Hernâni Marques 2026-07-19 02:55:56 +02:00
parent d5213adb7a
commit e450470429
No known key found for this signature in database
GPG key ID: CB5738652768F7E9
5 changed files with 179 additions and 73 deletions

View file

@ -5,6 +5,7 @@ from __future__ import annotations
import argparse
import html
import re
import os
from datetime import datetime, timezone
from pathlib import Path
@ -27,6 +28,22 @@ def format_generated_now() -> tuple[str, str]:
generated_at = now.strftime("%Y-%m-%d %H:%M:%S") + f" {tz_name}"
return generated_at, generated_iso
def atomic_write_text(path: Path, text: str, encoding: str = "utf-8") -> None:
"""Write file atomically (tmp + replace) so monpages never curls a half-written page."""
path = Path(path)
path.parent.mkdir(parents=True, exist_ok=True)
tmp = path.with_name(f".{path.name}.tmp.{os.getpid()}")
try:
tmp.write_text(text, encoding=encoding)
os.replace(tmp, path)
finally:
if tmp.exists():
try:
tmp.unlink()
except OSError:
pass
def ui_lang(explicit: str = "") -> str:
"""en (default) or fr. Env: TALER_MON_LANG; auto fr for lefrancpaysan hosts."""
import os
@ -1901,8 +1918,7 @@ def main() -> None:
suite_version_url=getattr(args, "suite_version_url", "") or "",
)
args.out.parent.mkdir(parents=True, exist_ok=True)
args.out.write_text(html_out, encoding="utf-8")
atomic_write_text(args.out, html_out, encoding="utf-8")
print(f"wrote {args.out} (errors={n_err} warnings={n_warn} level={status_level(n_err, n_warn)})")