7.6 KiB
7.6 KiB
gitea-pr-review 设计文档
- 日期: 2026-04-08
- 项目:
gitea-pr-review - 目标: 读取 Gitea PR 信息,输出 LLM 友好的
Markdown与JSON
1. 背景与目标
当前需求是将单个 PR 的评审上下文整理成可直接喂给在同仓库工作的 LLM 的输入文档。重点是:
- 评论与回复内容完整保留(最高优先级)。
- 保留基础 PR 元信息,尤其是分支名与 commit 列表。
- 提供基础 diff stat(不含完整 diff 内容)。
- 输出两种格式:
markdown: 直接阅读与投喂 LLM。json: 结构化保真输出,便于脚本和后续处理。
2. 范围
2.1 In Scope
- 输入
pr_index,通过 Gitea API 拉取:- PR 基本信息(标题、作者、状态、源/目标分支、时间)
- review 列表
- review comments(含回复)
- commit 列表
- diff stat(文件级增删统计或可等价聚合的数据)
- 生成 Markdown 输出,结构遵循
README.md约定。 - 生成 JSON 输出,字段可追溯到源 API 实体。
- 处理评论正文为 Markdown 的情况,避免破坏外层文档结构。
2.2 Out of Scope
- 不输出完整 diff patch。
- 不做评论摘要、情感分析、优先级排序等“解释型加工”。
- 不做跨 PR 聚合。
3. 方案对比与结论
方案 A: 拉取后直接拼 Markdown
- 优点: 最快。
- 缺点: 结构易耦合;JSON 输出扩展困难;线程关系处理易混乱。
方案 B: 标准化模型 + 多格式渲染(推荐)
- 流程:
fetch -> normalize -> render(markdown/json) - 优点:
- 采集与展示解耦。
- 评论线程完整性规则可集中实现。
- 便于新增输出格式或字段。
- 缺点: 初期代码比 A 多一层。
方案 C: 模板引擎渲染
- 优点: 视觉格式更可配置。
- 缺点: 对当前固定结构需求偏重,收益不高。
结论
采用方案 B,优先保证数据完整性与可追溯性,再做格式输出。
4. 架构设计
4.1 模块划分
cli- 解析参数与环境变量。
- 决定输出格式与输出路径。
gitea_client- 仅负责 API 调用与分页。
- 返回原始 DTO(与 API 字段接近)。
normalize- 将原始 DTO 归一化为内部模型
PrReviewDocument。 - 负责线程聚合、排序、缺失值兜底。
- 将原始 DTO 归一化为内部模型
render_markdown- 将
PrReviewDocument渲染为 Markdown。
- 将
render_json- 将
PrReviewDocument序列化为稳定 JSON。
- 将
4.2 核心数据模型(内部)
PrReviewDocument
meta:
repo, pr_index, pr_title, pr_state, author
base_branch, head_branch
created_at, updated_at, merged_at?
commits: CommitItem[]
diff_stat:
files_changed, additions, deletions
files?: FileStat[]
reviews: ReviewItem[]
threads: CommentThread[]
CommentThread
thread_id
file_path?
line?
root_comment: CommentItem
replies: CommentItem[]
CommentItem.body 保存原始文本,不做语义改写。
5. 数据流与排序规则
- 读取输入:
pr_index来自命令行。repo/url/token来自环境变量或参数。
- 拉取数据:
- PR 基本信息
- reviews
- comments(含回复关系字段)
- commits
- diff stat
- 归一化:
- 基于
in_reply_to/original_id等字段聚合线程。 - 无父评论但标记为回复的异常数据,单独作为孤立线程并记录 warning。
- 统一按时间排序:
- 线程按根评论时间升序。
- 回复按时间升序。
- 基于
- 渲染:
- Markdown: 面向阅读。
- JSON: 面向程序消费。
6. Markdown 输出规范
目标: 对齐 README.md 给出的基础结构,保证评论内容完整。
6.1 顶层结构
# <repo> `#<pr-index>` <pr-title>
<基本信息区>
## Commits
- <sha-short> <title> (<author>, <date>)
...
## Diff Stat
- files changed: <n>
- additions: <n>
- deletions: <n>
## Review 1 (<review-state>)
> <reviewer>
### Comment 1.1
<file>:<line>
<user>:
```md
<原始评论正文>
```
### Reply 1.1.1
<user>:
```md
<原始回复正文>
```
6.2 Markdown 正文保真策略
评论正文可能本身含 Markdown(标题、列表、代码块、引用等),为避免破坏外层结构,统一策略:
- 评论正文使用 fenced code block 包裹,info string 为
md。 - 若正文内已含三反引号,动态选择更长 fence(例如四反引号)。
- 不转义正文中的 Markdown 语法,不改写文本。
7. JSON 输出规范
输出为单对象,建议结构如下:
{
"meta": {
"repo": "Origami404/aaa",
"pr_index": 123,
"title": "feat: ...",
"state": "open",
"author": "alice",
"base_branch": "main",
"head_branch": "feature/x",
"created_at": "2026-04-07T10:00:00Z",
"updated_at": "2026-04-08T10:00:00Z",
"merged_at": null
},
"commits": [
{
"sha": "abcdef...",
"short_sha": "abcdef1",
"title": "fix: ...",
"author": "bob",
"date": "2026-04-07T12:00:00Z"
}
],
"diff_stat": {
"files_changed": 3,
"additions": 120,
"deletions": 30,
"files": [
{"path": "src/a.rs", "additions": 10, "deletions": 2}
]
},
"reviews": [
{
"id": 1,
"state": "COMMENT",
"reviewer": "carol",
"submitted_at": "2026-04-08T08:00:00Z"
}
],
"threads": [
{
"thread_id": "t-1",
"file_path": "src/main.rs",
"line": 42,
"root_comment": {
"id": 11,
"user": "carol",
"created_at": "2026-04-08T08:01:00Z",
"body": "原始 markdown 文本"
},
"replies": [
{
"id": 12,
"user": "alice",
"created_at": "2026-04-08T08:02:00Z",
"body": "原始 markdown 文本"
}
]
}
]
}
约束:
body保留原始字符串。- 数组顺序稳定(按时间/出现顺序规则)。
- 字段缺失时使用
null或空数组,不省略关键键。
8. CLI 与配置
8.1 输入
- 必填:
pr_index(位置参数)
- 环境变量(可被参数覆盖):
GITEA_PR_CLI_API_TOKENGITEA_PR_CLI_URLGITEA_PR_CLI_REPO
8.2 输出参数(新增)
--format markdown|json|both(默认markdown)--out <path>(单输出文件)--out-dir <dir>(both时用于分文件输出)
9. 错误处理策略
- 配置错误: 缺 token/repo/url,直接报错并退出非 0。
- 网络/API 错误: 明确打印 HTTP 状态码与接口路径。
- 数据不完整:
- 评论缺父节点: 降级为孤立线程并 warning。
- 分支或 commit 字段缺失: 输出
null并 warning。
- 渲染错误: 指出是 Markdown 还是 JSON 渲染失败。
10. 测试策略
- 单元测试
- 线程聚合(正常链路、孤立回复、乱序输入)。
- Markdown fence 选择逻辑(三反引号冲突场景)。
- JSON 序列化稳定性(字段与顺序)。
- 快照测试
- 固定输入 DTO -> Markdown 输出快照。
- 集成测试
- 使用 mock server 覆盖分页、鉴权失败、空评论 PR。
11. 里程碑计划(高层)
- M1: 完成
gitea_client+ DTO。 - M2: 完成
normalize与线程规则。 - M3: 完成 Markdown 渲染并对齐 README 结构。
- M4: 完成 JSON 输出。
- M5: 补齐测试与错误处理。
12. 验收标准
- 能对任意有效 PR index 输出 Markdown,且包含:
- 基础信息
- 分支名
- commit 列表
- diff stat
- review/comment/reply 完整正文
- 能输出 JSON 且字段完整、顺序稳定。
- 评论正文含 Markdown/代码块时,Markdown 总文档结构不被破坏。
- 关键异常路径有清晰错误信息并返回非 0。