feat: orchestrator MVP — webhooks, agent launcher, QG checks
This commit is contained in:
0
src/webhooks/__init__.py
Normal file
0
src/webhooks/__init__.py
Normal file
54
src/webhooks/gitea.py
Normal file
54
src/webhooks/gitea.py
Normal file
@@ -0,0 +1,54 @@
|
||||
from fastapi import APIRouter, Request
|
||||
import json
|
||||
from ..db import get_db
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
|
||||
@router.post("/gitea")
|
||||
async def gitea_webhook(request: Request):
|
||||
"""Handle Gitea webhook events."""
|
||||
body = await request.body()
|
||||
payload = json.loads(body)
|
||||
|
||||
# Log event
|
||||
conn = get_db()
|
||||
event_type = request.headers.get("X-Gitea-Event", "unknown")
|
||||
conn.execute(
|
||||
"INSERT INTO events (source, event_type, payload) VALUES (?, ?, ?)",
|
||||
("gitea", event_type, body.decode()),
|
||||
)
|
||||
conn.commit()
|
||||
|
||||
if event_type == "push":
|
||||
await handle_push(payload, conn)
|
||||
elif event_type == "pull_request":
|
||||
await handle_pr(payload, conn)
|
||||
elif event_type == "status":
|
||||
await handle_ci_status(payload, conn)
|
||||
|
||||
conn.close()
|
||||
return {"status": "accepted"}
|
||||
|
||||
|
||||
async def handle_push(payload: dict, conn):
|
||||
"""Push event — log for now."""
|
||||
pass
|
||||
|
||||
|
||||
async def handle_pr(payload: dict, conn):
|
||||
"""PR event — check reviews, CI status."""
|
||||
action = payload.get("action", "")
|
||||
pr = payload.get("pull_request", {})
|
||||
|
||||
if action == "reviewed" and pr.get("state") == "approved":
|
||||
# TODO: QG-5 check -> launch Tester
|
||||
pass
|
||||
|
||||
|
||||
async def handle_ci_status(payload: dict, conn):
|
||||
"""CI status update — check if all green -> advance."""
|
||||
state = payload.get("state", "")
|
||||
if state == "success":
|
||||
# TODO: Check all required contexts green -> advance stage
|
||||
pass
|
||||
49
src/webhooks/plane.py
Normal file
49
src/webhooks/plane.py
Normal file
@@ -0,0 +1,49 @@
|
||||
from fastapi import APIRouter, Request
|
||||
import json
|
||||
from ..db import get_db
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
|
||||
@router.post("/plane")
|
||||
async def plane_webhook(request: Request):
|
||||
"""Handle Plane webhook events."""
|
||||
body = await request.body()
|
||||
payload = json.loads(body)
|
||||
|
||||
# Log event
|
||||
conn = get_db()
|
||||
conn.execute(
|
||||
"INSERT INTO events (source, event_type, payload) VALUES (?, ?, ?)",
|
||||
("plane", payload.get("event", "unknown"), body.decode()),
|
||||
)
|
||||
conn.commit()
|
||||
|
||||
event = payload.get("event")
|
||||
data = payload.get("data", {})
|
||||
|
||||
if event == "work_item.created":
|
||||
await handle_work_item_created(data, conn)
|
||||
elif event == "comment.created":
|
||||
await handle_comment(data, conn)
|
||||
|
||||
conn.close()
|
||||
return {"status": "accepted"}
|
||||
|
||||
|
||||
async def handle_work_item_created(data: dict, conn):
|
||||
"""New work item -> create task record."""
|
||||
plane_id = data.get("id", "")
|
||||
conn.execute(
|
||||
"INSERT INTO tasks (plane_id, repo, stage) VALUES (?, ?, ?)",
|
||||
(plane_id, "enduro-trails", "analysis"),
|
||||
)
|
||||
conn.commit()
|
||||
|
||||
|
||||
async def handle_comment(data: dict, conn):
|
||||
"""Check for :approved: reaction -> advance stage."""
|
||||
comment_body = data.get("comment", "")
|
||||
if ":approved:" in comment_body:
|
||||
# TODO: Determine which task, advance QG
|
||||
pass
|
||||
Reference in New Issue
Block a user