feat: 仓库导入、分支模型重构与审查历史摘要

仓库接入
- 新增「从 Gitea 导入」:用全局 Token 列出可见仓库,一键建配置
- 新增仓库只填 Git 地址,自动解析 owner/name,支持 https/ssh/scp 写法
- 新增「测试连接」按钮,保存前即可校验地址并拉取分支

分支模型
- 由单一 base_branch + glob 改为「一个管理分支 + 多个检查分支」
- 管理分支是唯一合并目标;检查分支全部纳入监控
- 支持从任意分支克隆创建管理分支
- 审查基准改为管理分支的 merge-base;仅目标为管理分支的 PR 才自动合并
- 旧库自动迁移:base_branch 播种 managed_branch,branch_patterns 展开为检查分支

审查历史
- 新增 review_records 表与「审查历史」页
- 记录触发来源、PR 链接、审查范围、阻断阈值、发布方式、自动合并设置、
  排除路径、LLM 模型、token 消耗、耗时、需求背景与全部审查意见
- 详情弹窗一览,支持按仓库过滤

AI 摘要
- 新增独立摘要模块(app/lib/summary.js),与代码审查提示词分离
- 专用提示词输出固定四节、500 字内的中文记录:结论/范围/问题/要点
- 与代码审查共用全局 LLM 设置;摘要失败不影响审查与合并,可单条重跑

修复
- 摘要改用内置 fetch:运行镜像没有 curl,原先 spawn curl 必然 ENOENT
- 去掉 blob:none 部分克隆并把凭据写入 .git/config:
  惰性取 blob 不会带上 per-command extraHeader,私有库会报 could not read Username

UI
- 审查背景改为多行文本域(可滚动)
- 分支改为可点选列表,管理分支高亮
- 仓库表格展示管理分支与检查分支
This commit is contained in:
2026-09-20 12:38:23 +08:00
parent ed172bf369
commit 6dc77ce907
12 changed files with 1374 additions and 153 deletions
+44 -6
View File
@@ -19,10 +19,21 @@ Push / Pull Request 事件
## 功能
**仓库接入**
- 「从 Gitea 导入」一键列出全局 Token 可见的仓库,点「添加」即建好监控配置
- 手动新增时只填 Git 地址,自动识别 `所有者/仓库名`,旁边可「测试连接」验证
- 支持 https / ssh / scp 三种地址写法
**分支模型**
- 一个「管理分支」作为唯一合并目标
- 多个「检查分支」全部纳入监控,点选即可增减
- 管理分支不存在时可「克隆创建」,从任意已有分支复制
- 审查始终以管理分支为对比基准,即「这些改动合入管理分支会怎样」
**审查触发**
- 监听分支推送,自动对比上次提交或与目标分支的 merge-base
- 监听检查分支的推送,对比管理分支的 merge-base
- 监听 Pull Request 的 opened / synchronize / reopened / ready_for_review
- 按分支 glob 过滤(`*`、`release/*`、`main`),可选只审 PR 或只审 push
- 可选只审 PR 或只审 push
- 同一 commit 在队列中只入队一次;webhook 按 delivery id 去重
**发布结果**
@@ -38,8 +49,20 @@ Push / Pull Request 事件
- 合并方式、是否删除分支可配
- PR head 已变化或 PR 不可合并时自动放弃
**审查历史**
- 「审查历史」页按仓库汇总每次审查的摘要,可一键跳转 PR
- 每条记录保留完整上下文:触发来源、PR 链接、审查范围、阻断阈值、发布方式、
自动合并设置、排除路径、LLM 模型、token 消耗、耗时、本次填写的需求背景
- 详情弹窗列出本次全部审查意见,标注严重级别与是否阻断
**AI 摘要**
- 独立的摘要模块,与代码审查的提示词完全分开,但共用同一份全局 LLM 设置
- 专用提示词把一次审查压缩成固定四节、500 字内的记录:
`结论 / 范围 / 问题 / 要点`
- 摘要失败不影响审查结果,可单条重新生成
**运维**
- 内置 Web 后台:仓库配置、任务列表、实时日志、重跑、连通性自检
- 内置 Web 后台:仓库配置、审查历史、任务列表、实时日志、重跑、连通性自检
- 每次审查的完整日志和结果 JSON 落库
- worker 重启后自动回收卡住的任务,失败任务自动重试一次
- 全局或按仓库覆盖 Gitea token、LLM 端点 / 模型 / Key、排除路径、并发数
@@ -135,9 +158,10 @@ curl -fsS http://localhost:8090/api/health
| 字段 | 说明 |
| --- | --- |
| `branch_patterns` | 监听的分支 glob,逗号分隔;`*` 为全部 |
| `repo_url` | 仓库 Git 地址,`owner` / `name` 由此自动解析 |
| `managed_branch` | 唯一的管理分支,所有审查都相对它做对比,也是唯一允许自动合并的目标 |
| `check_branches` | 纳入监控的分支列表,逗号分隔;支持任意多个 |
| `review_scope` | `both` / `pr` / `push` |
| `base_branch` | 对比基准分支,也是无 PR 时 push 审查的目标 |
| `block_severity` | 阻断级别阈值,如 `critical,high`;留空则不看级别 |
| `block_categories` | 额外按类别阻断,如 `security` |
| `fail_on_findings` | 打开后任何意见都视为阻断 |
@@ -163,6 +187,13 @@ curl -fsS http://localhost:8090/api/health
| `GET` `POST` | `/api/repos` | 列出 / 新增仓库配置 |
| `GET` `PATCH` `DELETE` | `/api/repos/:id` | 读取 / 修改 / 删除 |
| `POST` | `/api/repos/:id/discover` | 校验连接,返回默认分支与分支列表 |
| `GET` | `/api/gitea/repos` | 列出全局 Token 可见的仓库,供一键导入 |
| `POST` | `/api/repos/parse` | 解析 Git 地址,返回 `owner` / `name` |
| `POST` | `/api/repos/branches` | 用 Git 地址查询分支(仓库尚未保存时使用) |
| `POST` | `/api/repos/:id/branches` | 创建分支,可从指定分支克隆 |
| `GET` | `/api/records` | 审查历史(`?repo_id=`、`?limit=`) |
| `GET` | `/api/records/:id` | 单条记录,含参数、意见与摘要 |
| `POST` | `/api/records/:id/summarise` | 重新排队生成摘要 |
| `GET` | `/api/jobs` | 任务列表(`?repo_id=`、`?limit=`) |
| `GET` | `/api/jobs/:id` | 任务详情,含日志 |
| `POST` | `/api/jobs/:id/retry` | 重跑任务 |
@@ -181,7 +212,11 @@ curl -X POST http://localhost:8090/api/review \
## 行为说明
**审查范围**:PR 事件用 `base.sha..head.sha`;push 事件用 webhook 里的 `before..after`,如果 `before` 是新建分支的全零值,则退回到与 `base_branch` 的 merge-base。
**分支与合并**:`check_branches` 里的每个分支都会被监控审查,审查基准是 `managed_branch`(用 merge-base 计算),也就是「这些改动合入管理分支会怎样」。自动合并只作用于目标为 `managed_branch` 的 PR,其他分支的 PR 只审不合。
**审查范围**:PR 事件优先用 PR 的目标分支作为基准;push 事件优先用 webhook 里的 `before`,当 `before` 是新建分支的全零值或缺失时,退回到与管理分支的 merge-base。
**审查背景**:仓库配置里的「审查背景 / 需求」是多行文本,既作为 OCR 的 `--background` 传给模型,也会完整记录到审查历史,方便回溯「当时是按什么需求审的」。
**阻断判定**:一条意见命中任一条件即为阻断 —— 严重级别 ≥ `block_severity` 中任一项,类别在 `block_categories` 中,或打开了 `fail_on_findings`。阻断会创建 Issue、把提交状态置为 `failure`,并阻止自动合并。
@@ -209,6 +244,9 @@ Gitea 拦截了内网地址。按上文给 `[webhook] ALLOWED_HOST_LIST` 加上
**后台打开后要求输入访问 Token**
这是 `CR_ADMIN_TOKEN` 在生效。输入 `.env` 里的值即可,Token 只存在浏览器本地。想免登录就把它留空并重启容器(仅限不对外暴露的网络)。
**历史记录一直显示「摘要生成中…」**
摘要与审查串行执行,一次只跑一个;如果 LLM 不可达会在记录里留下失败原因,可在详情里点「重新生成摘要」。摘要失败不会影响审查结论与自动合并。
**任务一直停在 `reviewing`**
LLM 慢或不可达。在后台「设置」点「测试 LLM」,或在「任务」页查看日志;调大 `CR_REVIEW_TIMEOUT_MS`。