feat(webhook): is_repo_enabled reads .pr-review.json:enabled

This commit is contained in:
claude
2026-08-22 01:24:10 +00:00
parent 86352a3771
commit 2c7d4803f1
2 changed files with 61 additions and 1 deletions
+28 -1
View File
@@ -34,14 +34,16 @@ Env:
(optional) request-body cap, default 10 MiB
"""
import base64
import hashlib
import hmac
import json
import os
import threading
import urllib.parse
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
from ai_review import review_pr
from ai_review import gitea_get, review_pr
try:
import feedback_harvest # optional — absent in CI-step pod, present in
@@ -109,6 +111,31 @@ def _labels_have_ai_review(labels) -> bool:
return _labels_have(labels, AI_REVIEW_LABEL)
def is_repo_enabled(api: str, repo: str, ref: str, token: str) -> bool:
"""True iff `.pr-review.json` on `ref` has `"enabled": true`.
Reads from the given ref (typically the PR's base ref). False on any
failure: 404, parse error, missing file, missing `enabled`, wrong type.
The bool-coerce of `.get("enabled") is True` rejects the common
gotchas (`null`, `1`, `"yes"`, missing field all yield False).
"""
code, raw = gitea_get(
api, repo,
"contents/.pr-review.json?ref=" + urllib.parse.quote(ref, safe=""),
token,
)
if code != 200:
return False
try:
data = json.loads(raw)
content_b64 = data.get("content", "").replace("\n", "")
decoded = base64.b64decode(content_b64).decode("utf-8", errors="replace")
cfg = json.loads(decoded)
except (json.JSONDecodeError, ValueError):
return False
return isinstance(cfg, dict) and cfg.get("enabled") is True
def _verify_signature(raw_body: bytes, headers) -> bool:
if not WEBHOOK_SECRET:
return False # refuse to run without a configured secret
+33
View File
@@ -1,4 +1,5 @@
"""Unit tests for the webhook receiver's gating, dedupe and limits. No network."""
import base64
import os
import sys
import threading
@@ -134,3 +135,35 @@ def test_missing_label_is_ignored(monkeypatch):
def test_review_slots_bound_matches_config():
assert ws.MAX_CONCURRENT >= 1
assert ws._review_slots._value <= ws.MAX_CONCURRENT
# ---------------------------------------------------------------------------
# is_repo_enabled — reads `.pr-review.json` from the PR base ref and parses
# its `enabled` flag. False on any failure (404, parse error, missing field).
# ---------------------------------------------------------------------------
def test_is_repo_enabled_returns_false_when_404(monkeypatch):
monkeypatch.setattr(
"webhook_server.gitea_get",
lambda *a, **kw: (404, b'{"message":"not found"}'),
)
assert ws.is_repo_enabled("api", "owner/repo", "main", "tok") is False
def test_is_repo_enabled_returns_true_when_enabled(monkeypatch):
body = b'{"content":"' + base64.b64encode(b'{"enabled": true}').decode().encode() + b'"}'
monkeypatch.setattr("webhook_server.gitea_get", lambda *a, **kw: (200, body))
assert ws.is_repo_enabled("api", "owner/repo", "main", "tok") is True
def test_is_repo_enabled_returns_false_when_disabled(monkeypatch):
body = b'{"content":"' + base64.b64encode(b'{"enabled": false}').decode().encode() + b'"}'
monkeypatch.setattr("webhook_server.gitea_get", lambda *a, **kw: (200, body))
assert ws.is_repo_enabled("api", "owner/repo", "main", "tok") is False
def test_is_repo_enabled_returns_false_when_field_missing(monkeypatch):
body = b'{"content":"' + base64.b64encode(b'{}').decode().encode() + b'"}'
monkeypatch.setattr("webhook_server.gitea_get", lambda *a, **kw: (200, body))
assert ws.is_repo_enabled("api", "owner/repo", "main", "tok") is False