""" Webhook handlers for JIRA and Bitbucket events. """ from fastapi import APIRouter, Request, HTTPException, Header from typing import Optional import hmac import hashlib import logging logger = logging.getLogger(__name__) router = APIRouter() def verify_jira_signature(payload: bytes, signature: str, secret: str) -> bool: """Verify JIRA webhook signature.""" expected = hmac.new(secret.encode(), payload, hashlib.sha256).hexdigest() return hmac.compare_digest(expected, signature) @router.post("/jira") async def jira_webhook( request: Request, x_atlassian_webhook_identifier: Optional[str] = Header(None), ): """ Handle JIRA webhook events. Events processed: - jira:issue_created - jira:issue_updated """ body = await request.body() data = await request.json() event_type = data.get("webhookEvent", "unknown") issue = data.get("issue", {}) issue_key = issue.get("key", "unknown") logger.info(f"📥 JIRA webhook: {event_type} - {issue_key}") # Filter: only process Support Cases issue_type = issue.get("fields", {}).get("issuetype", {}).get("name", "") if issue_type != "Support Case": logger.info(f"⏭️ Skipping non-Support Case issue: {issue_key} ({issue_type})") return {"status": "skipped", "reason": "not a Support Case"} # Queue for analysis # TODO: Implement queue system logger.info(f"📋 Queuing Support Case for analysis: {issue_key}") return { "status": "accepted", "issue": issue_key, "event": event_type, } @router.post("/bitbucket") async def bitbucket_webhook(request: Request): """ Handle Bitbucket webhook events. Events processed: - repo:refs_changed (push) - pr:merged """ data = await request.json() event_type = data.get("eventKey", "unknown") logger.info(f"📥 Bitbucket webhook: {event_type}") if event_type == "repo:refs_changed": # Re-index affected files changes = data.get("changes", []) for change in changes: ref = change.get("ref", {}).get("displayId", "") logger.info(f"🔄 Branch updated: {ref}") return {"status": "accepted", "event": event_type}