|
11 | 11 | from flask import Flask, request, jsonify
|
12 | 12 |
|
13 | 13 | from biz.gitlab.webhook_handler import slugify_url
|
14 |
| -from biz.queue.worker import handle_merge_request_event, handle_push_event |
| 14 | +from biz.queue.worker import handle_merge_request_event, handle_push_event, handle_github_pull_request_event, handle_github_push_event |
15 | 15 | from biz.service.review_service import ReviewService
|
16 | 16 | from biz.utils.im import notifier
|
17 | 17 | from biz.utils.log import logger
|
@@ -114,58 +114,98 @@ def handle_webhook():
|
114 | 114 | if not data:
|
115 | 115 | return jsonify({"error": _("Invalid JSON")}), 400
|
116 | 116 |
|
117 |
| - object_kind = data.get("object_kind") |
118 |
| - |
119 |
| - # 优先从请求头获取,如果没有,则从环境变量获取,如果没有,则从推送事件中获取 |
120 |
| - gitlab_url = os.getenv('GITLAB_URL') or request.headers.get('X-Gitlab-Instance') |
121 |
| - if not gitlab_url: |
122 |
| - repository = data.get('repository') |
123 |
| - if not repository: |
124 |
| - return jsonify({'message': _('Missing GitLab URL')}), 400 |
125 |
| - homepage = repository.get("homepage") |
126 |
| - if not homepage: |
127 |
| - return jsonify({'message': _('Missing GitLab URL')}), 400 |
128 |
| - try: |
129 |
| - parsed_url = urlparse(homepage) |
130 |
| - gitlab_url = f"{parsed_url.scheme}://{parsed_url.netloc}/" |
131 |
| - except Exception as e: |
132 |
| - return jsonify({"error": f"Failed to parse homepage URL: {str(e)}"}), 400 |
133 |
| - |
134 |
| - # 优先从环境变量获取,如果没有,则从请求头获取 |
135 |
| - gitlab_token = os.getenv('GITLAB_ACCESS_TOKEN') or request.headers.get('X-Gitlab-Token') |
136 |
| - # 如果gitlab_token为空,返回错误 |
137 |
| - if not gitlab_token: |
138 |
| - return jsonify({'message': _('Missing GitLab access token')}), 400 |
139 |
| - |
140 |
| - gitlab_url_slug = slugify_url(gitlab_url) |
141 |
| - |
142 |
| - # 打印整个payload数据,或根据需求进行处理 |
143 |
| - logger.info(_('Received event: {}').format(object_kind)) |
144 |
| - logger.info(_('Payload: {}').format(json.dumps(data))) |
145 |
| - |
146 |
| - # 处理Merge Request Hook |
147 |
| - if object_kind == "merge_request": |
148 |
| - # 创建一个新进程进行异步处理 |
149 |
| - handle_queue(handle_merge_request_event, data, gitlab_token, gitlab_url, gitlab_url_slug) |
150 |
| - # 立马返回响应 |
151 |
| - return jsonify({'message': _('Request received(object_kind={}), will process asynchronously.').format( |
152 |
| - object_kind)}), 200 |
153 |
| - elif object_kind == "push": |
154 |
| - # 创建一个新进程进行异步处理 |
155 |
| - # TODO check if PUSH_REVIEW_ENABLED is needed here |
156 |
| - handle_queue(handle_push_event, data, gitlab_token, gitlab_url, gitlab_url_slug) |
157 |
| - # 立马返回响应 |
158 |
| - return jsonify({'message': _('Request received(object_kind={}), will process asynchronously.').format( |
159 |
| - object_kind)}), 200 |
160 |
| - else: |
161 |
| - error_message = _( |
162 |
| - 'Only merge_request and push events are supported (both Webhook and System Hook), but received: {}.').format( |
163 |
| - object_kind) |
164 |
| - logger.error(error_message) |
165 |
| - return jsonify(error_message), 400 |
| 117 | + # 判断是GitLab还是GitHub的webhook |
| 118 | + webhook_source = request.headers.get('X-GitHub-Event') |
| 119 | + |
| 120 | + if webhook_source: # GitHub webhook |
| 121 | + return handle_github_webhook(webhook_source, data) |
| 122 | + else: # GitLab webhook |
| 123 | + return handle_gitlab_webhook(data) |
166 | 124 | else:
|
167 | 125 | return jsonify({'message': _('Invalid data format')}), 400
|
168 | 126 |
|
| 127 | +def handle_github_webhook(event_type, data): |
| 128 | + # 获取GitHub配置 |
| 129 | + github_token = os.getenv('GITHUB_ACCESS_TOKEN') or request.headers.get('X-GitHub-Token') |
| 130 | + if not github_token: |
| 131 | + return jsonify({'message': _('Missing GitLab URL')}), 400 |
| 132 | + |
| 133 | + github_url = os.getenv('GITHUB_URL') or 'https://github.com' |
| 134 | + github_url_slug = slugify_url(github_url) |
| 135 | + |
| 136 | + # 打印整个payload数据 |
| 137 | + logger.info(_('Received event: {}').format(event_type)) |
| 138 | + logger.info(_('Payload: {}').format(json.dumps(data))) |
| 139 | + |
| 140 | + if event_type == "pull_request": |
| 141 | + # 使用handle_queue进行异步处理 |
| 142 | + handle_queue(handle_github_pull_request_event, data, github_token, github_url, github_url_slug) |
| 143 | + # 立马返回响应 |
| 144 | + return jsonify({'message': _('GitHub request received(event_type={}), will process asynchronously.').format( |
| 145 | + event_type)}), 200 |
| 146 | + elif event_type == "push": |
| 147 | + # 使用handle_queue进行异步处理 |
| 148 | + handle_queue(handle_github_push_event, data, github_token, github_url, github_url_slug) |
| 149 | + # 立马返回响应 |
| 150 | + return jsonify({'message': _('GitHub request received(event_type={}), will process asynchronously.').format( |
| 151 | + event_type)}), 200 |
| 152 | + else: |
| 153 | + error_message = _( |
| 154 | + 'Only pull_request and push events are supported for GitHub webhook, but received:: {}.').format( |
| 155 | + event_type) |
| 156 | + logger.error(error_message) |
| 157 | + return jsonify(error_message), 400 |
| 158 | + |
| 159 | +def handle_gitlab_webhook(data): |
| 160 | + object_kind = data.get("object_kind") |
| 161 | + |
| 162 | + # 优先从请求头获取,如果没有,则从环境变量获取,如果没有,则从推送事件中获取 |
| 163 | + gitlab_url = os.getenv('GITLAB_URL') or request.headers.get('X-Gitlab-Instance') |
| 164 | + if not gitlab_url: |
| 165 | + repository = data.get('repository') |
| 166 | + if not repository: |
| 167 | + return jsonify({'message': _('Missing GitLab URL')}), 400 |
| 168 | + homepage = repository.get("homepage") |
| 169 | + if not homepage: |
| 170 | + return jsonify({'message': _('Missing GitLab URL')}), 400 |
| 171 | + try: |
| 172 | + parsed_url = urlparse(homepage) |
| 173 | + gitlab_url = f"{parsed_url.scheme}://{parsed_url.netloc}/" |
| 174 | + except Exception as e: |
| 175 | + return jsonify({"error": f"Failed to parse homepage URL: {str(e)}"}), 400 |
| 176 | + |
| 177 | + # 优先从环境变量获取,如果没有,则从请求头获取 |
| 178 | + gitlab_token = os.getenv('GITLAB_ACCESS_TOKEN') or request.headers.get('X-Gitlab-Token') |
| 179 | + # 如果gitlab_token为空,返回错误 |
| 180 | + if not gitlab_token: |
| 181 | + return jsonify({'message': _('Missing GitLab access token')}), 400 |
| 182 | + |
| 183 | + gitlab_url_slug = slugify_url(gitlab_url) |
| 184 | + |
| 185 | + # 打印整个payload数据,或根据需求进行处理 |
| 186 | + logger.info(_('Received event: {}').format(object_kind)) |
| 187 | + logger.info(_('Payload: {}').format(json.dumps(data))) |
| 188 | + |
| 189 | + # 处理Merge Request Hook |
| 190 | + if object_kind == "merge_request": |
| 191 | + # 创建一个新进程进行异步处理 |
| 192 | + handle_queue(handle_merge_request_event, data, gitlab_token, gitlab_url, gitlab_url_slug) |
| 193 | + # 立马返回响应 |
| 194 | + return jsonify({'message': _('Request received(object_kind={}), will process asynchronously.').format( |
| 195 | + object_kind)}), 200 |
| 196 | + elif object_kind == "push": |
| 197 | + # 创建一个新进程进行异步处理 |
| 198 | + # TODO check if PUSH_REVIEW_ENABLED is needed here |
| 199 | + handle_queue(handle_push_event, data, gitlab_token, gitlab_url, gitlab_url_slug) |
| 200 | + # 立马返回响应 |
| 201 | + return jsonify({'message': _('Request received(object_kind={}), will process asynchronously.').format( |
| 202 | + object_kind)}), 200 |
| 203 | + else: |
| 204 | + error_message = _( |
| 205 | + 'Only merge_request and push events are supported (both Webhook and System Hook), but received: {}.').format( |
| 206 | + object_kind) |
| 207 | + logger.error(error_message) |
| 208 | + return jsonify(error_message), 400 |
169 | 209 |
|
170 | 210 | if __name__ == '__main__':
|
171 | 211 | # 启动定时任务调度器
|
|
0 commit comments