-
Notifications
You must be signed in to change notification settings - Fork 100
Expand file tree
/
Copy pathdefault_handler.py
More file actions
131 lines (115 loc) · 5.78 KB
/
default_handler.py
File metadata and controls
131 lines (115 loc) · 5.78 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
import concurrent.futures
import threading
from retrying import retry
from config.config import GPT_MESSAGE, EXCLUDE_FILE_TYPES, IGNORE_FILE_TYPES, MAX_FILES
from review_engine.abstract_handler import ReviewHandle
from utils.gitlab_parser import filter_diff_content
from utils.logger import log
def chat_review(changes, generate_review, *args, **kwargs):
log.info('开始code review')
with concurrent.futures.ThreadPoolExecutor() as executor:
review_results = []
result_lock = threading.Lock()
def process_change(change):
result = generate_review(change, *args, **kwargs)
with result_lock:
review_results.append(result)
futures = []
for change in changes:
if any(change["new_path"].endswith(ext) for ext in EXCLUDE_FILE_TYPES) and not any(
change["new_path"].endswith(ext) for ext in IGNORE_FILE_TYPES):
futures.append(executor.submit(process_change, change))
else:
log.info(f"{change['new_path']} 非目标检测文件!")
concurrent.futures.wait(futures)
return "\n\n".join(review_results) if review_results else ""
@retry(stop_max_attempt_number=3, wait_fixed=60000)
def generate_review_note(change, model):
try:
content = filter_diff_content(change['diff'])
messages = [
{"role": "system",
"content": GPT_MESSAGE
},
{"role": "user",
"content": f"请review这部分代码变更{content}",
},
]
log.info(f"发送给gpt 内容如下:{messages}")
model.generate_text(messages)
new_path = change['new_path']
log.info(f'对 {new_path} review中...')
response_content = model.get_respond_content().replace('\n\n', '\n')
total_tokens = model.get_respond_tokens()
review_note = f'# 📚`{new_path}`' + '\n\n'
review_note += f'({total_tokens} tokens) {"AI review 意见如下:"}' + '\n\n'
review_note += response_content + "\n\n---\n\n---\n\n"
log.info(f'对 {new_path} review结束')
return review_note
except Exception as e:
log.error(f"GPT error:{e}")
class MainReviewHandle(ReviewHandle):
def merge_handle(self, gitlabMergeRequestFetcher, gitlabRepoManager, hook_info, reply, model):
changes = gitlabMergeRequestFetcher.get_changes()
merge_info = gitlabMergeRequestFetcher.get_info()
self.default_handle(changes, merge_info, hook_info, reply, model)
def default_handle(self, changes, merge_info, hook_info, reply, model):
if changes and len(changes) <= MAX_FILES:
# Code Review 信息
review_info = chat_review(changes, generate_review_note, model)
if review_info:
reply.add_reply({
'content': review_info,
'msg_type': 'MAIN, SINGLE',
'target': 'all',
})
reply.add_reply({
'title': '__MAIN_REVIEW__',
'content': (
f"## 项目名称: **{hook_info['project']['name']}**\n\n"
f"### 合并请求详情\n"
f"- **MR URL**: [查看合并请求]({hook_info['object_attributes']['url']})\n"
f"- **源分支**: `{hook_info['object_attributes']['source_branch']}`\n"
f"- **目标分支**: `{hook_info['object_attributes']['target_branch']}`\n\n"
f"### 变更详情\n"
f"- **修改文件个数**: `{len(changes)}`\n"
f"- **Code Review 状态**: ✅\n"
),
'target': 'dingtalk',
'msg_type': 'MAIN, SINGLE',
})
else:
reply.add_reply({
'title': '__MAIN_REVIEW__',
'content': (
f"## 项目名称: **{hook_info['project']['name']}**\n\n"
f"### 合并请求详情\n"
f"- **MR URL**: [查看合并请求]({hook_info['object_attributes']['url']})\n"
f"- **源分支**: `{hook_info['object_attributes']['source_branch']}`\n"
f"- **目标分支**: `{hook_info['object_attributes']['target_branch']}`\n\n"
f"### 变更详情\n"
f"- **修改文件个数**: `{len(changes)}`\n"
f"- **备注**: 存在已经提交的 MR,所有文件已进行 MR\n"
f"- **Code Review 状态**: pass ✅\n"
),
'target': 'dingtalk',
'msg_type': 'MAIN, SINGLE',
})
elif changes and len(changes) > MAX_FILES:
reply.add_reply({
'title': '__MAIN_REVIEW__',
'content': (
f"## 项目名称: **{hook_info['project']['name']}**\n\n"
f"### 备注\n"
f"修改 `{len(changes)}` 个文件 > 50 个文件,不进行 Code Review ⚠️\n\n"
f"### 合并请求详情\n"
f"- **MR URL**: [查看合并请求]({hook_info['object_attributes']['url']})\n"
f"- **源分支**: `{hook_info['object_attributes']['source_branch']}`\n"
f"- **目标分支**: `{hook_info['object_attributes']['target_branch']}`\n"
),
'target': 'dingtalk',
'msg_type': 'MAIN, SINGLE',
})
else:
log.error(f"获取merge_request信息失败,project_id: {hook_info['project']['id']} |"
f" merge_iid: {hook_info['object_attributes']['iid']} | merge_info: {merge_info}")