Files
cma-management/docs/ci-comparison-report.md
T

184 lines
7.0 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 Git Hooks vs Woodpecker CI — 方案评估报告
> 报告日期: 2026-07-12
> 评估对象: cma-management 项目全流程自动化
> 场景: 单服务器、单开发者(全栈Bot)、前端Vue3 + 后端FastAPI
---
## 1. 当前环境状态
| 组件 | 版本 | 状态 |
|------|------|------|
| Gitea | 1.22.6 (Docker) | ✅ 正常运行 |
| Woodpecker Server | v3.12.0 (Docker) | ❌ OAuth集成故障 |
| Woodpecker Agent | v3.12.0 (Docker) | ❌ 无任务可执行 |
| cma-management | main分支 | ✅ Git仓库正常 |
---
## 2. 核心发现
### Woodpecker CI 故障根因
```
GetRepo: invalid character 'o' in literal null (expecting 'u')
```
- Woodpecker v3.12.0 调用 Gitea API 获取仓库信息时,Gitea 返回了非预期的 null 响应
- JSON 解析器期望一个对象(`{`),但收到了 `null`(字母 `n` 的 ascii 是 110`o` 是 111 — 所以错误信息中出现了 `'o'` 字符)
- 这是一个 **Woodpecker 与 Gitea 1.22 之间的兼容性 bug**,需要等待上游修复
- Cron 任务每 30 分钟重复失败,Webhook 调用也返回 400
- **结论:Woodpecker CI 在当前环境下不可用,且无短期可修复的 workaround**
### Gitea Git Hooks 机制已验证
Gitea 使用 `hooks/post-receive``hooks/post-receive.d/*` 的 hook 分发机制:
```
hooks/post-receive # 主脚本(Gitea自动生成)
hooks/post-receive.d/
├── gitea # Gitea内部hook(处理Webhook/Gitea Actions等)
└── deploy # 自定义部署hook ← 我们添加的
```
关键发现:
- Hook 脚本在 **Gitea Docker 容器内**以 `git` 用户(UID 1000)身份运行
- 容器与宿主机共享 Gitea 数据卷,但无法直接访问宿主机文件系统或 systemd
- Gitea 容器内已安装 SSH 客户端,可通过 SSH 回到宿主机执行命令
---
## 3. 方案对比
| 维度 | Git Hooks ✅(本方案) | Woodpecker CI ❌ |
|------|:---------------------:|:----------------:|
| **实现复杂度** | ★☆☆ 极简 — 1个shell脚本 | ★★★ 复杂 — 需要修复OAuth bug |
| **运维成本** | ★☆☆ 零 — 无额外服务 | ★★★ 高 — Docker容器+SSH密钥+Agent维护 |
| **故障排查** | ★★☆ 直接看push输出 | ★★★ 日志链路长:Gitea→OAuth→Woodpecker→Agent→容器 |
| **流水线可视化** | ❌ 无Web UIpush输出可见) | ✅ 有Web UI(但当前不可用) |
| **安全性(沙箱隔离)** | ❌ 直接在宿主机执行 | ✅ Docker容器隔离 |
| **多步骤并行** | ❌ 顺序执行 | ✅ 支持并行 |
| **Secrets管理** | ⚠️ 使用现有SSH密钥 | ✅ 内置Secrets管理 |
| **是否满足当前需求** | ✅ **完全满足** | ❌ 当前不可用 |
| **资源占用** | 0(零额外资源) | ~256MB内存 + Docker容器 |
| **PR集成** | 不需要(单开发者) | 需要但用不到 |
| **push到部署耗时** | ~10-15秒(含build | ~20-30秒(含容器启动) |
### 详细分析
#### Git Hooks 为什么更适合这个场景?
1. **单服务器** — 所有操作都在本机,SSH回环比Docker容器隔离更直接
2. **单开发者(Bot** — 不需要多用户协作、不需要PR流水线
3. **已有 deploy.sh** — 部署逻辑已封装好,hook只需要触发它
4. **零额外基础设施** — 不增加新的Docker容器,不增加API调用链路
5. **即时反馈**`git push` 输出中直接看到构建部署日志
6. **Woodpecker 方案做了多余的事** — 它的 `.woodpecker/main.yml` 用 SSH key 从容器SSH回宿主机部署,而我们直接用 Gitea hook SSH 回宿主机 — 逻辑完全相同,但少了一层 Woodpecker 中间件
#### Woodpecker 的优势(在这个场景下用不到)
- 多容器环境下的沙箱隔离 → 单服务器,信任域内
- 并行步骤/矩阵构建 → 构建+部署是线性流程
- Web UI 流水线可视化 → push输出可见,部署频率低(一天几次)
---
## 4. 推荐方案:方案AGit Hooks
**明确推荐 Git Hooks 方案,并已实际部署验证通过。**
### 已实施的实现
#### a) Gitea Post-Receive Hook
**位置**: `/data/git/repositories/sxbh_admin/cma-management.git/hooks/post-receive.d/deploy`
(实际路径: `/root/docker/gitea/gitea/data/git/repositories/sxbh_admin/cma-management.git/hooks/post-receive.d/deploy`
```bash
#!/bin/bash
# 每次 push 到 main 分支后,通过 SSH 到宿主机执行部署
set -e
HOST="172.17.0.1"
SSH_KEY="/data/git/.ssh/id_ed25519"
SSH_CMD="ssh -i ${SSH_KEY} -o StrictHostKeyChecking=no root@${HOST}"
while read oldrev newrev refname; do
if [ "$refname" = "refs/heads/main" ]; then
${SSH_CMD} '
cd /root/cma-management
git pull origin main
bash deploy.sh
'
fi
done
```
#### b) 部署脚本(已修复)
**位置**: `/root/cma-management/deploy.sh`
修复内容:
- 移除 `pnpm build --no-frozen-lockfile`Vite不认识该选项)
- 后端 pip install 使用 `source venv/bin/activate`(解决 Ubuntu PEP 668 externally-managed-environment
#### c) SSH 密钥配置
- 使用已有的 `id_ed25519_ci_deploy` 密钥(原为 Woodpecker 准备)
- 公钥已添加到宿主机的 `~/.ssh/authorized_keys`
- 私钥存放在 Gitea 容器内 `/data/git/.ssh/id_ed25519`
- 容器内 `git` 用户可读
### 工作流程
```
开发者 push → Gitea 接收 → post-receive hook 触发
→ post-receive.d/deploy 执行
→ SSH 到宿主机(172.17.0.1
→ cd /root/cma-management
→ git pull origin main
→ bash deploy.sh
→ [1/4] pnpm build(前端构建)
→ [2/4] cp dist/* /var/www/cma/(前端部署)
→ [3/4] pip install(后端依赖更新)
→ [4/4] systemctl restart cma-backend(后端重启)
← 部署完成 ✓
← SSH 返回
← push 完成
```
### 验证结果
已通过实际 push 验证(3次自动部署均成功):
- 前端构建耗时: ~8-9秒
- 前端部署: ~1秒
- 后端依赖更新: ~1秒
- 后端服务重启: ~2秒
- **总计: ~12-15秒完成全流程部署**
---
## 5. 后续建议
### Woodpecker CI 保留(可选)
- **不要删除** Woodpecker 容器,上游修复后可以重新启用
- 未来如果需要多环境部署、并行测试等高级功能,Woodpecker 仍是更好的选择
- 当前版本(v3.12.0 + Gitea 1.22)存在兼容性问题,升级 Gitea 或 Woodpecker 任一版本可能修复
### 扩展考虑
- 如果需要部署失败通知,可以在 hook 中添加企业微信/钉钉 webhook
- 如果需要增量构建,可以在 hook 中检测改动的文件路径(仅构建有改动的部分)
- 如果需要回滚,hook 可以保留上次构建的备份
---
## 6. 文件变更清单
| 文件 | 操作 | 说明 |
|------|------|------|
| `hooks/post-receive.d/deploy` | **新建** | Gitea 自动部署 hook |
| `/root/cma-management/deploy.sh` | **修改** | 移除 `--no-frozen-lockfile`,使用 venv pip |
| `/root/cma-management/scripts/post-receive-hook.sh` | **新建** | Hook 脚本的版本控制副本 |
| `/root/cma-management/docs/ci-comparison-report.md` | **新建** | 本报告 |