Basis: Certvia dev@a48c5fb als Fundament für Craftvia
Unveränderter Stand von certvia/dev (a48c5fb) plus Craftvia-Spezifikation und Brandbook unter docs/craftvia/. ISMS-Module werden im Folgecommit entfernt. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,79 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Regressionsschutz: Rendert alle Richtlinien in einer Framework-Sicht und vergleicht das
|
||||
Ergebnis mit einem Git-Stand. Erwartung fuer TISAX: 0 Abweichungen.
|
||||
|
||||
python3 _render_diff.py <git-revision> [--framework TISAX|ISO|BEIDE]
|
||||
|
||||
Beispiele:
|
||||
python3 _render_diff.py a9649b3 # TISAX-Sicht gegen den Stand vor dem ISO-Umbau
|
||||
python3 _render_diff.py dev --framework ISO # ISO-Sicht gegen dev
|
||||
|
||||
Verglichen wird der gerenderte Text ohne Leerzeilen und ohne Kommentar-Anker — also das,
|
||||
was ein Mandant tatsaechlich zu sehen bekommt.
|
||||
"""
|
||||
import difflib, glob, json, os, re, subprocess, sys
|
||||
|
||||
BASE = os.path.dirname(os.path.abspath(__file__))
|
||||
REPO = subprocess.run(["git", "rev-parse", "--show-toplevel"], cwd=BASE,
|
||||
capture_output=True, text=True).stdout.strip()
|
||||
|
||||
if len(sys.argv) < 2:
|
||||
print(__doc__); sys.exit(2)
|
||||
REV = sys.argv[1]
|
||||
FW = "TISAX"
|
||||
if "--framework" in sys.argv:
|
||||
FW = sys.argv[sys.argv.index("--framework") + 1].upper()
|
||||
|
||||
schema = json.load(open(os.path.join(BASE, "variables.schema.json"), encoding="utf-8"))
|
||||
|
||||
|
||||
def ctx():
|
||||
c = {k: (True if k.startswith("FLAG_") else "{%s}" % k) for k in schema["properties"]}
|
||||
for k in ["FLAG_OT_USED", "FLAG_DEV_INHOUSE", "FLAG_CRYPTO_PKI", "FLAG_CUSTOMER_SYSTEMS"]:
|
||||
c[k] = False
|
||||
c["FLAG_FW_TISAX"] = FW in ("TISAX", "BEIDE")
|
||||
c["FLAG_FW_ISO27001"] = FW in ("ISO", "BEIDE")
|
||||
return c
|
||||
|
||||
|
||||
def render(txt, c):
|
||||
pat = re.compile(r"\{\{#if (\w+)\}\}((?:(?!\{\{#if )(?!\{\{/if\}\}).)*?)\{\{/if\}\}", re.S)
|
||||
prev = None
|
||||
while prev != txt:
|
||||
prev = txt
|
||||
txt = pat.sub(lambda m: (m.group(2) if c.get(m.group(1)) else ""), txt)
|
||||
txt = re.sub(r"<!--.*?-->", "", txt, flags=re.S)
|
||||
txt = re.sub(r"\{\{LINK:([^}]+)\}\}", r"[\1]", txt)
|
||||
txt = re.sub(r"\{\{(\w+)\}\}", lambda m: str(c.get(m.group(1), "?")), txt)
|
||||
return [l.rstrip() for l in txt.split("\n") if l.strip()]
|
||||
|
||||
|
||||
def at_rev(relpath):
|
||||
r = subprocess.run(["git", "show", "%s:%s" % (REV, relpath)], cwd=REPO,
|
||||
capture_output=True, text=True)
|
||||
return r.stdout if r.returncode == 0 else None
|
||||
|
||||
|
||||
c = ctx()
|
||||
drift, missing, checked = 0, 0, 0
|
||||
for path in sorted(glob.glob(os.path.join(BASE, "richtlinien", "*.md"))):
|
||||
rel = os.path.relpath(path, REPO)
|
||||
old_raw = at_rev(rel)
|
||||
if old_raw is None:
|
||||
missing += 1
|
||||
print(" neu in dieser Fassung:", os.path.basename(path))
|
||||
continue
|
||||
checked += 1
|
||||
old, new = render(old_raw, c), render(open(path, encoding="utf-8").read(), c)
|
||||
if old != new:
|
||||
drift += 1
|
||||
print("ABWEICHUNG:", os.path.basename(path))
|
||||
for line in list(difflib.unified_diff(old, new, lineterm="", n=0))[:10]:
|
||||
print(" ", line[:140])
|
||||
|
||||
print()
|
||||
print("Sicht: %s · Vergleichsstand: %s" % (FW, REV))
|
||||
print("geprueft: %d Richtlinien, neu: %d, abweichend: %d" % (checked, missing, drift))
|
||||
print("OK" if drift == 0 else "PRUEFEN")
|
||||
sys.exit(0 if drift == 0 else 1)
|
||||
Reference in New Issue
Block a user