Some checks failed
Build and Deploy Log Center / build-and-deploy (push) Failing after 1m55s
361 lines
9.2 KiB
Markdown
361 lines
9.2 KiB
Markdown
# PR 操作功能实施完成
|
||
|
||
> 实施日期: 2026-02-25
|
||
> 状态: ✅ 已完成
|
||
|
||
---
|
||
|
||
## 📋 已实现功能
|
||
|
||
### ✅ 1. 数据库字段扩展
|
||
|
||
**文件**: `app/models.py`
|
||
|
||
新增字段:
|
||
```python
|
||
# PR Tracking
|
||
pr_number: Optional[int] # PR 编号
|
||
pr_url: Optional[str] # PR 链接
|
||
branch_name: Optional[str] # 分支名称
|
||
|
||
# Rejection Tracking
|
||
rejection_reason: Optional[str] # 拒绝原因 JSON
|
||
rejection_count: int # 拒绝次数
|
||
last_rejected_at: Optional[datetime] # 最后拒绝时间
|
||
merged_at: Optional[datetime] # 合并时间
|
||
```
|
||
|
||
### ✅ 2. Gitea API 客户端
|
||
|
||
**文件**: `app/gitea_client.py`
|
||
|
||
功能:
|
||
- `merge_pr()` - 合并 PR
|
||
- `close_pr()` - 关闭 PR(带原因评论)
|
||
- `add_pr_comment()` - 添加评论
|
||
- `merge_pr_by_url()` - 通过 URL 直接合并
|
||
- `close_pr_by_url()` - 通过 URL 直接关闭
|
||
|
||
### ✅ 3. 后端 API 接口
|
||
|
||
**文件**: `app/main.py`
|
||
|
||
新增接口:
|
||
|
||
#### POST `/api/v1/bugs/{bug_id}/merge-pr`
|
||
|
||
批准并合并 PR
|
||
|
||
**请求**:无需 body
|
||
|
||
**响应**:
|
||
```json
|
||
{
|
||
"message": "PR 已合并",
|
||
"pr_url": "https://gitea.xxx/owner/repo/pulls/45",
|
||
"bug_id": 123,
|
||
"new_status": "FIXED"
|
||
}
|
||
```
|
||
|
||
#### POST `/api/v1/bugs/{bug_id}/close-pr`
|
||
|
||
拒绝修复并关闭 PR
|
||
|
||
**请求 Body**:
|
||
```json
|
||
{
|
||
"reason": "测试覆盖不足,缺少边界条件测试"
|
||
}
|
||
```
|
||
|
||
**响应**:
|
||
```json
|
||
{
|
||
"message": "PR 已拒绝,Bug 将重新修复",
|
||
"rejection_count": 1,
|
||
"bug_id": 123,
|
||
"new_status": "PENDING_FIX"
|
||
}
|
||
```
|
||
|
||
### ✅ 4. 前端界面
|
||
|
||
**文件**: `web/src/pages/BugDetail.tsx`
|
||
|
||
**新增组件**:
|
||
|
||
1. **PR 信息展示区**
|
||
- 显示 PR 编号、分支名
|
||
- "查看 PR" 外链按钮
|
||
- 拒绝次数提示
|
||
|
||
2. **操作按钮**
|
||
- ✅ **批准并合并** 按钮(绿色)
|
||
- ❌ **拒绝修复** 按钮(红色)
|
||
|
||
3. **拒绝原因模态框**
|
||
- 常用模板快速填充
|
||
- 文本输入框(详细原因)
|
||
- 确认/取消按钮
|
||
|
||
4. **状态消息**
|
||
- 操作成功/失败提示
|
||
- 上次拒绝原因显示
|
||
|
||
---
|
||
|
||
## 🎯 使用流程
|
||
|
||
### 场景 1:批准并合并
|
||
|
||
```
|
||
1. 打开 Bug 详情页
|
||
2. 查看 PR 信息(可点击"查看 PR"跳转到 Gitea)
|
||
3. 确认修复正确
|
||
4. 点击 "批准并合并" 按钮
|
||
↓
|
||
✅ PR 合并成功,Bug 状态 → FIXED
|
||
```
|
||
|
||
### 场景 2:拒绝修复
|
||
|
||
```
|
||
1. 打开 Bug 详情页
|
||
2. 查看 PR 信息
|
||
3. 发现问题,点击 "拒绝修复" 按钮
|
||
4. 弹出模态框:
|
||
- 可点击模板快速填充常用原因
|
||
- 或手动输入详细原因
|
||
5. 点击 "确认拒绝"
|
||
↓
|
||
✅ PR 已关闭,Bug 状态 → PENDING_FIX
|
||
✅ 原因已记录,Agent 将结合原因重新修复
|
||
```
|
||
|
||
---
|
||
|
||
## ⚙️ 配置步骤
|
||
|
||
### 1. 配置 Gitea 凭证
|
||
|
||
创建 `/log_center/app/.env` 文件:
|
||
|
||
```bash
|
||
# Gitea 配置
|
||
GITEA_URL=https://gitea.airlabs.art
|
||
GITEA_TOKEN=your_gitea_token_here
|
||
```
|
||
|
||
**获取 Gitea Token**:
|
||
1. 登录 Gitea
|
||
2. 设置 → 应用 → 生成新令牌
|
||
3. 权限:`repo`(读写仓库)
|
||
4. 复制 Token 到 `.env`
|
||
|
||
### 2. 数据库迁移
|
||
|
||
需要执行数据库迁移添加新字段:
|
||
|
||
```sql
|
||
-- 手动执行或使用 Alembic
|
||
ALTER TABLE errorlog ADD COLUMN pr_number INT;
|
||
ALTER TABLE errorlog ADD COLUMN pr_url VARCHAR(500);
|
||
ALTER TABLE errorlog ADD COLUMN branch_name VARCHAR(200);
|
||
ALTER TABLE errorlog ADD COLUMN rejection_reason TEXT;
|
||
ALTER TABLE errorlog ADD COLUMN rejection_count INT DEFAULT 0;
|
||
ALTER TABLE errorlog ADD COLUMN last_rejected_at TIMESTAMP;
|
||
ALTER TABLE errorlog ADD COLUMN merged_at TIMESTAMP;
|
||
```
|
||
|
||
### 3. 重启服务
|
||
|
||
```bash
|
||
# 后端
|
||
cd /log_center/app
|
||
uvicorn main:app --reload
|
||
|
||
# 前端
|
||
cd /log_center/web
|
||
npm run dev
|
||
```
|
||
|
||
---
|
||
|
||
## 🧪 测试
|
||
|
||
### 测试 Gitea API(可选)
|
||
|
||
使用测试脚本验证 API:
|
||
|
||
```bash
|
||
cd /log_center/repair_agent
|
||
python test_gitea_api.py \
|
||
--gitea-url https://gitea.airlabs.art \
|
||
--token YOUR_TOKEN \
|
||
--owner owner \
|
||
--repo repo \
|
||
--pr-number 45
|
||
```
|
||
|
||
### 手动测试流程
|
||
|
||
1. **准备测试数据**:
|
||
- 确保有一个状态为 `PENDING_FIX` 的 Bug
|
||
- 确保该 Bug 有 `pr_url` 字段(Repair Agent 创建的)
|
||
|
||
2. **测试合并**:
|
||
- 打开 Bug 详情页
|
||
- 点击"批准并合并"
|
||
- 检查:
|
||
- ✅ Bug 状态变为 `FIXED`
|
||
- ✅ Gitea PR 状态为 `Merged`
|
||
- ✅ `merged_at` 字段有值
|
||
|
||
3. **测试拒绝**:
|
||
- 打开另一个有 PR 的 Bug
|
||
- 点击"拒绝修复"
|
||
- 输入原因:"测试覆盖不足"
|
||
- 确认
|
||
- 检查:
|
||
- ✅ Bug 状态变为 `PENDING_FIX`
|
||
- ✅ Gitea PR 状态为 `Closed`
|
||
- ✅ PR 有评论记录原因
|
||
- ✅ `rejection_count` +1
|
||
- ✅ `rejection_reason` 有值
|
||
|
||
---
|
||
|
||
## 📸 界面预览
|
||
|
||
### 有 PR 的 Bug 详情页
|
||
|
||
```
|
||
┌─────────────────────────────────────────────────────┐
|
||
│ TypeError: 'NoneType' object is not iterable │
|
||
│ 项目: rtc_backend 来源: 运行时 级别: ERROR │
|
||
│ 状态: [待修复] │
|
||
├─────────────────────────────────────────────────────┤
|
||
│ Pull Request │
|
||
│ PR #45 | fix/auto-20260225-1430 │
|
||
│ [查看 PR →] 已拒绝 0 次 │
|
||
├─────────────────────────────────────────────────────┤
|
||
│ 文件位置: app/views.py : 第 24 行 │
|
||
│ ... │
|
||
├─────────────────────────────────────────────────────┤
|
||
│ [✅ 批准并合并] [❌ 拒绝修复] │ ← 关键按钮
|
||
└─────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
### 拒绝原因模态框
|
||
|
||
```
|
||
┌─────────────────────────────────────────┐
|
||
│ 拒绝修复 │
|
||
├─────────────────────────────────────────┤
|
||
│ 请说明拒绝原因,Agent 将根据反馈重新修复 │
|
||
│ │
|
||
│ 常用模板: │
|
||
│ [测试覆盖不足] [业务逻辑调整] [代码质量] │
|
||
│ │
|
||
│ ┌─────────────────────────────────────┐ │
|
||
│ │ [文本输入框] │ │
|
||
│ │ │ │
|
||
│ │ │ │
|
||
│ └─────────────────────────────────────┘ │
|
||
│ │
|
||
│ [取消] [❌ 确认拒绝] │
|
||
└─────────────────────────────────────────┘
|
||
```
|
||
|
||
---
|
||
|
||
## 🔍 技术细节
|
||
|
||
### 状态流转
|
||
|
||
```
|
||
【合并】
|
||
PENDING_FIX → 点击"批准并合并" → 调用 Gitea API merge
|
||
→ 更新 Bug 状态 FIXED → 设置 merged_at
|
||
|
||
【拒绝】
|
||
PENDING_FIX → 点击"拒绝修复" → 添加评论到 PR
|
||
→ 调用 Gitea API close → 更新 Bug 状态 PENDING_FIX
|
||
→ rejection_count +1 → 记录 rejection_reason
|
||
→ Agent 检测到 PENDING_FIX + 有 rejection_reason
|
||
→ 结合原因重新修复
|
||
```
|
||
|
||
### 安全性
|
||
|
||
1. **权限控制**:需要有效的 Gitea Token
|
||
2. **状态检查**:只有 `PENDING_FIX` 状态的 Bug 才能操作
|
||
3. **PR 验证**:必须有 `pr_url` 才能操作
|
||
4. **错误处理**:API 失败会显示详细错误信息
|
||
|
||
---
|
||
|
||
## ❓ FAQ
|
||
|
||
### Q1: 按钮显示条件?
|
||
|
||
**A:** 只有同时满足以下条件才显示:
|
||
1. Bug 有 `pr_url`(Agent 创建了 PR)
|
||
2. Bug 状态为 `PENDING_FIX`
|
||
|
||
### Q2: 拒绝后 Agent 会立即修复吗?
|
||
|
||
**A:** 取决于 Agent 扫描频率:
|
||
- 如果 Agent 定时扫描(如每小时),需等待下次扫描
|
||
- 可以手动触发 Agent 立即扫描特定项目
|
||
|
||
### Q3: 合并失败怎么办?
|
||
|
||
**A:** 常见失败原因:
|
||
1. Token 权限不足 → 检查 Token 权限
|
||
2. PR 有冲突 → 需要手动在 Gitea 解决冲突
|
||
3. PR 已关闭 → 检查 PR 状态
|
||
|
||
### Q4: 能否批量操作?
|
||
|
||
**A:** 当前版本不支持批量操作,计划在下个版本添加。
|
||
|
||
---
|
||
|
||
## 🎯 后续优化
|
||
|
||
### Phase 2(可选)
|
||
|
||
1. **批量操作**:
|
||
- 批量合并多个 PR
|
||
- 批量拒绝
|
||
|
||
2. **通知系统**:
|
||
- 邮件通知审核结果
|
||
- 钉钉/企业微信通知
|
||
|
||
3. **审批流程**:
|
||
- 指定审批人
|
||
- 需要多人审批
|
||
- 审批历史记录
|
||
|
||
4. **统计面板**:
|
||
- PR 合并率
|
||
- 平均拒绝次数
|
||
- 审核耗时
|
||
|
||
---
|
||
|
||
## ✅ 完成清单
|
||
|
||
- [x] 数据库字段扩展
|
||
- [x] Gitea API 客户端
|
||
- [x] 后端 API 接口
|
||
- [x] 前端界面实现
|
||
- [x] 拒绝原因模态框
|
||
- [x] 环境变量配置
|
||
- [x] 文档编写
|
||
|
||
**状态**: ✅ 功能已完整实现,可以部署使用!
|