#!/usr/bin/env bash # Idempotent org-level Forgejo webhook for reuse-surface hub recompose (REUSE-WP-0019-T03). # Reads the HMAC secret from the live cluster Secret — never prints it. set -euo pipefail FORGEJO_API="${FORGEJO_API:-https://forgejo.coulomb.social/api/v1}" FORGEJO_ORG="${FORGEJO_ORG:-coulomb}" WEBHOOK_URL="${REUSE_WEBHOOK_URL:-https://reuse.coulomb.social/v1/webhooks/forgejo}" KUBECONFIG_PATH="${KUBECONFIG:-$HOME/.kube/config-hosteurope}" SECRET_NS="${REUSE_SECRET_NAMESPACE:-reuse}" SECRET_NAME="${REUSE_SECRET_NAME:-reuse-surface-env}" SECRET_KEY="${REUSE_WEBHOOK_SECRET_KEY:-REUSE_SURFACE_FORGEJO_WEBHOOK_SECRET}" TOKEN_FILE="${FORGEJO_TOKEN_FILE:-/tmp/forgejo-tegwick-api-token}" if [[ -n "${FORGEJO_ADMIN_TOKEN:-}" ]]; then TOKEN="${FORGEJO_ADMIN_TOKEN}" elif [[ -f "${TOKEN_FILE}" ]]; then TOKEN="$(cat "${TOKEN_FILE}")" else echo "Set FORGEJO_ADMIN_TOKEN or create ${TOKEN_FILE}" >&2 exit 1 fi WEBHOOK_SECRET="$( kubectl --kubeconfig "${KUBECONFIG_PATH}" get secret "${SECRET_NAME}" -n "${SECRET_NS}" \ -o "jsonpath={.data.${SECRET_KEY}}" | base64 -d )" if [[ -z "${WEBHOOK_SECRET}" ]]; then echo "Missing ${SECRET_KEY} in ${SECRET_NS}/${SECRET_NAME}" >&2 exit 1 fi export FORGEJO_API FORGEJO_ORG WEBHOOK_URL TOKEN WEBHOOK_SECRET python3 <<'PY' import json import os import urllib.error import urllib.request api = os.environ["FORGEJO_API"].rstrip("/") org = os.environ["FORGEJO_ORG"] url = os.environ["WEBHOOK_URL"] token = os.environ["TOKEN"] secret = os.environ["WEBHOOK_SECRET"] headers = {"Authorization": f"token {token}"} def api_json(method: str, path: str, payload: dict | None = None): data = None if payload is None else json.dumps(payload).encode() req = urllib.request.Request( f"{api}{path}", data=data, headers={**headers, **({} if payload is None else {"Content-Type": "application/json"})}, method=method, ) with urllib.request.urlopen(req) as resp: return json.load(resp) hooks = api_json("GET", f"/orgs/{org}/hooks") for hook in hooks: cfg = hook.get("config") or {} if cfg.get("url") == url and hook.get("active") and "push" in (hook.get("events") or []): print(f"==> Forgejo org webhook already configured (id={hook['id']})") raise SystemExit(0) created = api_json( "POST", f"/orgs/{org}/hooks", { "type": "gitea", "config": { "url": url, "content_type": "json", "secret": secret, }, "events": ["push"], "active": True, }, ) print(f"==> Forgejo org webhook created (id={created['id']}) -> {url}") PY