#!/usr/bin/env python3 """Gitea release webhook -> spawn deploy script. Socket-activated (systemd Accept=yes + StandardInput/Output=socket + KillMode=process — without KillMode=process the spawn is killed when this handler exits).""" import hmac, hashlib, json, os, subprocess, sys SECRET_FILE = os.path.expanduser("~/.config/kanbante-webhook-secret") DEPLOY = "/home/bruno/bin/deploy-on-release.sh" LOG = os.path.expanduser("~/.local/state/kanbante-deploy.log") f = sys.stdin.buffer f.readline() # POST / HTTP/1.1 hdrs = {} while True: line = f.readline() if line in (b"\r\n", b"\n", b""): break k, _, v = line.decode(errors="replace").partition(":") hdrs[k.strip().lower()] = v.strip() raw = f.read(int(hdrs.get("content-length", 0))) if hdrs.get("content-length") else b"" def reply(code, msg): sys.stdout.write(f"HTTP/1.1 {code} {msg}\r\nContent-Length: 0\r\nConnection: close\r\n\r\n") sys.stdout.flush() if hdrs.get("x-gitea-event") != "release": sys.exit(0) secret = open(SECRET_FILE, "rb").read().strip() sig = hdrs.get("x-gitea-signature", "") if not hmac.compare_digest(sig, hmac.new(secret, raw, hashlib.sha256).hexdigest()): reply("401", "Unauthorized") sys.exit(1) try: rel = json.loads(raw)["release"] if rel.get("action", "published") != "published": sys.exit(0) tag = rel["tag_name"] except Exception: sys.exit(0) reply("202", "Accepted") open(LOG, "a").write(f"{__import__('datetime').datetime.now().astimezone().isoformat()} webhook: release {tag}\n") env = dict(os.environ, DEPLOY_TAG=tag) subprocess.Popen([DEPLOY], env=env, stdout=open(LOG, "a"), stderr=subprocess.STDOUT)