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

7.0 KiB
Raw Permalink Blame History

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 是 110o 是 111 — 所以错误信息中出现了 'o' 字符)
  • 这是一个 Woodpecker 与 Gitea 1.22 之间的兼容性 bug,需要等待上游修复
  • Cron 任务每 30 分钟重复失败,Webhook 调用也返回 400
  • 结论:Woodpecker CI 在当前环境下不可用,且无短期可修复的 workaround

Gitea Git Hooks 机制已验证

Gitea 使用 hooks/post-receivehooks/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

#!/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-lockfileVite不认识该选项)
  • 后端 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 新建 本报告