diff --git a/app/main.py b/app/main.py index 0d5955a..ec2adb4 100644 --- a/app/main.py +++ b/app/main.py @@ -409,3 +409,33 @@ def list_webhook_logs(webhook_id: int, limit: int = 50, db: Session = Depends(ge WebhookLog.webhook_id == webhook_id ).order_by(WebhookLog.created_at.desc()).limit(limit).all() return logs + + + +# ============ Issue Status Transition ============ + +@app.post("/issues/{issue_id}/transition", response_model=schemas.IssueResponse) +def transition_issue(issue_id: int, new_status: str, bg: BackgroundTasks, db: Session = Depends(get_db)): + """Transition issue status with validation and webhook.""" + valid_statuses = ["open", "in_progress", "resolved", "closed", "blocked"] + if new_status not in valid_statuses: + raise HTTPException(status_code=400, detail=f"Invalid status. Must be one of: {valid_statuses}") + + issue = db.query(models.Issue).filter(models.Issue.id == issue_id).first() + if not issue: + raise HTTPException(status_code=404, detail="Issue not found") + + old_status = issue.status + issue.status = new_status + db.commit() + db.refresh(issue) + + event = "issue.closed" if new_status == "closed" else "issue.updated" + bg.add_task(fire_webhooks_sync, event, { + "issue_id": issue.id, + "title": issue.title, + "old_status": old_status, + "new_status": new_status, + }, issue.project_id, db) + + return issue