diff --git a/skills/devops/gitea-release-autodeploy/scripts/webhook-handler.py b/skills/devops/gitea-release-autodeploy/scripts/webhook-handler.py new file mode 100644 index 0000000..088f301 --- /dev/null +++ b/skills/devops/gitea-release-autodeploy/scripts/webhook-handler.py @@ -0,0 +1,43 @@ +#!/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)