dev-manager-tauri/.blueprint/modules/gitea-integration.md

215 lines
14 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: done
- 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作为复杂项目可选增配不进基线档
### 📋 R0. 炼境自身发版链路迁移(本机 act_runner + Gitea Actions
- status: todo
- complexity: M
- depends: Gitea Actions workflow 生成
- files: .gitea/workflows/release.yml生成, .github/workflows/release.yml删除
- acceptance: 本机安装 act_runner 并注册到 git.yljt.infowindows 标签,出站长连接、无入站需求);用 CicdModal 为炼境生成 Gitea 版 release workflow 并按需微调;删除 .github/workflows/ 死配置push 一个测试 tag 走通「构建 → 签名 → OSS 上传 → latest.json」全链路客户端自动更新恢复供给
> 背景GitHub 退役后 tag 不再触发旧 CI自动更新断供——这是当前唯一的结构性不自洽。act_runner 主动出站拉任务,完美适配公网 Gitea + 内网本机拓扑Tauri Windows 构建本就需要 Windows 环境,本机即最合适的 runner。
### 💭 旧项目 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 清理绑定
### ✅ G6. 远端轮询采集webhook 不可达时的降级路径)
- status: done
- complexity: M
- depends: G2
- files: src-tauri/src/commands/gitea.rs, src-tauri/src/lib.rs, src/lib/commands.ts, src/components/dashboard/GiteaPanel.tsx
- acceptance: 后台常驻线程每 10 分钟对所有 gitea_repos 绑定仓库调 GET /api/v1/repos/:owner/:repo/commits 拉取最新 commitrecord_commit 幂等写入gitea_poll_now 命令供 UI 手动触发并返回摘要;解析函数有单元测试;轮询结果记 log_event适配「公网 Gitea + 内网炼境」拓扑(纯出站,无需 webhook 可达)
> 背景:用户实际拓扑为公网云 Gitea + 内网本机炼境webhook 入站不可达;且不宜 frp 全端口映射 27190MCP 路由无鉴权)。轮询是该拓扑下唯一安全的远端采集方式。
### ✅ 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 回调地址
## 决策记录
- **公网 Gitea + 内网炼境为标准拓扑2026-07-02 裁决)**:观测面以 G6 出站轮询为主(每 10 分钟webhook 仅作同网/有穿透场景的补充。理由:① 炼境 27190 端口MCP 路由无鉴权)保持零公网暴露;② 飞轮是统计系统非监控系统10 分钟延迟在天/周分析粒度下为零影响;③ /ship 在 enterprise-system 已实证全出站 API 可支撑完整 PR 流水线;④ 主动拉取更贴合风筝线"持线人"定位。若未来需秒级实时:云服务器 nginx 仅反代 /webhook/gitea/ 路径 + 内网穿透(备案,不建议)
- 不用 frp 直接映射 27190MCP Server 工具路由无鉴权,全端口暴露 = append_project_note 等工具裸奔公网
## 复盘笔记
【复盘】G6 远端轮询采集2026-07-02
任务类型: 后端命令 + 前端组件
复杂度: M
实际轮数: 1轮预估 1 轮)
是否返工: 否
有效策略: 需求源自真实拓扑约束(用户确认公网 Gitea + 内网炼境),先做安全裁决(否决 frp 全端口映射)再写代码;解析函数纯函数化可测;复用 record_commit 幂等性使轮询与本地 watcher/全量导入三路径共存不重复计数
遗留风险: ① 轮询间隔 600s 硬编码仓库数大时50+)单轮串行请求可能拉长,届时可加并发或间隔配置;② limit=50 意味着 10 分钟内单仓库超 50 commit 会漏采(实际不可能,全量导入可兜底)
auto_applied_rules: R01, R07
rule_effectiveness: R01=有效gitea_poll_now 命令与 commands.ts 封装同步), R07=有效(解析纯函数 2 测试)
【复盘】Gitea Actions workflow 生成2026-07-02
任务类型: 后端命令 + 前端组件
复杂度: M
实际轮数: 1轮预估 1 轮)
是否返工: 否
有效策略: 语法兼容性使改造收敛为三处——输出目录 .gitea/workflows、去掉 GitHub Release 步骤(发布走 OSS 不需要 Release 页、runs-on 改自建 runner 标签;用单元测试断言"无 github.com/GITHUB_TOKEN 残留"把验收标准变成回归测试
遗留风险: ① tauri_oss 模板需要带 windows 标签的自建 act_runner尚未实际部署② actions/cachesetup-node 的 pnpm 缓存)依赖 act_runner 的 cache server旧版本 runner 可能不生效
auto_applied_rules: R01, R07
rule_effectiveness: R01=有效(命令未新增,仅改产出), R07=有效(模板残留断言测试)
【复盘】G2-G5 控制面 + 观测面全链路2026-07-02
任务类型: 后端命令 + MCP工具 + 前端组件
复杂度: M×4
实际轮数: 1轮预估 2 轮)
是否返工: 否
有效策略: 续接 🔵 锁前先读代码判断真实断点G1 已含查询命令G2 只缺三个写命令webhook 验签/解析拆成纯函数使单元测试不依赖 HTTP 层;绑定 UI 的 project_id 显式对齐 ingest_full_git_history 的 Project.id 体系
遗留风险: ① ~~全链路未在真实 Gitea 实例上端到端验证~~已消除2026-07-02 晚git.yljt.info 实测通过——实例连接 ✓ 迁移绑定 ✓ push ✓ 轮询采集 ✓webhook 因公网拓扑不适用,由 G6 轮询替代);② 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