"""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 (НЕ сохраняем llm_chunk - их слишком много) if event.get("type") != "llm_chunk": 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 (отправляем все события, включая llm_chunk) 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