dev-manager-tauri/.blueprint/modules/gitea-integration.md
lanrtop d14b348845 feat(gitea): G2-G5 全链路——建仓/迁移/绑定 + webhook 收发 + 治理面板
G2 控制面:gitea_create_repo / gitea_migrate_repo / gitea_link_repo,
   upsert 绑定(换绑自动重置 webhook 字段),API 错误提取 Gitea message 可读返回
G3 观测面:MCP Server 新增 POST /webhook/gitea/:project_id——HMAC-SHA256 验签
   (X-Gitea-Signature,兼容 X-Hub-Signature-256)→ 解析 commits → 批量
   record_commit(sha 幂等,与本地 watcher 双路径不重复计数);验签失败记 log_event
G4 webhook 注册:gitea_setup_webhook 生成随机 secret 注册 push hook(重设先删旧)、
   gitea_unlink_repo 解绑顺带清理 Gitea 侧 hook
G5 治理面板:GiteaPanel——实例管理(添加/测试/删除)、当前项目三种绑定方式、
   webhook 注册与可复制回调地址、全部绑定概览

依赖:新增 hmac + sha2;project_id 与 commit_metrics 同源(Project.id),
避免双路径冲突复发;R10 修正设计文档错误签名头

验证:cargo test 58 passed(新增 upsert 换绑重置 + hmac 正反向 + payload 解析 5 测试)、
typecheck 全绿
2026-07-02 14:22:49 +09:00

172 lines
9.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Gitea 集成
对接已有的自建 Gitea 实例,作为所有被管理项目的统一 git 后端。接入包「增配档」的核心。
## 风筝线模型(炼境与 Gitea 的关系)
🪁 **风筝 = Gitea 本体**git 存储 + CI 执行):独立部署、独立运行,炼境**不托管其进程、不背运维**。
🧵 **线 = 炼境的掌控**(控制面):炼境是**唯一持线人**——Gitea 连接/token 统一存炼境,建仓/关联/迁移/配置 lefthook&CI 的操控全经炼境,子项目对 Gitea 的动作都从它手里过。
👀 **关注风筝的动态 = 观测面**(飞轮燃料):炼境持续感知每个子项目 ↔ Gitea 的连接动态push 的 commit type/scope、PR、CI 三阶段、review、停滞项目
> 「线」≠ 松散 API 对接:炼境是**主动掌控者**而非被动客户端。风筝越多 → 线越多 → 动态越丰富 → 飞轮越强(契合核心愿景)。
## 其他边界
- 替代炼境现有 GitHub 能力:`github-auth` / `github-publish` 已退役2026-07-02见 github-decommission`cicd.rs` 的 GitHub Actions 生成改造为 Gitea Actions
- 炼境自身仓库也迁 Gitea发布产物仍走 OSS updater 不变)
- **不使用 Gitea Issues / Projects / Milestones / Wiki**任务跟踪的意图层acceptance/complexity/depends/复盘)由蓝图任务卡承载,与 Claude 工作流深度耦合Gitea 只做三件事——存代码、跑 CI、发事件。蓝图与 Gitea 的唯一耦合关节 = conventional commit scope ↔ 蓝图 module id 映射(单点、单向、可降级)
## 参考实现
`enterprise-system` 已趟通完整链路,属「照搬」而非「从零探索」:
- Gitea origin`git.yljt.info`+ Gitee 镜像(备份)
- lefthook 强制 conventional commit + typecheckpre-commit
- Gitea Actions 三阶段 CI静态检查 → 测试DeepSeek-V3 自修)→ PR code reviewDeepSeek
- Gitea Actions 语法兼容 GitHub Actions迁移成本低
> 详见 `E:/code-project/enterprise-system/docs/ai-context/git-workflow.md` 与 `AGENTS.md`。
## 架构设计2026-06-30 /architect
### 实现策略
**webhook 接收端**:扩展已有 MCP ServerAxum端口 27190添加 `POST /webhook/gitea/:project_id` 路由。零新依赖,复用端口和进程。
**HTTP 客户端**`ureq`Cargo.toml 已有github.rs 已有使用范例),调 Gitea API v1。
**数据表**:新增 `gitea_instances`(实例管理)+ `gitea_repos`(项目-仓库绑定)。
```sql
CREATE TABLE IF NOT EXISTS gitea_instances (
id TEXT PRIMARY KEY,
name TEXT NOT NULL,
url TEXT NOT NULL, -- https://gitea.myserver.com
access_token TEXT NOT NULL,
is_default INTEGER NOT NULL DEFAULT 0,
created_at TEXT DEFAULT (datetime('now'))
);
CREATE TABLE IF NOT EXISTS gitea_repos (
id TEXT PRIMARY KEY,
instance_id TEXT NOT NULL REFERENCES gitea_instances(id) ON DELETE CASCADE,
project_id TEXT NOT NULL, -- blueprint_buffs.project_idUUID
gitea_owner TEXT NOT NULL,
gitea_repo_name TEXT NOT NULL,
clone_url TEXT,
webhook_secret TEXT, -- HMAC-SHA256 secret
webhook_id INTEGER, -- Gitea 返回的 hook ID
linked_at TEXT DEFAULT (datetime('now'))
);
CREATE UNIQUE INDEX IF NOT EXISTS idx_gitea_repos_project ON gitea_repos(project_id);
```
**webhook 流程**
```
Gitea push → POST /webhook/gitea/:project_id
1. 从 gitea_repos 查 webhook_secret
2. HMAC-SHA256 验签 X-Gitea-Signature兼容 X-Hub-Signature-256
3. 解析 payload.commits[]sha / message / timestamp
4. 批量 record_commit(project_id, sha, message, date)
5. 返回 200 OK验签失败记 log_event
```
> 修正2026-07-02R10原设计写的签名头 `X-Gitea-Signature-256` 有误Gitea 实际发送
> `X-Gitea-Signature`payload 的 HMAC-SHA256 hex实现以实际行为为准并兼容 GitHub 风格头。
> project_id 采用与 commit_metrics/ingest_full_git_history 相同的 Project.idgetProjects 体系),
> 避免重蹈 project_id 双路径冲突b13dc83 教训)。
**网络说明**Gitea 服务器需能访问宿主机 `{ip}:27190`MCP 端口。UI 显示可复制的 webhook 回调地址,用户自行确认网络可达。
---
## 任务卡concept待 /architect
### 💭 Gitea API 对接(握线基础)
- status: concept
- complexity: L
- acceptance: TBD —— 建仓/关联、推送、读 CI 状态、读 PR review 结果
> ⚠️ 建仓/关联部分已被 G1/G2 实现取代;剩余范围收窄为「读 CI 状态、读 PR review 结果」(依赖 Gitea Actions 落地后再议)。
### 💭 观测面Gitea webhook 接入(持线人感知动态)
- status: concept
- complexity: L
- files: src-tauri/src/mcp_server.rs内嵌 HTTP server 加 webhook 端点), src-tauri/src/commands/blueprint.rs
- acceptance: TBD —— 复用炼境内嵌 HTTP server 新增 Gitea webhook 接收端点;实时接住各子项目 push/PR/CI/review 事件 → 解析 conventional commit对接 flywheel-intelligence 的 L0 解析层)→ 写飞轮快照 + 刷新连接动态webhook 不可达时降级为定时轮询 Gitea API
> ⚠️ push 事件部分已被 G3/G4 实现取代剩余范围收窄为「PR/CI/review 事件 + 轮询降级」见「PR 事件 ↔ 蓝图任务卡联动」concept 卡)。
### 📋 Gitea Actions workflow 生成
- status: todo
- complexity: M
- depends: G1
- files: src-tauri/src/commands/cicd.rs, src/components/dashboard/CicdModal.tsx
- acceptance: generate_workflow 产出 Gitea Actions 模板(.gitea/workflows/,语法兼容 GitHub Actions参考 enterprise-system 三阶段 CIweb_ssh 与 tauri_oss 两类配置均支持CicdModal 的 Secrets 提示文案改为 Gitea 路径Settings → Actions → Secrets生成后模板中不残留 github.com 引用
> 一石三鸟:炼境自身仓库迁 Gitea 有了工具CicdModal 残留 GitHub 模板的问题解决(见 github-decommission 复盘遗留②CI 事实流有了源头。
### 💭 DeepSeek CI review 集成(可选插件)
- status: concept
- complexity: L
- acceptance: TBD —— 静态检查 + 测试自修 + PR review作为复杂项目可选增配不进基线档
### 💭 旧项目 GitHub → Gitea 迁移
- status: concept
- complexity: M
- acceptance: TBD —— remote 切换 + 推送,安全增量,不丢历史
### 💭 PR 事件 ↔ 蓝图任务卡联动
- status: concept
- depends: G3
- notes: webhook 收到 PR 事件 → 解析 title 的 conventional scope → 匹配蓝图模块 → 对应任务卡置 🔵 in_progress加锁提示。铁律 R09绝不自动置 ✅,完成语义只能由 Claude/人工验收产生merge 事件仅在导师报告中生成"待验收提醒"。不使用 Gitea Issues/Projects 做任务系统(见决策记录)。
---
## 任务卡(可执行,拆自 2026-06-30 /architect
### ✅ G1. DB schema + Gitea 实例 CRUD
- status: done
- complexity: M
- files: src-tauri/src/db.rs, src-tauri/src/commands/gitea.rs, src-tauri/src/lib.rs, src/lib/commands.ts
- acceptance: gitea_instances + gitea_repos 表建好migratesave/list/delete/test_connection 命令可调test_connection 调 GET /api/v1/user 返回 Gitea 用户名验证 token 有效性
### ✅ G2. 仓库创建 / 迁移 / 绑定
- status: done
- complexity: M
- depends: G1
- files: src-tauri/src/commands/gitea.rs, src/lib/commands.ts
- acceptance: gitea_create_repo 调 Gitea API 建仓后写 gitea_reposgitea_migrate_repo 能从 GitHub/GitLab 迁移仓库到 Giteagitea_link_repo 绑定已有仓库;命令失败返回可读错误
### ✅ G3. Webhook 接收端MCP Server 扩展)
- status: done
- complexity: M
- depends: G1
- files: src-tauri/src/mcp_server.rs
- acceptance: POST /webhook/gitea/:project_id 路由上线HMAC-SHA256 验签通过后解析 commits 数组批量写 commit_metrics验签失败记 log_event单元测试覆盖 parse_push_payload + hmac_verify
### ✅ G4. Webhook 注册命令
- status: done
- complexity: M
- depends: G2, G3
- files: src-tauri/src/commands/gitea.rs, src/lib/commands.ts
- acceptance: gitea_setup_webhook 生成随机 secret调 Gitea API POST /repos/:owner/:repo/hooks 注册events=push写 webhook_secret + webhook_id 到 gitea_reposgitea_unlink_repo 清理绑定
### ✅ G5. Gitea 治理面板 UI
- status: done
- complexity: M
- depends: G1, G2, G3, G4
- files: src/components/dashboard/GiteaPanel.tsx, src/components/dashboard/BlueprintModal.tsx
- acceptance: 治理面板新增"Gitea"区块;可添加/测试/删除实例;显示已绑定仓库列表(仓库名/webhook 状态);操作:新建仓库、迁移、绑定已有、设置 webhook显示可复制的 webhook 回调地址
## 复盘笔记
【复盘】G2-G5 控制面 + 观测面全链路2026-07-02
任务类型: 后端命令 + MCP工具 + 前端组件
复杂度: M×4
实际轮数: 1轮预估 2 轮)
是否返工: 否
有效策略: 续接 🔵 锁前先读代码判断真实断点G1 已含查询命令G2 只缺三个写命令webhook 验签/解析拆成纯函数使单元测试不依赖 HTTP 层;绑定 UI 的 project_id 显式对齐 ingest_full_git_history 的 Project.id 体系
遗留风险: ① 全链路未在真实 Gitea 实例上端到端验证(建仓/webhook 注册/push 接收),首次使用时按 G5 面板流程走一遍即是验收;② gitea_migrate_repo 未处理同名仓库已存在的场景Gitea 返回 409错误信息可读但需手动改名③ webhook 回调地址依赖用户确认网络可达,无自动探测
auto_applied_rules: R01, R05, R06, R07, R10
rule_effectiveness: R01=有效, R05=有效(复用已有表无新 migration, R06=有效upsert 依赖注入可测), R07=有效5 个新测试), R10=有效(纠正了设计文档中错误的签名头 X-Gitea-Signature-256 → 实际 X-Gitea-Signature