"""Bitbucket webhook handler""" from fastapi import HTTPException from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy import select from app.models import Repository, PullRequest, Review from app.models.pull_request import PRStatusEnum from app.models.review import ReviewStatusEnum from app.schemas.webhook import BitbucketWebhook async def handle_bitbucket_webhook( webhook_data: BitbucketWebhook, db: AsyncSession ) -> dict: """Handle Bitbucket webhook""" # Find repository by URL repo_url = webhook_data.repository.get("links", {}).get("html", {}).get("href", "") result = await db.execute( select(Repository).where(Repository.url == repo_url) ) repository = result.scalar_one_or_none() if not repository: raise HTTPException(status_code=404, detail="Repository not found") # Check if repository is active if not repository.is_active: return {"message": "Repository is not active"} # Get PR state pr_state = webhook_data.pullrequest.state.lower() # Handle PR events if pr_state in ["open", "opened"]: # Create or update PR result = await db.execute( select(PullRequest).where( PullRequest.repository_id == repository.id, PullRequest.pr_number == webhook_data.pullrequest.id ) ) pr = result.scalar_one_or_none() if not pr: pr = PullRequest( repository_id=repository.id, pr_number=webhook_data.pullrequest.id, title=webhook_data.pullrequest.title, author=webhook_data.pullrequest.author.get("display_name", ""), source_branch=webhook_data.pullrequest.source.get("branch", {}).get("name", ""), target_branch=webhook_data.pullrequest.destination.get("branch", {}).get("name", ""), url=webhook_data.pullrequest.links.get("html", {}).get("href", ""), status=PRStatusEnum.OPEN ) db.add(pr) await db.commit() await db.refresh(pr) else: pr.title = webhook_data.pullrequest.title pr.status = PRStatusEnum.OPEN await db.commit() # Create review review = Review( pull_request_id=pr.id, status=ReviewStatusEnum.PENDING ) db.add(review) await db.commit() await db.refresh(review) return { "message": "Review created", "review_id": review.id, "pr_id": pr.id } elif pr_state in ["closed", "merged", "declined"]: # Mark PR as closed result = await db.execute( select(PullRequest).where( PullRequest.repository_id == repository.id, PullRequest.pr_number == webhook_data.pullrequest.id ) ) pr = result.scalar_one_or_none() if pr: pr.status = PRStatusEnum.CLOSED await db.commit() return {"message": "PR closed"} return {"message": "Event not handled"}