Files
pw/scripts/omstempl.py
T
Asger Geel WeirsøeandClaude Opus 5.5 e58a11c2b4 feat: flyt sitet fra Astro til Zola
Samme indhold, URL'er og udseende, bygget af en enkelt zola-binær og Tailwind
standalone-CLI uden Node. Kanonisk domæne er asger.weirsoe.dk.

Blogindlæg ligger som page bundles med frontmatter Zola forstår, så de gamle
stempler er ugyldige, indtil scripts/omstempl.py er kørt med PUBLISH_KEY.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 16:47:08 +01:00

104 lines
4.1 KiB
Python
Executable File

#!/usr/bin/env python3
"""Stempler de udgivne indlæg om efter flytningen fra src/content/blog/<slug>.md til
content/blog/<slug>/index.md. Stien og frontmatter indgår i stemplet, så de gamle er ugyldige.
Kør på zola-branchen, med master stadig på Astro-versionen:
PUBLISH_KEY=<hex> python3 scripts/omstempl.py [--fra master]
PUBLISH_KEY=<hex> python3 scripts/verify-approvals.py
git commit -am "blog: stempl indlæg om efter flytning til Zola"
Scriptet underskriver kun det der allerede var godkendt. For hvert indlæg tjekker det at
det gamle stempel er gyldigt, og at den nye fil er præcis den gamle i nyt format. Fejler
ét indlæg, skrives der intet.
"""
import argparse
import hashlib
import hmac
import os
import re
import subprocess
import sys
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
from godkendelse import BLOG, assets_for, read_text, sign, stamp_of # noqa: E402
OLD = "src/content/blog"
def git(*args, binary=False):
return subprocess.run(["git", *args], check=True, capture_output=True, text=not binary).stdout
def old_sign(key, rel, text, assets):
"""Det gamle format: stemplet stod som topniveau-linje og er det eneste der skæres fra."""
lines = text.replace("\r\n", "\n").split("\n")
end = lines.index("---", 1)
lines = [l for i, l in enumerate(lines) if not (0 < i < end and l.startswith("godkendt:"))]
tail = "".join(f"\n@asset {p} {h}" for p, h in assets)
body = f"{rel}\n" + "\n".join(lines) + tail
return "v1:" + hmac.new(key, body.encode(), hashlib.sha256).hexdigest()
def migrated(text, stamp):
"""Den gamle fil i det nye format: tags under taxonomies, stemplet under extra."""
lines = text.split("\n")
end = lines.index("---", 1)
head = []
for l in lines[1:end]:
if l.startswith("godkendt:"):
continue
head += ["taxonomies:", " " + l] if l.startswith("tags:") else [l]
return "\n".join(["---", *head, "extra:", f' godkendt: "{stamp}"', *lines[end:]])
def old_assets(ref, slug):
out = git("ls-tree", "--name-only", ref, f"{OLD}/{slug}/").split()
return sorted((p, hashlib.sha256(git("show", f"{ref}:{p}", binary=True)).hexdigest()) for p in out)
def main():
ap = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter)
ap.add_argument("--fra", default="master", help="ref med de gamle, godkendte indlæg")
args = ap.parse_args()
if not os.environ.get("PUBLISH_KEY"):
sys.exit("PUBLISH_KEY mangler.")
key = bytes.fromhex(os.environ["PUBLISH_KEY"])
slugs = sorted(n for n in os.listdir(BLOG) if os.path.isdir(f"{BLOG}/{n}"))
new, errors = {}, []
for slug in slugs:
rel = f"{BLOG}/{slug}/index.md"
old_rel = f"{OLD}/{slug}.md"
try:
old = git("show", f"{args.fra}:{old_rel}")
except subprocess.CalledProcessError:
errors.append(f"{rel}: findes ikke i {args.fra} som {old_rel}; kun godkendelsesflowet må stemple nyt")
continue
text = read_text(rel)
stamp_gl, draft = stamp_of(old)
o_assets = old_assets(args.fra, slug)
n_assets = assets_for(slug)
if draft or not stamp_gl or not hmac.compare_digest(stamp_gl, old_sign(key, old_rel, old, o_assets)):
errors.append(f"{old_rel}: det gamle stempel er ikke gyldigt med denne nøgle")
continue
if text != migrated(old, stamp_of(text)[0]):
errors.append(f"{rel}: indholdet er ændret i forhold til {args.fra}")
continue
if [h for _, h in o_assets] != [h for _, h in n_assets]:
errors.append(f"{rel}: billederne er ændret i forhold til {args.fra}")
continue
new[rel] = migrated(old, sign(key, rel, text, n_assets))
if errors:
print("\n".join(f"✗ {e}" for e in errors), file=sys.stderr)
sys.exit(f"\n{len(errors)} fejl. Intet er skrevet.")
for rel, text in new.items():
with open(rel, "w", encoding="utf-8", newline="") as f:
f.write(text)
print(f"✓ {rel}")
print(f"\n{len(new)} indlæg stemplet om. Kør scripts/verify-approvals.py og commit.")
if __name__ == "__main__":
main()