railiance-apps/tools/reuse-forgejo-webhook.sh
tegwick 0da83472c4
All checks were successful
CI Smoke / host-smoke (push) Successful in 1s
CI Smoke / container-smoke (push) Successful in 5s
Default railiance01 kubeconfig to config-railiance01
config-hosteurope names port 16443, but the k3s-api-railiance01
ops-bridge tunnel listens on 16444, so every default target failed
with connection refused. Switch Makefile, tools and docs to
~/.kube/config-railiance01 and fix the restore recipe to rewrite the
API address to the tunnel port. The node-side hostPath in STATE.md is
unrelated and unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 1031639@bnt-lap001
Assistant-Session: e5073fee-f4ae-4fc3-a75a-6c1fc83e0576
2026-10-17 11:46:40 +02:00

80 lines
No EOL
2.6 KiB
Bash
Executable file

#!/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-railiance01}"
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