2025-10-13 17:26:41 +03:00

143 lines
4.3 KiB
Python

"""Webhook endpoints"""
from fastapi import APIRouter, Depends, Request, Header, BackgroundTasks
from sqlalchemy.ext.asyncio import AsyncSession
from typing import Optional
from app.database import get_db
from app.schemas.webhook import GiteaWebhook, GitHubWebhook, BitbucketWebhook
from app.webhooks import handle_gitea_webhook, handle_github_webhook, handle_bitbucket_webhook
from app.agents import ReviewerAgent
router = APIRouter()
async def start_review_task(review_id: int, pr_number: int, repository_id: int):
"""Background task to start review with streaming"""
from app.database import async_session_maker
from app.main import manager
from datetime import datetime as dt
async with async_session_maker() as db:
# Create event handler for streaming
async def on_review_event(event: dict):
"""Handle review events and broadcast to clients"""
try:
event_data = {
"type": event.get("type", "agent_update"),
"review_id": review_id,
"pr_number": pr_number,
"timestamp": dt.utcnow().isoformat(),
"data": event
}
# Save to DB
from app.models.review_event import ReviewEvent
db_event = ReviewEvent(
review_id=review_id,
event_type=event.get("type", "agent_update"),
step=event.get("step"),
message=event.get("message"),
data=event
)
db.add(db_event)
await db.commit()
# Broadcast
await manager.broadcast(event_data)
except Exception as e:
print(f"Error in webhook review event handler: {e}")
agent = ReviewerAgent(db)
await agent.run_review_stream(review_id, pr_number, repository_id, on_event=on_review_event)
@router.post("/gitea/{repository_id}")
async def gitea_webhook(
repository_id: int,
request: Request,
background_tasks: BackgroundTasks,
x_gitea_signature: Optional[str] = Header(None),
db: AsyncSession = Depends(get_db)
):
"""Handle Gitea webhook"""
raw_payload = await request.body()
webhook_data = GiteaWebhook(**await request.json())
result = await handle_gitea_webhook(
webhook_data=webhook_data,
signature=x_gitea_signature or "",
raw_payload=raw_payload,
db=db
)
# Start review in background if created
if "review_id" in result:
background_tasks.add_task(
start_review_task,
result["review_id"],
webhook_data.number,
repository_id
)
return result
@router.post("/github/{repository_id}")
async def github_webhook(
repository_id: int,
request: Request,
background_tasks: BackgroundTasks,
x_hub_signature_256: Optional[str] = Header(None),
db: AsyncSession = Depends(get_db)
):
"""Handle GitHub webhook"""
raw_payload = await request.body()
webhook_data = GitHubWebhook(**await request.json())
result = await handle_github_webhook(
webhook_data=webhook_data,
signature=x_hub_signature_256 or "",
raw_payload=raw_payload,
db=db
)
# Start review in background if created
if "review_id" in result:
background_tasks.add_task(
start_review_task,
result["review_id"],
webhook_data.number,
repository_id
)
return result
@router.post("/bitbucket/{repository_id}")
async def bitbucket_webhook(
repository_id: int,
request: Request,
background_tasks: BackgroundTasks,
db: AsyncSession = Depends(get_db)
):
"""Handle Bitbucket webhook"""
webhook_data = BitbucketWebhook(**await request.json())
result = await handle_bitbucket_webhook(
webhook_data=webhook_data,
db=db
)
# Start review in background if created
if "review_id" in result:
background_tasks.add_task(
start_review_task,
result["review_id"],
webhook_data.pullrequest.id,
repository_id
)
return result