from flask import Flask, request, jsonify from tool import create_session, get_pull_request_overview, get_diff, send_slack_message, save_md_report, reply_slack_thread from dotenv import load_dotenv import os from agent.code_review import code_review_agent, read_text_file, DiffDeps # Set up ENVIRONMENT VARIABLE load_dotenv() WORKSPACE_ID = os.getenv("WORKSPACE_ID") BITBUCKET_USERNAME = os.getenv("BITBUCKET_USERNAME") BITBUCKET_APP_PASSWORD = os.getenv("BITBUCKET_APP_PASSWORD") DEFAULT_BASE_URL = os.getenv("DEFAULT_BASE_URL") REPO_SLUG = os.getenv("REPO_SLUG") SLACK_WEBHOOK_URL = os.getenv("SLACK_WEBHOOK_URL") SLACK_BOT_TOKEN = os.getenv("SLACK_BOT_TOKEN") SLACK_CHANNEL = os.getenv("SLACK_CHANNEL") app = Flask(__name__) @app.route("/webhook", methods=["POST"]) def webhook(): event_key = request.headers.get("X-Event-Key") # ví dụ: pullrequest:created, repo:push payload = request.json print("=== Webhook Received ===") print("Event:", event_key) # Xử lý Pull Request event if event_key and event_key.startswith("pullrequest"): if payload and "pullrequest" in payload: pr = payload["pullrequest"] pr_info = { "id": pr.get("id"), "title": pr.get("title"), "state": pr.get("state"), "author": pr.get("author", {}).get("display_name"), "source_branch": pr.get("source", {}).get("branch", {}).get("name"), "destination_branch": pr.get("destination", {}).get("branch", {}).get("name"), } print("Pull Request Info:", pr_info) # Chỉ xử lý khi có đủ thông tin PR if pr_info["id"]: try: PR_ID = pr_info["id"] session = create_session(BITBUCKET_USERNAME, BITBUCKET_APP_PASSWORD) data = get_pull_request_overview( session = session, workspace = WORKSPACE_ID, repo_slug = REPO_SLUG, pr_id = PR_ID, base_url = DEFAULT_BASE_URL ) title = data["title"] description = data["description"] source_branch = data["source"]["branch"]["name"] destination_branch = data["destination"]["branch"]["name"] author = data["author"]["display_name"] created_on = data["created_on"] reviewers = data.get("reviewers", []) reviewer_mentions = " ".join([f"@{r.get('nickname')}" for r in reviewers]) if reviewers else "None" pr_link = data["links"]["html"]["href"] changelog = data["summary"]["raw"] diff_url = data["links"]["diff"]["href"] # Tạo nội dung PR pr_report = ( f"# [{REPO_SLUG}] PR #{PR_ID}: {title}\n" f"*{description}*\n\n" f"**🌿 Branch Information:**\n" f"- **Source Branch:** {source_branch} → **Target Branch:** {destination_branch}\n\n" f"**👤 Người tạo:** {author}\n\n" f"**📅 Thời gian tạo:** {created_on}\n\n" f"**👥 Reviewers:**\n{reviewer_mentions}\n\n" f"**🔗 Link Pull Request:** {pr_link}\n" ) print(pr_report) # Lấy diff và chạy agent diff = get_diff(session, diff_url) print("Running Agent ...") code_review_result = code_review_agent.run_sync("", deps = DiffDeps(diff = diff[:-10_000])) code_review_text = getattr(code_review_result, "output", None) or str(code_review_result) # Gộp thông tin PR + kết quả review vào 1 lần gửi code_review_message = ( f"## 🤖 Code Review Summary\n\n" f"{code_review_text}" ) resp = send_slack_message( message_text = pr_report, webhook_url = SLACK_WEBHOOK_URL, bot_token = SLACK_BOT_TOKEN, channel = "pull-request", blocks = [ { "type": "markdown", "text": pr_report } ] ) first_message_ts = resp["response"]["ts"] # lấy ts để trả lời sau reply_slack_thread( thread_ts=first_message_ts, message_text=code_review_message, channel="pull-request", blocks = [ { "type": "markdown", "text": pr_report } ] ) print("Sent combined PR + code review") return jsonify({"status": "ok", "message": "Pull request processed successfully"}), 200 except Exception as exc: print("Error processing pull request:", str(exc)) return jsonify({"status": "error", "message": str(exc)}), 500 else: return jsonify({"status": "error", "message": "Invalid pull request data"}), 400 else: return jsonify({"status": "error", "message": "No pull request data in payload"}), 400 # Xử lý các event khác elif event_key and event_key.startswith("repo"): print("Repository event received:", event_key) return jsonify({"status": "ok", "message": "Repository event received"}), 200 else: print("Unknown event type:", event_key) return jsonify({"status": "ok", "message": "Event received but not processed"}), 200 if __name__ == "__main__": app.run(host="0.0.0.0", port=7860)