Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions biz/event/event_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down
121 changes: 83 additions & 38 deletions biz/queue/worker.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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()}'
Expand Down
49 changes: 37 additions & 12 deletions biz/service/review_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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):
"""插入推送审核日志"""
Expand Down