From 35d64a91b3d9499c628637c7d8153fa64aa11143 Mon Sep 17 00:00:00 2001 From: dongzi Date: Fri, 5 Jun 2026 14:23:46 +0800 Subject: [PATCH] 1 --- .gitea/checker/comparator.py | 237 ++++++++---------- .../controller/CultureClockInController.java | 1 + 2 files changed, 108 insertions(+), 130 deletions(-) diff --git a/.gitea/checker/comparator.py b/.gitea/checker/comparator.py index b44c9fc..d447c67 100644 --- a/.gitea/checker/comparator.py +++ b/.gitea/checker/comparator.py @@ -215,6 +215,11 @@ def compare_parameters( return changes +def _method_identity(ep: ApiEndpoint) -> Tuple[str, str]: + """生成方法的唯一标识:(source_file, method_name)。""" + return (ep.source_file or "", ep.method_name) + + def compare_endpoints( old_endpoints: Dict[str, ApiEndpoint], new_endpoints: Dict[str, ApiEndpoint], @@ -222,170 +227,142 @@ def compare_endpoints( """ 对比新旧两个版本的全部 Controller 端点,生成变更报告列表。 - 支持以下变更类型检测: - - HTTP 方法变更(GET → POST 等) - - URI 路径变更(路径重命名) - - 新增 / 删除接口 - - 参数变更 + 匹配策略(方案 1): + - 使用 (source_file, method_name) 作为「同一个 Java 方法」的唯一标识。 + - 只要同一个 Java 方法被修改,就分别判断「请求方式是否变」和「路径是否变」。 + - 支持「同时改请求方式 + 路径」时生成两条独立报告。 + - 支持「同时改请求方式/路径 + 参数」时生成多条独立报告。 """ reports: List[EndpointChangeReport] = [] - old_keys = set(old_endpoints.keys()) - new_keys = set(new_endpoints.keys()) + # 1. 构建基于方法标识的映射 + old_by_identity: Dict[Tuple[str, str], List[ApiEndpoint]] = {} + new_by_identity: Dict[Tuple[str, str], List[ApiEndpoint]] = {} - removed_keys = old_keys - new_keys - added_keys = new_keys - old_keys - common_keys = old_keys & new_keys + for ep in old_endpoints.values(): + identity = _method_identity(ep) + old_by_identity.setdefault(identity, []).append(ep) - # 收集未匹配的 removed / added - unmatched_removed: List[Tuple[str, ApiEndpoint]] = [] - unmatched_added: List[Tuple[str, ApiEndpoint]] = [] + for ep in new_endpoints.values(): + identity = _method_identity(ep) + new_by_identity.setdefault(identity, []).append(ep) - for key in removed_keys: - unmatched_removed.append((key, old_endpoints[key])) - for key in added_keys: - unmatched_added.append((key, new_endpoints[key])) + all_identities = set(old_by_identity.keys()) | set(new_by_identity.keys()) - matched_removed: Set[str] = set() - matched_added: Set[str] = set() + for identity in all_identities: + old_list = old_by_identity.get(identity, []) + new_list = new_by_identity.get(identity, []) - # 1. HTTP 方法变更检测(uri + controller 相同,但 method 不同) - # 放宽匹配条件:只要同一个 Controller 的同一个 URI 请求方式改变,就识别为「修改请求方式」 - # 不再要求 method_name 相同(允许方法重命名场景) - # 如果同时有参数变更,生成两条独立报告(方法变更 + 参数变更),互不干扰 - for r_key, r_ep in unmatched_removed: - for a_key, a_ep in unmatched_added: - if a_key in matched_added: - continue - if ( - r_ep.uri == a_ep.uri - and r_ep.controller_class == a_ep.controller_class - and r_ep.http_method != a_ep.http_method - ): - # 先生成纯方法变更报告 + # 简单场景:同一个方法在旧版和新版各出现一次 + if len(old_list) == 1 and len(new_list) == 1: + old_ep = old_list[0] + new_ep = new_list[0] + + # 判断请求方式是否改变 + if old_ep.http_method != new_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, + uri=new_ep.uri, + http_method=new_ep.http_method, + controller_class=new_ep.controller_class, + method_name=new_ep.method_name, + source_file=new_ep.source_file, is_method_changed=True, - old_http_method=r_ep.http_method, + old_http_method=old_ep.http_method, ) ) - # 再检测参数变更,如果有则额外生成一条独立的参数变更报告 - param_changes = compare_parameters(r_ep.parameters, a_ep.parameters) + # 如果同时有参数变更,额外生成参数报告 + param_changes = compare_parameters(old_ep.parameters, new_ep.parameters) if param_changes: 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, + uri=new_ep.uri, + http_method=new_ep.http_method, + controller_class=new_ep.controller_class, + method_name=new_ep.method_name, + source_file=new_ep.source_file, parameter_changes=param_changes, ) ) - 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 - ): - # 先生成纯路径变更报告 + # 判断路径是否改变 + if old_ep.uri != new_ep.uri: 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, + uri=new_ep.uri, + http_method=new_ep.http_method, + controller_class=new_ep.controller_class, + method_name=new_ep.method_name, + source_file=new_ep.source_file, is_renamed_endpoint=True, - old_uri=r_ep.uri, + old_uri=old_ep.uri, ) ) - # 再检测参数变更,如果有则额外生成一条独立的参数变更报告 - param_changes = compare_parameters(r_ep.parameters, a_ep.parameters) + # 如果同时有参数变更,额外生成参数报告(避免重复) + if old_ep.http_method == new_ep.http_method: + param_changes = compare_parameters(old_ep.parameters, new_ep.parameters) + if param_changes: + reports.append( + EndpointChangeReport( + uri=new_ep.uri, + http_method=new_ep.http_method, + controller_class=new_ep.controller_class, + method_name=new_ep.method_name, + source_file=new_ep.source_file, + parameter_changes=param_changes, + ) + ) + + # 如果请求方式和路径都没变,只检测参数变更 + if old_ep.http_method == new_ep.http_method and old_ep.uri == new_ep.uri: + param_changes = compare_parameters(old_ep.parameters, new_ep.parameters) if param_changes: 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, + uri=new_ep.uri, + http_method=new_ep.http_method, + controller_class=new_ep.controller_class, + method_name=new_ep.method_name, + source_file=new_ep.source_file, parameter_changes=param_changes, ) ) - matched_removed.add(r_key) - matched_added.add(a_key) - break - # 3. 剩余未匹配的 removed → 删除接口 - for key, ep in unmatched_removed: - if key not in matched_removed: - reports.append( - EndpointChangeReport( - uri=ep.uri, - http_method=ep.http_method, - controller_class=ep.controller_class, - method_name=ep.method_name, - source_file=ep.source_file, - is_removed_endpoint=True, + elif len(old_list) == 0 and len(new_list) > 0: + # 新增接口 + for new_ep in new_list: + reports.append( + EndpointChangeReport( + uri=new_ep.uri, + http_method=new_ep.http_method, + controller_class=new_ep.controller_class, + method_name=new_ep.method_name, + source_file=new_ep.source_file, + is_new_endpoint=True, + parameter_changes=[ + ParameterChange( + change_type=ChangeType.ADDED, + param_name=p.name, + param_type=p.type, + required=p.required, + ) + for p in new_ep.parameters + ], + ) ) - ) - # 4. 剩余未匹配的 added → 新增接口 - for key, ep in unmatched_added: - if key not in matched_added: - reports.append( - EndpointChangeReport( - uri=ep.uri, - http_method=ep.http_method, - controller_class=ep.controller_class, - method_name=ep.method_name, - source_file=ep.source_file, - is_new_endpoint=True, - parameter_changes=[ - ParameterChange( - change_type=ChangeType.ADDED, - param_name=p.name, - param_type=p.type, - required=p.required, - ) - for p in ep.parameters - ], + elif len(old_list) > 0 and len(new_list) == 0: + # 删除接口 + for old_ep in old_list: + reports.append( + EndpointChangeReport( + uri=old_ep.uri, + http_method=old_ep.http_method, + controller_class=old_ep.controller_class, + method_name=old_ep.method_name, + source_file=old_ep.source_file, + is_removed_endpoint=True, + ) ) - ) - - # 5. 共同 URI:对比参数变更 - for key in common_keys: - old_ep = old_endpoints[key] - new_ep = new_endpoints[key] - param_changes = compare_parameters(old_ep.parameters, new_ep.parameters) - if param_changes: - reports.append( - EndpointChangeReport( - uri=new_ep.uri, - http_method=new_ep.http_method, - controller_class=new_ep.controller_class, - method_name=new_ep.method_name, - source_file=new_ep.source_file, - parameter_changes=param_changes, - ) - ) return [r for r in reports if r.has_changes] diff --git a/ftb/src/main/java/ftb/test/controller/CultureClockInController.java b/ftb/src/main/java/ftb/test/controller/CultureClockInController.java index 1ce6f54..c5e015e 100644 --- a/ftb/src/main/java/ftb/test/controller/CultureClockInController.java +++ b/ftb/src/main/java/ftb/test/controller/CultureClockInController.java @@ -70,6 +70,7 @@ public class CultureClockInController { * @param response HttpServletResponse */ @GetMapping(value = "/random-preview/base641") + @PutMapping(value = "/random-preview/base64") public ActionResult getRandomPicPreviewBase64(@RequestParam(value = "lastCombo1", required = false) String lastCombo, HttpServletRequest request, HttpServletResponse response) throws Exception { MutablePair pair = cultureClockInService.getRandomPicPreview(lastCombo, requestUrl);