diff --git a/check_goldens.py b/check_goldens.py new file mode 100644 index 0000000..09d13c0 --- /dev/null +++ b/check_goldens.py @@ -0,0 +1,80 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +check_goldens.py — C0 · goldens de non-régression du moteur +=========================================================== +Rend chaque golden_*.yaml présent et compare sa STRUCTURE (nb de +slides, nb de shapes par slide) au manifeste goldens_manifest.json. +Le PPTX contient des timestamps : un diff binaire est impossible — la +structure, elle, est déterministe et attrape les régressions de rendu +(shape manquante, layout cassé, exception). + + python3 check_goldens.py → vérifie (code retour 1 si écart) + python3 check_goldens.py --update → (re)génère le manifeste + +À lancer avant tout push moteur (ou en tâche DSM hebdo). +""" +import glob +import json +import subprocess +import sys +from pathlib import Path + +MANIFEST = Path("goldens_manifest.json") + + +def structure(pptx_path): + from pptx import Presentation + prs = Presentation(pptx_path) + return [len(list(s.shapes)) for s in prs.slides] + + +def render_all(): + out = {} + for y in sorted(glob.glob("golden_*.yaml")): + pptx = "_check_%s.pptx" % Path(y).stem + r = subprocess.run( + ["python3", "render_engine_v2.py", y, pptx, + "--assets", "assets"], + capture_output=True, text=True) + if r.returncode != 0: + print(" ! %s : le rendu ÉCHOUE\n%s" % (y, r.stdout[-400:])) + sys.exit(1) + out[y] = structure(pptx) + Path(pptx).unlink(missing_ok=True) + return out + + +def main(): + got = render_all() + if "--update" in sys.argv: + MANIFEST.write_text(json.dumps(got, indent=2)) + print(" + Manifeste écrit : %d goldens, %d slides au total." + % (len(got), sum(len(v) for v in got.values()))) + return + if not MANIFEST.exists(): + print(" ! Pas de manifeste — lancer d'abord : " + "python3 check_goldens.py --update") + sys.exit(1) + want = json.loads(MANIFEST.read_text()) + ok = True + for y, shapes in got.items(): + ref = want.get(y) + if ref is None: + print(" ~ %s : nouveau golden (absent du manifeste)" % y) + continue + if shapes != ref: + ok = False + print(" ! %s : ÉCART — slides/shapes %s ≠ attendu %s" + % (y, shapes, ref)) + for y in want: + if y not in got: + ok = False + print(" ! %s : golden du manifeste INTROUVABLE" % y) + print(" %s" % ("✓ goldens conformes (%d fichiers)" % len(got) + if ok else "✗ régression détectée")) + sys.exit(0 if ok else 1) + + +if __name__ == "__main__": + main() diff --git a/goldens_manifest.json b/goldens_manifest.json new file mode 100644 index 0000000..9e26dfe --- /dev/null +++ b/goldens_manifest.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/resilience_boot.sh b/resilience_boot.sh new file mode 100644 index 0000000..99cdf57 --- /dev/null +++ b/resilience_boot.sh @@ -0,0 +1,33 @@ +#!/bin/sh +# resilience_boot.sh — Résilience C2 · à planifier en tâche DSM +# « Au démarrage », utilisateur ROOT (recrée la règle sudoers). +# Rejouable sans risque (idempotent). Journalise dans resilience.log. + +BASE=/volume1/homes/Master/App/Sliding/python-pptx +LOG="$BASE/resilience.log" +TS=$(date '+%Y-%m-%d %H:%M:%S') + +# 1. Règle sudoers de la preview (sautée par les MAJ DSM majeures) +SUDOERS=/etc/sudoers.d/sliding-preview +if [ ! -f "$SUDOERS" ]; then + printf 'Master ALL=(root) NOPASSWD: %s/preview.sh\n' "$BASE" > "$SUDOERS" + chmod 440 "$SUDOERS" + echo "$TS [sudoers] regle sliding-preview RECREEE" >> "$LOG" +fi + +# 2. Purge des previews de plus de 30 jours (le disque du DS218 est petit) +N=$(find "$BASE/projets" -type d -name "*_previews" -mtime +30 2>/dev/null | wc -l) +if [ "$N" -gt 0 ]; then + find "$BASE/projets" -type d -name "*_previews" -mtime +30 -exec rm -rf {} + 2>/dev/null + echo "$TS [purge] $N dossier(s) de previews > 30j supprimes" >> "$LOG" +fi + +# 3. L'image docker de la preview a-t-elle survécu ? +DOCKER=/volume1/@appstore/ContainerManager/usr/bin/docker +if [ -x "$DOCKER" ]; then + if ! "$DOCKER" image inspect sliding-preview >/dev/null 2>&1; then + echo "$TS [docker] IMAGE sliding-preview ABSENTE — rebuild requis (voir fiche systeme Trilium)" >> "$LOG" + fi +else + echo "$TS [docker] demon/binaire docker indisponible" >> "$LOG" +fi