pilot: central webhook service (user-level Gitea webhook + AI-REVIEW gate)
- pilot/webhook_server.py: stdlib HTTP receiver. HMAC-verifies X-Gitea-Signature, gates on pull_request action + AI-REVIEW label, runs review_pr in a background thread (responds 202 immediately so Gitea's delivery timeout never fires). Accepts both GitHub-style (labeled/synchronize) and Gitea event-type-style (label_updated/synchronized) action names. - pilot/ai_review.py: extract review_pr() core so both the CI run() and the webhook server share one review path. run() is now an env-driven wrapper. - pilot/README-webhook.md: architecture, onboarding, one-time per-owner user-webhook setup, the Gitea 1.26.1 system-webhook bug, the SSRF ALLOWED_HOST_LIST change, K8s deploy + script-update recipe. - README.md + design doc: note the webhook service as the preferred delivery path (partially reverses 'central webhook = non-goal', pilot only). Gitea 1.26.1 system webhooks broken (POST /admin/hooks -> 201 but never persists); user-level webhooks (one per repo-owner) are the working fallback. Gitea SSRF allow-list blocks in-cluster webhook targets by default; required a scoped [webhook] ALLOWED_HOST_LIST addition + gitea restart. E2E verified 2026-08-17: pragent-bot reviewed gitea_admin/pragent PR #2 and masi/portfolio PR #3 via the webhook service (glm-5.2:cloud). Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -318,3 +318,26 @@ The pilot validates the delivery model (CI-step + bot user, not a central
|
||||
webhook) and the on-network provider path. When the framework build resumes,
|
||||
`pilot/ai_review.py` is replaced by `pragent review`; the per-repo workflow
|
||||
stays, just calling the CLI instead of curling the script. See `pilot/README.md`.
|
||||
|
||||
### Central webhook service (2026-08-17) — partially reverses the non-goal
|
||||
|
||||
User decision 2026-08-17: ship a central webhook service so "add the bot +
|
||||
label a PR" is the only per-repo action (no workflow file, no secret, no runner).
|
||||
This walks back the "central webhook service = non-goal" line above, for the
|
||||
pilot only — the framework's CLI-step delivery model is unchanged.
|
||||
|
||||
Implementation notes (see `pilot/README-webhook.md`):
|
||||
|
||||
- **Gitea 1.26.1 system webhooks are broken**: `POST /admin/hooks` returns `201`
|
||||
but the hook never persists (`GET /admin/hooks` lists 0, no delivery). The
|
||||
one-webhook-per-instance ideal is not achievable on this version. Fallback:
|
||||
**user-level webhooks** — one webhook per repo-owner, fires for every repo
|
||||
that user owns. Few owners on this instance, so near-equivalent.
|
||||
- **Gitea SSRF allow-list** blocks webhook delivery to in-cluster hosts by
|
||||
default; required a scoped `[webhook] ALLOWED_HOST_LIST` addition to
|
||||
`app.ini` (via the helm inline-config secret) + a gitea pod restart.
|
||||
- The webhook receiver (`pilot/webhook_server.py`, stdlib only) HMAC-verifies
|
||||
the delivery, gates on `AI-REVIEW` label + PR action, and calls the same
|
||||
`ai_review.review_pr()` core the CI-step uses — one review path, two triggers.
|
||||
- The bot stays a **normal user** (not site admin); it must be a Write
|
||||
collaborator on each reviewed repo.
|
||||
|
||||
Reference in New Issue
Block a user