7.0 KiB
7.0 KiB
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 UI(push输出可见) | ✅ 有Web UI(但当前不可用) |
| 安全性(沙箱隔离) | ❌ 直接在宿主机执行 | ✅ Docker容器隔离 |
| 多步骤并行 | ❌ 顺序执行 | ✅ 支持并行 |
| Secrets管理 | ⚠️ 使用现有SSH密钥 | ✅ 内置Secrets管理 |
| 是否满足当前需求 | ✅ 完全满足 | ❌ 当前不可用 |
| 资源占用 | 0(零额外资源) | ~256MB内存 + Docker容器 |
| PR集成 | 不需要(单开发者) | 需要但用不到 |
| push到部署耗时 | ~10-15秒(含build) | ~20-30秒(含容器启动) |
详细分析
Git Hooks 为什么更适合这个场景?
- 单服务器 — 所有操作都在本机,SSH回环比Docker容器隔离更直接
- 单开发者(Bot) — 不需要多用户协作、不需要PR流水线
- 已有 deploy.sh — 部署逻辑已封装好,hook只需要触发它
- 零额外基础设施 — 不增加新的Docker容器,不增加API调用链路
- 即时反馈 —
git push输出中直接看到构建部署日志 - Woodpecker 方案做了多余的事 — 它的
.woodpecker/main.yml用 SSH key 从容器SSH回宿主机部署,而我们直接用 Gitea hook SSH 回宿主机 — 逻辑完全相同,但少了一层 Woodpecker 中间件
Woodpecker 的优势(在这个场景下用不到)
- 多容器环境下的沙箱隔离 → 单服务器,信任域内
- 并行步骤/矩阵构建 → 构建+部署是线性流程
- Web UI 流水线可视化 → push输出可见,部署频率低(一天几次)
4. 推荐方案:方案A(Git 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)
#!/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 |
新建 | 本报告 |