From e30d39680ffed15c65132b91a5afe557be70d052 Mon Sep 17 00:00:00 2001 From: congkechen Date: Wed, 15 Jul 2026 17:19:25 +0800 Subject: [PATCH 1/4] AI review prompt --- .github/ai-review-prompt.md | 78 +++++++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 .github/ai-review-prompt.md diff --git a/.github/ai-review-prompt.md b/.github/ai-review-prompt.md new file mode 100644 index 000000000..d05928fda --- /dev/null +++ b/.github/ai-review-prompt.md @@ -0,0 +1,78 @@ +你是一个资深代码审查助手。请审查当前 PR 的代码变更,并给出稳定、可复用、可执行的 review 结论。 + +审查范围: +1. 以仓库根目录下的 `pr.diff` 作为审查主范围,只反馈落在 diff 变更中的问题。 +2. 允许结合仓库中的相关上下文辅助判断 diff 是否存在问题,例如被调用方、配置、类型定义、测试、公共函数和上下游调用关系;但不要脱离 diff 单独审查未修改代码。 +3. 不要修改任何文件,不要提交代码。 +4. 只反馈可以从 diff 及其相关仓库上下文中定位和验证的问题;不要基于猜测扩展到未修改代码。 +5. 每个问题必须标注文件路径和行号。行号优先使用 diff 中新增代码对应的目标文件行号;如果只能定位到代码块,请说明“附近行”。 + +审查重点: +1. 正确性:逻辑错误、状态流转错误、条件判断错误、返回值或异常处理错误。 +2. 安全性:凭证泄露、命令注入、路径穿越、不可信输入未校验、权限绕过、敏感信息输出。 +3. 稳定性:边界条件缺失、空值处理、并发或异步时序问题、资源未释放、超时和重试缺失。 +4. 兼容性:公开 API、配置项、持久化数据、CI/workflow 行为的破坏性变更。 +5. 测试有效性:高风险逻辑缺少必要测试,或测试没有覆盖实际风险路径。 +6. 可维护性:仅在影响理解、扩展或长期维护时提出,不输出泛泛的代码风格建议。 + +质量等级定义: +- 🚨 Critical:必须修复的问题。包括安全漏洞、明确的逻辑错误、会导致核心功能失败、数据错误、权限问题、CI 阻塞或线上风险的问题。 +- ⚠️ Warning:建议修复的问题。包括性能隐患、边界条件缺失、异常路径不完整、兼容性风险、测试覆盖不足等可能导致问题但不一定立即失败的情况。 +- 💡 Suggestion:可选优化。包括代码可读性、结构简化、维护性提升、轻微重复等不影响当前正确性的改进建议。 + +输出要求: +1. 使用 Markdown 输出,保持简洁,避免长篇解释。 +2. 先列问题,再给总结。 +3. 按 Critical、Warning、Suggestion 的顺序输出;同级别内按风险从高到低排序。 +4. 合并同类问题:同一根因、同一文件相邻代码、同一修复方式的问题应合并为一条,不要重复展开,也不要用不同表述重复描述同一问题。 +5. 优先输出高价值问题。Critical 和 Warning 不限数量但要合并;Suggestion 最多 2 条,且只有在确实有维护价值时输出。 +6. 每条问题控制在 2-3 句话内:说明问题、影响和修复方向即可,不要分别展开大段“问题/影响/建议”。 +7. 问题位置必须使用反引号包裹的 `文件路径:行号` 或 `文件路径:起始行-结束行` 格式,便于评论自动生成 GitHub 跳转链接。 +8. 如果没有发现明确问题,请直接说明“未发现明显阻塞问题”,不要为了完整性补充低价值建议。 +9. 如果同一段代码同时涉及多个相关风险(如命令注入、路径穿越),优先合并成一条,除非修复方式或影响范围明显不同。 +10. 对测试代码、示例代码、演示代码也按真实执行风险评估;如果这些代码会进入 CI、测试运行路径或被其他开发者复用,不要因为“仅用于示例/测试”而降低问题等级。 +11. 仅当问题离开具体代码片段不易理解时,才附带 3-8 行最小必要代码片段;前后可用 `...` 省略,不要默认给每个问题都附代码块,也不要贴大段代码。 +12. 结论要尽量确定:只有在确实无法从 diff 验证时,才使用“可能”“疑似”等措辞。 + +输出格式: + +## 发现的问题 + +如果存在问题,请按下面格式逐条输出。每条尽量一行位置 + 一段简短说明: + +### 🚨 Critical + +- `文件路径:行号`:问题标题 + - 简要说明具体风险和建议修复方式。 + - 如有必要,可附最小必要代码片段: + ```python + ... + 问题代码 + ... + ``` + +### ⚠️ Warning + +- `文件路径:行号`:问题标题 + - 简要说明具体风险和建议修复方式。 + - 如有必要,可附最小必要代码片段: + ```python + ... + 问题代码 + ... + ``` + +### 💡 Suggestion + +- `文件路径:行号`:问题标题 + - 简要说明维护性影响和可选优化方式。 + +如果某个等级没有问题,可以省略该等级。 + +## 总结 + +用 1-2 句话说明整体风险,以及是否存在必须修复的问题。 + +## 测试建议 + +如果需要补充测试,用 1-2 条说明建议覆盖的场景;如果不需要,请说明“暂无额外测试建议”。 \ No newline at end of file From cfd9752577c2a80552b7c91d401be9a276f94536 Mon Sep 17 00:00:00 2001 From: congkechen Date: Thu, 16 Jul 2026 10:09:19 +0800 Subject: [PATCH 2/4] Extend example_timeout_second in all_example_test --- pipeline_test/run_all_examples.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pipeline_test/run_all_examples.sh b/pipeline_test/run_all_examples.sh index 89c1fb468..7d7bc45ce 100644 --- a/pipeline_test/run_all_examples.sh +++ b/pipeline_test/run_all_examples.sh @@ -11,7 +11,7 @@ REPO_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)" RUN_MODE="all" FAIL_FAST=false INCLUDE_MANUAL=false -EXAMPLE_TIMEOUT_SECONDS="${EXAMPLE_TIMEOUT_SECONDS:-300}" +EXAMPLE_TIMEOUT_SECONDS="${EXAMPLE_TIMEOUT_SECONDS:-500}" PASSED=() FAILED=() From 9f515bc39b8b81a881acbfc6ef80a3df84eacf7c Mon Sep 17 00:00:00 2001 From: congkechen Date: Thu, 16 Jul 2026 10:42:38 +0800 Subject: [PATCH 3/4] test: add intentional bad code for AI review pipeline --- tests/ai_review_demo_bad_code.py | 121 +++++++++++++++++++++++++++++++ 1 file changed, 121 insertions(+) create mode 100644 tests/ai_review_demo_bad_code.py diff --git a/tests/ai_review_demo_bad_code.py b/tests/ai_review_demo_bad_code.py new file mode 100644 index 000000000..cc3856ead --- /dev/null +++ b/tests/ai_review_demo_bad_code.py @@ -0,0 +1,121 @@ +# Tencent is pleased to support the open source community by making tRPC-Agent-Python available. +# +# Copyright (C) 2026 Tencent. All rights reserved. +# +# tRPC-Agent-Python is licensed under Apache-2.0. +""" +AI Code Review 流水线效果验证用 demo。 + +本文件故意包含多类问题,供 AI review 抓取: +- Critical: 凭证硬编码、命令注入、路径穿越、明确逻辑错误 +- Warning: 空值/边界、资源未关闭、缺少超时 +- Suggestion: 可维护性 + +注意:不要把这个模块接到正式业务或 CI 执行路径上。 +pytest 默认也不会收集本文件(文件名不以 test_ 开头)。 +""" + +from __future__ import annotations + +import os +import subprocess +from pathlib import Path +from typing import Any + + +# --- Critical: 硬编码密钥 --- +API_KEY = "sk-live-hardcoded-secret-do-not-use" +DB_PASSWORD = "P@ssw0rd123" + + +def authenticate(user: str, token: str) -> bool: + """用硬编码密钥做“鉴权”,任何知道仓库内容的人都能伪造。""" + return token == API_KEY and user == "admin" + + +def run_user_command(cmd: str) -> str: + """Critical: 命令注入 —— 不可信输入直接进入 shell=True。""" + # 攻击示例: cmd = "ls; rm -rf /" + result = subprocess.run(cmd, shell=True, capture_output=True, text=True) + return result.stdout + + +def read_user_file(base_dir: str, relative_path: str) -> str: + """Critical: 路径穿越 —— 未规范化/校验就拼路径读文件。""" + # 攻击示例: relative_path = "../../etc/passwd" + target = base_dir + "/" + relative_path + with open(target, "r", encoding="utf-8") as f: + return f.read() + + +def apply_discount(price: float, percent: float) -> float: + """Critical: 逻辑错误 —— 折扣按加法算,导致价格算错。""" + # 正确应为: price * (1 - percent / 100) + return price + percent / 100 + + +def is_authorized(role: str | None) -> bool: + """Critical: 权限绕过 —— None/空字符串也会被当成授权通过。""" + # 本意是拒绝未登录;实际 `if not role` 为 True 时反而 return True + if not role: + return True + return role in {"admin", "editor"} + + +def fetch_profile(user_id: str | None) -> dict[str, Any]: + """Warning: 空值未处理 —— user_id 为 None 时会 TypeError。""" + return {"id": user_id, "name": user_id.upper()} + + +def average(scores: list[float]) -> float: + """Warning: 边界条件 —— 空列表直接 ZeroDivisionError。""" + return sum(scores) / len(scores) + + +def load_config(path: str) -> dict[str, str]: + """Warning: 资源未关闭 —— 打开文件后未 close / 未用 with。""" + f = open(path, "r", encoding="utf-8") + data = f.read() + # 故意不关闭 f + result: dict[str, str] = {} + for line in data.splitlines(): + if "=" in line: + k, v = line.split("=", 1) + result[k.strip()] = v.strip() + return result + + +def call_remote_api(url: str) -> str: + """Warning: 缺少超时 —— 外网请求可能永久挂起。""" + import urllib.request + + with urllib.request.urlopen(url) as resp: # noqa: S310 - demo only + return resp.read().decode("utf-8") + + +def dump_debug(env: dict[str, str] | None = None) -> None: + """Warning: 敏感信息输出 —— 把环境变量(可能含密钥)直接打印。""" + data = env if env is not None else dict(os.environ) + print("DEBUG ENV:", data) + + +def merge_settings(defaults: dict[str, Any], overrides: dict[str, Any] | None) -> dict[str, Any]: + """Suggestion: 可维护性 —— 原地修改 defaults,副作用不清晰。""" + if overrides: + defaults.update(overrides) + return defaults + + +def write_report(output_dir: str, name: str, content: str) -> Path: + """Suggestion: 可维护性 —— 魔法字符串/弱约束,长期难扩展。""" + # 没有校验 name,也没有统一路径工具 + p = Path(output_dir) / (name + ".txt") + p.write_text(content, encoding="utf-8") + return p + + +if __name__ == "__main__": + # 本地手测入口;正式 CI 请勿执行 + print(authenticate("admin", API_KEY)) + print(apply_discount(100, 10)) + print(is_authorized(None)) From 9c3ed20ec9c1665c5b0bb03aeaad50a66b2137d1 Mon Sep 17 00:00:00 2001 From: congkechen Date: Thu, 16 Jul 2026 10:54:36 +0800 Subject: [PATCH 4/4] renew test script --- tests/ai_review_demo_bad_code.py | 45 +------------------------------- 1 file changed, 1 insertion(+), 44 deletions(-) diff --git a/tests/ai_review_demo_bad_code.py b/tests/ai_review_demo_bad_code.py index cc3856ead..b62b8201e 100644 --- a/tests/ai_review_demo_bad_code.py +++ b/tests/ai_review_demo_bad_code.py @@ -1,20 +1,3 @@ -# Tencent is pleased to support the open source community by making tRPC-Agent-Python available. -# -# Copyright (C) 2026 Tencent. All rights reserved. -# -# tRPC-Agent-Python is licensed under Apache-2.0. -""" -AI Code Review 流水线效果验证用 demo。 - -本文件故意包含多类问题,供 AI review 抓取: -- Critical: 凭证硬编码、命令注入、路径穿越、明确逻辑错误 -- Warning: 空值/边界、资源未关闭、缺少超时 -- Suggestion: 可维护性 - -注意:不要把这个模块接到正式业务或 CI 执行路径上。 -pytest 默认也不会收集本文件(文件名不以 test_ 开头)。 -""" - from __future__ import annotations import os @@ -23,60 +6,46 @@ from typing import Any -# --- Critical: 硬编码密钥 --- API_KEY = "sk-live-hardcoded-secret-do-not-use" DB_PASSWORD = "P@ssw0rd123" def authenticate(user: str, token: str) -> bool: - """用硬编码密钥做“鉴权”,任何知道仓库内容的人都能伪造。""" return token == API_KEY and user == "admin" def run_user_command(cmd: str) -> str: - """Critical: 命令注入 —— 不可信输入直接进入 shell=True。""" - # 攻击示例: cmd = "ls; rm -rf /" result = subprocess.run(cmd, shell=True, capture_output=True, text=True) return result.stdout def read_user_file(base_dir: str, relative_path: str) -> str: - """Critical: 路径穿越 —— 未规范化/校验就拼路径读文件。""" - # 攻击示例: relative_path = "../../etc/passwd" target = base_dir + "/" + relative_path with open(target, "r", encoding="utf-8") as f: return f.read() def apply_discount(price: float, percent: float) -> float: - """Critical: 逻辑错误 —— 折扣按加法算,导致价格算错。""" - # 正确应为: price * (1 - percent / 100) return price + percent / 100 def is_authorized(role: str | None) -> bool: - """Critical: 权限绕过 —— None/空字符串也会被当成授权通过。""" - # 本意是拒绝未登录;实际 `if not role` 为 True 时反而 return True if not role: return True return role in {"admin", "editor"} def fetch_profile(user_id: str | None) -> dict[str, Any]: - """Warning: 空值未处理 —— user_id 为 None 时会 TypeError。""" return {"id": user_id, "name": user_id.upper()} def average(scores: list[float]) -> float: - """Warning: 边界条件 —— 空列表直接 ZeroDivisionError。""" return sum(scores) / len(scores) def load_config(path: str) -> dict[str, str]: - """Warning: 资源未关闭 —— 打开文件后未 close / 未用 with。""" f = open(path, "r", encoding="utf-8") data = f.read() - # 故意不关闭 f result: dict[str, str] = {} for line in data.splitlines(): if "=" in line: @@ -86,36 +55,24 @@ def load_config(path: str) -> dict[str, str]: def call_remote_api(url: str) -> str: - """Warning: 缺少超时 —— 外网请求可能永久挂起。""" import urllib.request - with urllib.request.urlopen(url) as resp: # noqa: S310 - demo only + with urllib.request.urlopen(url) as resp: return resp.read().decode("utf-8") def dump_debug(env: dict[str, str] | None = None) -> None: - """Warning: 敏感信息输出 —— 把环境变量(可能含密钥)直接打印。""" data = env if env is not None else dict(os.environ) print("DEBUG ENV:", data) def merge_settings(defaults: dict[str, Any], overrides: dict[str, Any] | None) -> dict[str, Any]: - """Suggestion: 可维护性 —— 原地修改 defaults,副作用不清晰。""" if overrides: defaults.update(overrides) return defaults def write_report(output_dir: str, name: str, content: str) -> Path: - """Suggestion: 可维护性 —— 魔法字符串/弱约束,长期难扩展。""" - # 没有校验 name,也没有统一路径工具 p = Path(output_dir) / (name + ".txt") p.write_text(content, encoding="utf-8") return p - - -if __name__ == "__main__": - # 本地手测入口;正式 CI 请勿执行 - print(authenticate("admin", API_KEY)) - print(apply_discount(100, 10)) - print(is_authorized(None))