switch to euphon org webhook, remove per-repo sync
This commit is contained in:
parent
9c9e634d65
commit
3c4a66183e
4
gitea.py
4
gitea.py
@ -114,13 +114,13 @@ class GiteaClient:
|
|||||||
|
|
||||||
return downloaded
|
return downloaded
|
||||||
|
|
||||||
async def list_user_repos(self, owner: str) -> list[dict]:
|
async def list_org_repos(self, org: str) -> list[dict]:
|
||||||
repos = []
|
repos = []
|
||||||
page = 1
|
page = 1
|
||||||
async with httpx.AsyncClient() as c:
|
async with httpx.AsyncClient() as c:
|
||||||
while True:
|
while True:
|
||||||
r = await c.get(
|
r = await c.get(
|
||||||
f"{self.base}/users/{owner}/repos?page={page}&limit=50",
|
f"{self.base}/orgs/{org}/repos?page={page}&limit=50",
|
||||||
headers=self.headers,
|
headers=self.headers,
|
||||||
)
|
)
|
||||||
r.raise_for_status()
|
r.raise_for_status()
|
||||||
|
|||||||
41
main.py
41
main.py
@ -4,8 +4,6 @@ import hmac
|
|||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
|
|
||||||
from contextlib import asynccontextmanager
|
|
||||||
|
|
||||||
from fastapi import FastAPI, Request, HTTPException
|
from fastapi import FastAPI, Request, HTTPException
|
||||||
|
|
||||||
import config
|
import config
|
||||||
@ -15,16 +13,16 @@ from workspace import ensure_repo, repo_path, attachments_path
|
|||||||
logging.basicConfig(level=logging.INFO, format="%(asctime)s %(levelname)s %(message)s")
|
logging.basicConfig(level=logging.INFO, format="%(asctime)s %(levelname)s %(message)s")
|
||||||
log = logging.getLogger("gitea-bot")
|
log = logging.getLogger("gitea-bot")
|
||||||
|
|
||||||
app = FastAPI(lifespan=lifespan)
|
|
||||||
gitea = GiteaClient()
|
gitea = GiteaClient()
|
||||||
|
|
||||||
ALLOWED_OWNER = "fam"
|
ALLOWED_OWNER = "euphon"
|
||||||
MAX_RESPONSE_LEN = 60000
|
MAX_RESPONSE_LEN = 60000
|
||||||
CLAUDE_TIMEOUT = 600 # 10 minutes
|
CLAUDE_TIMEOUT = 600 # 10 minutes
|
||||||
WEBHOOK_SYNC_INTERVAL = 300 # 5 minutes
|
app = FastAPI()
|
||||||
WEBHOOK_URL = "http://100.65.168.42:9880/webhook"
|
|
||||||
|
|
||||||
|
|
||||||
|
# --- Helpers ---
|
||||||
|
|
||||||
def verify_signature(payload: bytes, signature: str) -> bool:
|
def verify_signature(payload: bytes, signature: str) -> bool:
|
||||||
if not config.WEBHOOK_SECRET:
|
if not config.WEBHOOK_SECRET:
|
||||||
return True
|
return True
|
||||||
@ -167,7 +165,6 @@ async def process_mention(
|
|||||||
pr_info = None
|
pr_info = None
|
||||||
pull_request = issue.get("pull_request")
|
pull_request = issue.get("pull_request")
|
||||||
if pull_request and pull_request.get("merged") is not None:
|
if pull_request and pull_request.get("merged") is not None:
|
||||||
# It's a PR - fetch full PR info
|
|
||||||
pr_info = await gitea.get_pull_request(owner, repo, issue_number)
|
pr_info = await gitea.get_pull_request(owner, repo, issue_number)
|
||||||
head_branch = pr_info.get("head", {}).get("ref")
|
head_branch = pr_info.get("head", {}).get("ref")
|
||||||
if head_branch:
|
if head_branch:
|
||||||
@ -204,6 +201,8 @@ async def process_mention(
|
|||||||
log.exception("Failed to post error comment")
|
log.exception("Failed to post error comment")
|
||||||
|
|
||||||
|
|
||||||
|
# --- Routes ---
|
||||||
|
|
||||||
@app.post("/webhook")
|
@app.post("/webhook")
|
||||||
async def webhook(request: Request):
|
async def webhook(request: Request):
|
||||||
body = await request.body()
|
body = await request.body()
|
||||||
@ -220,7 +219,6 @@ async def webhook(request: Request):
|
|||||||
owner = repo_data.get("owner", {}).get("login", "")
|
owner = repo_data.get("owner", {}).get("login", "")
|
||||||
repo = repo_data.get("name", "")
|
repo = repo_data.get("name", "")
|
||||||
|
|
||||||
# Only process repos owned by fam
|
|
||||||
if owner != ALLOWED_OWNER:
|
if owner != ALLOWED_OWNER:
|
||||||
return {"status": "skip", "reason": f"owner {owner} not allowed"}
|
return {"status": "skip", "reason": f"owner {owner} not allowed"}
|
||||||
|
|
||||||
@ -255,33 +253,6 @@ async def webhook(request: Request):
|
|||||||
return {"status": "skip", "reason": f"unhandled {event}/{action}"}
|
return {"status": "skip", "reason": f"unhandled {event}/{action}"}
|
||||||
|
|
||||||
|
|
||||||
async def sync_webhooks():
|
|
||||||
"""Ensure all repos under ALLOWED_OWNER have our webhook."""
|
|
||||||
try:
|
|
||||||
repos = await gitea.list_user_repos(ALLOWED_OWNER)
|
|
||||||
for r in repos:
|
|
||||||
name = r["name"]
|
|
||||||
created = await gitea.ensure_webhook(ALLOWED_OWNER, name, WEBHOOK_URL)
|
|
||||||
if created:
|
|
||||||
log.info(f"Added webhook to {ALLOWED_OWNER}/{name}")
|
|
||||||
except Exception:
|
|
||||||
log.exception("Failed to sync webhooks")
|
|
||||||
|
|
||||||
|
|
||||||
async def webhook_sync_loop():
|
|
||||||
"""Periodically sync webhooks for new repos."""
|
|
||||||
while True:
|
|
||||||
await sync_webhooks()
|
|
||||||
await asyncio.sleep(WEBHOOK_SYNC_INTERVAL)
|
|
||||||
|
|
||||||
|
|
||||||
@asynccontextmanager
|
|
||||||
async def lifespan(app):
|
|
||||||
task = asyncio.create_task(webhook_sync_loop())
|
|
||||||
yield
|
|
||||||
task.cancel()
|
|
||||||
|
|
||||||
|
|
||||||
@app.get("/health")
|
@app.get("/health")
|
||||||
async def health():
|
async def health():
|
||||||
return {"status": "ok"}
|
return {"status": "ok"}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user