diff --git a/.gitea/checker/comparator.py b/.gitea/checker/comparator.py index 95bda87..eeaf1ac 100644 --- a/.gitea/checker/comparator.py +++ b/.gitea/checker/comparator.py @@ -89,6 +89,8 @@ class EndpointChangeReport: is_removed_endpoint: bool = False is_renamed_endpoint: bool = False old_uri: Optional[str] = None + is_method_changed: bool = False + old_http_method: Optional[str] = None @property def has_changes(self) -> bool: @@ -97,6 +99,7 @@ class EndpointChangeReport: self.is_new_endpoint or self.is_removed_endpoint or self.is_renamed_endpoint + or self.is_method_changed or len(self.parameter_changes) > 0 ) @@ -219,7 +222,11 @@ def compare_endpoints( """ 对比新旧两个版本的全部 Controller 端点,生成变更报告列表。 - 支持 URI 重命名检测(路径变更)。 + 支持以下变更类型检测: + - HTTP 方法变更(GET → POST 等) + - URI 路径变更(路径重命名) + - 新增 / 删除接口 + - 参数变更 """ reports: List[EndpointChangeReport] = [] @@ -230,7 +237,7 @@ def compare_endpoints( added_keys = new_keys - old_keys common_keys = old_keys & new_keys - # 1. URI 重命名检测:在 removed + added 中找 method+controller+method_name 相同的配对 + # 收集未匹配的 removed / added unmatched_removed: List[Tuple[str, ApiEndpoint]] = [] unmatched_added: List[Tuple[str, ApiEndpoint]] = [] @@ -242,15 +249,44 @@ def compare_endpoints( matched_removed: Set[str] = set() matched_added: Set[str] = set() + # 1. HTTP 方法变更检测(uri + controller + method_name 相同,但 method 不同) for r_key, r_ep in unmatched_removed: for a_key, a_ep in unmatched_added: if a_key in matched_added: continue - # 匹配条件:method 相同 + controller 相同 + method_name 相同 + if ( + r_ep.uri == a_ep.uri + and r_ep.controller_class == a_ep.controller_class + and r_ep.method_name == a_ep.method_name + and r_ep.http_method != a_ep.http_method + ): + reports.append( + EndpointChangeReport( + uri=a_ep.uri, + http_method=a_ep.http_method, + controller_class=a_ep.controller_class, + method_name=a_ep.method_name, + source_file=a_ep.source_file, + is_method_changed=True, + old_http_method=r_ep.http_method, + ) + ) + matched_removed.add(r_key) + matched_added.add(a_key) + break + + # 2. URI 路径变更检测(method + controller + method_name 相同,但 uri 不同) + for r_key, r_ep in unmatched_removed: + if r_key in matched_removed: + continue + for a_key, a_ep in unmatched_added: + if a_key in matched_added: + continue if ( r_ep.http_method == a_ep.http_method and r_ep.controller_class == a_ep.controller_class and r_ep.method_name == a_ep.method_name + and r_ep.uri != a_ep.uri ): reports.append( EndpointChangeReport( @@ -267,7 +303,7 @@ def compare_endpoints( matched_added.add(a_key) break - # 2. 剩余未匹配的 removed → 删除接口 + # 3. 剩余未匹配的 removed → 删除接口 for key, ep in unmatched_removed: if key not in matched_removed: reports.append( @@ -281,7 +317,7 @@ def compare_endpoints( ) ) - # 3. 剩余未匹配的 added → 新增接口 + # 4. 剩余未匹配的 added → 新增接口 for key, ep in unmatched_added: if key not in matched_added: reports.append( @@ -304,7 +340,7 @@ def compare_endpoints( ) ) - # 4. 共同 URI:对比参数变更 + # 5. 共同 URI:对比参数变更 for key in common_keys: old_ep = old_endpoints[key] new_ep = new_endpoints[key] diff --git a/.gitea/checker/notifier.py b/.gitea/checker/notifier.py index 3764cc6..e1d3471 100644 --- a/.gitea/checker/notifier.py +++ b/.gitea/checker/notifier.py @@ -75,12 +75,16 @@ def build_markdown_notification( """ parts: List[str] = [] - # 所有 API 级变更(新增、修改路径、删除、参数变更)统一走 model1.md 路径变更通知 + # 所有 API 级变更(新增、修改路径、修改请求方式、删除、参数变更)统一走 model1.md 路径变更通知 + method_changed_reports = [r for r in reports if r.is_method_changed] renamed_reports = [r for r in reports if r.is_renamed_endpoint] new_reports = [r for r in reports if r.is_new_endpoint] changed_reports = [ r for r in reports - if not r.is_new_endpoint and not r.is_removed_endpoint and not r.is_renamed_endpoint + if not r.is_new_endpoint + and not r.is_removed_endpoint + and not r.is_renamed_endpoint + and not r.is_method_changed ] removed_reports = [r for r in reports if r.is_removed_endpoint] @@ -97,7 +101,22 @@ def build_markdown_notification( parts.append(path_md) parts.append("") - # 2. 修改路径 → 走 API路径变更通知 + # 2. 修改请求方式 → 走 API路径变更通知 + for report in method_changed_reports: + path_md = build_path_change_markdown( + old_uri=report.uri, + new_uri=report.uri, + change_type="修改请求方式", + push_user=push_user, + push_time=push_time, + file_name=report.source_file or report.controller_class, + old_method=report.old_http_method, + new_method=report.http_method, + ) + parts.append(path_md) + parts.append("") + + # 3. 修改路径 → 走 API路径变更通知 for report in renamed_reports: path_md = build_path_change_markdown( old_uri=report.old_uri or "-", @@ -110,7 +129,7 @@ def build_markdown_notification( parts.append(path_md) parts.append("") - # 3. 删除接口 → 走 API路径变更通知 + # 4. 删除接口 → 走 API路径变更通知 for report in removed_reports: path_md = build_path_change_markdown( old_uri=report.uri, @@ -259,14 +278,19 @@ def build_path_change_markdown( push_user: str, push_time: str, file_name: str, + old_method: Optional[str] = None, + new_method: Optional[str] = None, ) -> str: """构建 API路径变更通知,完全匹配 model1.md 模板,并加强视觉区分。 + 支持的 change_type: + - 新增接口 / 删除接口 / 修改路径 / 修改请求方式 + 改进点: - 标题使用【】风格 - 头部信息缩进 + 颜色高亮 - URI 详情使用列表(更直观) - - 根据变更类型动态强调「原/新路径」 + - 「修改请求方式」额外展示方法变更 """ # 变更类型高亮 type_highlight = f"**{change_type}**" @@ -281,6 +305,15 @@ def build_path_change_markdown( elif change_type == "删除接口": old_display = f"**`{old_uri}`****已删除**" new_display = "`已删除`" + elif change_type == "修改请求方式": + # 方法变更场景:展示原方法 → 新方法 + old_m = old_method or "?" + new_m = new_method or "?" + old_display = f"**`{old_uri}` **[{old_m}]**" + new_display = ( + f"**`{new_uri}` " + f"**[{old_m} → {new_m}]****请求方式变更**" + ) else: # 修改路径 old_display = f"~~`{old_uri}`~~**旧路径**" new_display = f"**`{new_uri}`****新路径**"