diff --git a/biz/event/event_manager.py b/biz/event/event_manager.py index 2c4454d51..973b285a2 100644 --- a/biz/event/event_manager.py +++ b/biz/event/event_manager.py @@ -35,8 +35,7 @@ def on_merge_request_reviewed(mr_review_entity: MergeRequestReviewEntity): project_name=mr_review_entity.project_name, url_slug=mr_review_entity.url_slug, webhook_data=mr_review_entity.webhook_data) - # 记录到数据库 - ReviewService().insert_mr_review_log(mr_review_entity) + # 注意:数据库记录现在在worker中处理,这里只负责发送通知 def on_push_reviewed(entity: PushReviewEntity): diff --git a/biz/queue/worker.py b/biz/queue/worker.py index a58cdef34..afc5e229f 100644 --- a/biz/queue/worker.py +++ b/biz/queue/worker.py @@ -131,38 +131,61 @@ def handle_merge_request_event(webhook_data: dict, gitlab_token: str, gitlab_url logger.error('Failed to get commits') return - # review 代码 + # 先插入初始记录到数据库(标记为处理中状态) commits_text = ';'.join(commit['title'] for commit in commits) + initial_entity = MergeRequestReviewEntity( + project_name=webhook_data['project']['name'], + author=webhook_data['user']['username'], + source_branch=webhook_data['object_attributes']['source_branch'], + target_branch=webhook_data['object_attributes']['target_branch'], + updated_at=int(datetime.now().timestamp()), + commits=commits, + score=0, # 初始分数为0 + url=webhook_data['object_attributes']['url'], + review_result="AI审查中...", # 标记为处理中 + url_slug=gitlab_url_slug, + webhook_data=webhook_data, + additions=additions, + deletions=deletions, + last_commit_id=last_commit_id, + ) + record_id = ReviewService.insert_mr_review_log(initial_entity) + if record_id > 0: + logger.info(f"Inserted initial MR record with id {record_id} for {webhook_data['project']['name']}, last_commit_id: {last_commit_id}") + else: + logger.error(f"Failed to insert initial MR record for {webhook_data['project']['name']}") + return + + # review 代码 review_result = CodeReviewer().review_and_strip_code(str(changes), commits_text) + score = CodeReviewer.parse_review_score(review_text=review_result) + + # 更新数据库记录 + update_success = ReviewService.update_mr_review_log_by_id( + record_id=record_id, + score=score, + review_result=review_result + ) + if update_success: + logger.info(f"Updated MR record with review result for {webhook_data['project']['name']}") + else: + logger.error(f"Failed to update MR record with review result for {webhook_data['project']['name']}") # 将review结果提交到Gitlab的 notes handler.add_merge_request_notes(f'Auto Review Result: \n{review_result}') + # 更新记录的review_result和score + initial_entity.review_result = review_result + initial_entity.score = score # dispatch merge_request_reviewed event - event_manager['merge_request_reviewed'].send( - MergeRequestReviewEntity( - project_name=webhook_data['project']['name'], - author=webhook_data['user']['username'], - source_branch=webhook_data['object_attributes']['source_branch'], - target_branch=webhook_data['object_attributes']['target_branch'], - updated_at=int(datetime.now().timestamp()), - commits=commits, - score=CodeReviewer.parse_review_score(review_text=review_result), - url=webhook_data['object_attributes']['url'], - review_result=review_result, - url_slug=gitlab_url_slug, - webhook_data=webhook_data, - additions=additions, - deletions=deletions, - last_commit_id=last_commit_id, - ) - ) + event_manager['merge_request_reviewed'].send(initial_entity) except Exception as e: error_message = f'AI Code Review 服务出现未知错误: {str(e)}\n{traceback.format_exc()}' notifier.send_notification(content=error_message) logger.error('出现未知错误: %s', error_message) + def handle_github_push_event(webhook_data: dict, github_token: str, github_url: str, github_url_slug: str): push_review_enabled = os.environ.get('PUSH_REVIEW_ENABLED', '0') == '1' try: @@ -270,32 +293,54 @@ def handle_github_pull_request_event(webhook_data: dict, github_token: str, gith if not commits: logger.error('Failed to get commits') return - - # review 代码 + # 先插入初始记录到数据库(标记为处理中状态) commits_text = ';'.join(commit['title'] for commit in commits) + initial_entity = MergeRequestReviewEntity( + project_name=webhook_data['repository']['name'], + author=webhook_data['pull_request']['user']['login'], + source_branch=webhook_data['pull_request']['head']['ref'], + target_branch=webhook_data['pull_request']['base']['ref'], + updated_at=int(datetime.now().timestamp()), + commits=commits, + score=0, # 初始分数为0 + url=webhook_data['pull_request']['html_url'], + review_result="AI审查中...", # 标记为处理中 + url_slug=github_url_slug, + webhook_data=webhook_data, + additions=additions, + deletions=deletions, + last_commit_id=github_last_commit_id, + ) + record_id = ReviewService.insert_mr_review_log(initial_entity) + if record_id > 0: + logger.info(f"Inserted initial PR record with id {record_id} for {webhook_data['repository']['name']}, last_commit_id: {github_last_commit_id}") + else: + logger.error(f"Failed to insert initial PR record for {webhook_data['repository']['name']}") + return + + # review 代码 review_result = CodeReviewer().review_and_strip_code(str(changes), commits_text) + score = CodeReviewer.parse_review_score(review_text=review_result) + + # 更新数据库记录 + update_success = ReviewService.update_mr_review_log_by_id( + record_id=record_id, + score=score, + review_result=review_result + ) + if update_success: + logger.info(f"Updated PR record with review result for {webhook_data['repository']['name']}") + else: + logger.error(f"Failed to update PR record with review result for {webhook_data['repository']['name']}") # 将review结果提交到GitHub的 notes handler.add_pull_request_notes(f'Auto Review Result: \n{review_result}') + # 更新记录的review_result和score + initial_entity.review_result = review_result + initial_entity.score = score # dispatch pull_request_reviewed event - event_manager['merge_request_reviewed'].send( - MergeRequestReviewEntity( - project_name=webhook_data['repository']['name'], - author=webhook_data['pull_request']['user']['login'], - source_branch=webhook_data['pull_request']['head']['ref'], - target_branch=webhook_data['pull_request']['base']['ref'], - updated_at=int(datetime.now().timestamp()), - commits=commits, - score=CodeReviewer.parse_review_score(review_text=review_result), - url=webhook_data['pull_request']['html_url'], - review_result=review_result, - url_slug=github_url_slug, - webhook_data=webhook_data, - additions=additions, - deletions=deletions, - last_commit_id=github_last_commit_id, - )) + event_manager['merge_request_reviewed'].send(initial_entity) except Exception as e: error_message = f'服务出现未知错误: {str(e)}\n{traceback.format_exc()}' diff --git a/biz/service/review_service.py b/biz/service/review_service.py index 887d6fca8..ceb7f66f6 100644 --- a/biz/service/review_service.py +++ b/biz/service/review_service.py @@ -79,24 +79,26 @@ def init_db(): print(f"Database initialization failed: {e}") @staticmethod - def insert_mr_review_log(entity: MergeRequestReviewEntity): - """插入合并请求审核日志""" + def insert_mr_review_log(entity: MergeRequestReviewEntity) -> int: + """插入合并请求审核日志,返回插入记录的id""" try: with sqlite3.connect(ReviewService.DB_FILE) as conn: cursor = conn.cursor() - cursor.execute(''' - INSERT INTO mr_review_log (project_name,author, source_branch, target_branch, - updated_at, commit_messages, score, url,review_result, additions, deletions, - last_commit_id) - VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) - ''', - (entity.project_name, entity.author, entity.source_branch, - entity.target_branch, entity.updated_at, entity.commit_messages, entity.score, - entity.url, entity.review_result, entity.additions, entity.deletions, - entity.last_commit_id)) + cursor.execute('''INSERT INTO mr_review_log (project_name, author, source_branch, + target_branch, updated_at, commit_messages, score, url, review_result, additions, deletions, last_commit_id) + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) + ''', + (entity.project_name, entity.author, + entity.source_branch, entity.target_branch, + entity.updated_at, entity.commit_messages, entity.score, + entity.url, entity.review_result, entity.additions, entity.deletions, entity.last_commit_id)) + record_id = cursor.lastrowid conn.commit() + print(f"Successfully inserted mr_review_log record with id: {record_id}") + return record_id except sqlite3.DatabaseError as e: print(f"Error inserting review log: {e}") + return 0 @staticmethod def get_mr_review_logs(authors: list = None, project_names: list = None, updated_at_gte: int = None, @@ -151,6 +153,29 @@ def check_mr_last_commit_id_exists(project_name: str, source_branch: str, target print(f"Error checking last_commit_id: {e}") return False + @staticmethod + def update_mr_review_log_by_id(record_id: int, score: float, review_result: str) -> bool: + """通过id更新合并请求审核日志的review_result和score""" + try: + with sqlite3.connect(ReviewService.DB_FILE) as conn: + cursor = conn.cursor() + cursor.execute(''' + UPDATE mr_review_log + SET score = ?, review_result = ? + WHERE id = ? + ''', (score, review_result, record_id)) + conn.commit() + updated_rows = cursor.rowcount + if updated_rows > 0: + print(f"Successfully updated mr_review_log record with id: {record_id}") + return True + else: + print(f"No mr_review_log record found with id: {record_id}") + return False + except sqlite3.DatabaseError as e: + print(f"Error updating mr_review_log by id: {e}") + return False + @staticmethod def insert_push_review_log(entity: PushReviewEntity): """插入推送审核日志"""