diff --git a/README.md b/README.md index bc3fd5c..4652c35 100644 --- a/README.md +++ b/README.md @@ -53,6 +53,28 @@ is not tied to any one subscription: another Hermes route needs a `/gitea/`, and no relay change. Route names are validated against a strict charset before being used in the outbound URL. +Neither provisioning unit deletes anything: Jupiter's only creates or updates +its own hook, and Mars's only removes the route it is about to re-subscribe. +Retiring the pre-rename `gitea-events` route is therefore a one-off, done by +hand after the first deploy of both hosts: + +``` +# on mars — drop the old subscription +sudo podman exec hermes-agent hermes webhook remove gitea-events + +# on jupiter — delete the old hook (it posts to the relay's bare /gitea path) +api=http://127.0.0.1:3000/api/v1; repo=darman/homelab +tok="$(sudo cat /run/secrets/gitea_provisioning_token)" +old="$(curl -fsS -H "Authorization: token $tok" "$api/repos/$repo/hooks" \ + | jq -r '.[] | select(.config.url == "http://mars.orbit.sol:8645/gitea") | .id')" +for id in $old; do + curl -fsS -H "Authorization: token $tok" -X DELETE "$api/repos/$repo/hooks/$id" +done +``` + +Check `hermes webhook list` and the repo's webhook page afterwards; until the +old hook is gone both it and the new one fire, so events arrive twice. + That one header copy is the entire reason the relay exists. Gitea signs every webhook with `X-Hub-Signature-256` in GitHub's exact format, which Hermes already accepts on any route — so authentication would work pointing Gitea diff --git a/services/dev/gitea-hermes-webhook-relay.nix b/services/dev/gitea-hermes-webhook-relay.nix index db2cd84..d47dfbe 100644 --- a/services/dev/gitea-hermes-webhook-relay.nix +++ b/services/dev/gitea-hermes-webhook-relay.nix @@ -138,11 +138,10 @@ in sleep 1 done - # gitea-events is the old name of this route (renamed to say what it - # actually handles); removing it keeps a redeployed host from serving - # both. The second remove is the idempotency step for the subscribe - # below, not cleanup. - podman exec hermes-agent hermes webhook remove gitea-events >/dev/null 2>&1 || true + # Idempotency for the subscribe below, not cleanup: this removes only + # the route this unit owns. The pre-rename gitea-events subscription is + # left alone — retiring it is a one-off migration done by hand, so that + # a redeploy never silently deletes a route someone added on purpose. podman exec hermes-agent hermes webhook remove gitea-pr-comments >/dev/null 2>&1 || true # `set -eu` inside the container shell is load-bearing: without it a # missing prompt file makes `cat` fail, the command substitution yields diff --git a/services/dev/gitea.nix b/services/dev/gitea.nix index fd10e55..ff21b02 100644 --- a/services/dev/gitea.nix +++ b/services/dev/gitea.nix @@ -338,11 +338,10 @@ in relay="http://mars.orbit.sol:8645" target="$relay/gitea/gitea-pr-comments" - # Retire the pre-rename hook, which posted to the relay's bare path and - # would now double-deliver alongside $target. Matched by its EXACT old - # URL, deliberately: anything else pointing at $relay is a hook for a - # different Hermes route and must survive. - legacy_target="$relay/gitea" + # This unit only ever creates or updates $target. It deliberately does + # NOT delete anything, including the pre-rename hook on the relay's bare + # path — that is a one-off migration, done by hand, not a thing this + # runs on every boot. See the README for the command. # Same readiness gate as gitea-ci-bot-provision / gitea-luna-provision # above: After=gitea.service only means the process started, not that it @@ -361,14 +360,7 @@ in --argjson events '${builtins.toJSON giteaWebhookEvents}' \ '{type: "gitea", config: {content_type: "json", url: $url, secret: $secret}, events: $events, active: true}')" - hooks="$(curl -fsS "''${auth[@]}" "$api/repos/darman/homelab/hooks")" - - for stale in $(printf '%s' "$hooks" \ - | jq -r --arg url "$legacy_target" '.[] | select(.type == "gitea" and .config.url == $url) | .id'); do - curl -fsS "''${auth[@]}" -X DELETE "$api/repos/darman/homelab/hooks/$stale" >/dev/null - done - - hook_id="$(printf '%s' "$hooks" \ + hook_id="$(curl -fsS "''${auth[@]}" "$api/repos/darman/homelab/hooks" \ | jq -r --arg url "$target" 'first(.[] | select(.type == "gitea" and .config.url == $url)) | .id // empty')" if [ -n "$hook_id" ]; then printf '%s' "$body" | curl -fsS "''${auth[@]}" -H 'Content-Type: application/json' \