5.5 KiB
5.5 KiB
GitHub 与 Gitea 同步:脚本与钩子规则
目的:说清定时脚本与 Web 钩子的关系、是否冲突、最佳用法与固定规则。
维护:金仓
一、脚本 vs 钩子
| 方式 | 触发 | 方向 | 说明 |
|---|---|---|---|
| 定时脚本(cron) | 每 30 分钟 | GitHub → Gitea | NAS 上执行 sync_github_to_gitea.sh,拉取 GitHub 全仓/指定仓并推送到存客宝 Gitea。 |
| GitHub Web 钩子 | GitHub 有 push 时 | GitHub → Gitea | GitHub 向 NAS 上的接收端发 POST,接收端执行同步脚本(实时)。 |
| Gitea Web 钩子 | Gitea 有 push 时 | Gitea → 外部 | Gitea 向指定 URL 发 POST(通知用);若要做 Gitea→GitHub 反向同步,需接收端再推送到 GitHub。 |
二、是否冲突?结论:不冲突,用锁兜底
- 脚本与 GitHub 钩子:做的是同一件事(GitHub → Gitea),只是触发不同(定时 vs 事件)。可能同时发生(例如刚 push 完又赶上 cron),不会逻辑冲突,但并发跑同一仓库可能造成重复拉取/推送。
- 处理方式:同步脚本已加全局锁(同一时间只允许一个同步进程)。钩子或 cron 触发时,若脚本已在跑,后到的会等待锁或超时跳过,不会两个进程同时写同一仓库。
- Gitea 钩子:若只做「GitHub → Gitea」单向,不需要在 Gitea 配置钩子。若要做「Gitea → GitHub」反向,Gitea 钩子只负责「通知接收端」,由接收端去 push 到 GitHub,与脚本(GitHub→Gitea)方向相反,不冲突。
三、最佳方案(推荐)
-
主向:GitHub → Gitea(实时 + 兜底)
- 实时:在 GitHub 仓库或组织里配置 Web 钩子,Payload URL 指向 NAS 上的 webhook 接收端(需 NAS 有可从外网访问的地址,如 frp);触发时只同步该仓库(或按约定同步全仓)。
- 兜底:保留 cron 每 30 分钟 全量同步,防止钩子漏触发或网络问题。
- 规则:脚本带锁,钩子与 cron 都只调同一脚本,不会并发冲突。
-
Gitea 钩子(按需)
- 若只需「GitHub 为源、Gitea 为镜像」,不必在 Gitea 配置钩子。
- 若需「在 Gitea 的修改也推到 GitHub」:
- 在 Gitea 用户设置 → Web 钩子 添加「添加 Web 钩子」;
- URL 填接收端地址,触发事件选「推送」等;
- 接收端收到后,根据 payload 找到对应仓库并执行
git push到 GitHub(需在接收端配置 GitHub 权限)。
-
约定规则(固定)
- 源真相:默认以 GitHub 为准,Gitea 为镜像;反向(Gitea→GitHub)仅对明确需要的仓库开启。
- 只用一个同步脚本:所有同步(cron 或钩子触发)都调用
sync_github_to_gitea.sh(可带--repo xxx),脚本内用同一把锁。 - 不在 Gitea 侧做「镜像仓库」与脚本重复:若用 Gitea 的「从 URL 迁移/镜像」功能,就不要再对同一仓库用本脚本,二选一,避免双写。
四、Gitea 上钩子设置(界面说明)
- 打开 open.quwanzhi.com:3000 → 右上角头像 → 设置 → 左侧 Web 钩子。
- 「添加 Web 钩子」:选类型(如 Gitea 或 HTTP),URL 填你的接收端地址(例如
http://你的NAS或frp地址:端口/webhook)。 - 触发事件:至少勾选「推送」;若需合并请求等再勾选对应项。
- 说明:此处钩子为由 Gitea 发出的通知,用于「Gitea → 外部」(如 Gitea→GitHub 反向同步);GitHub → Gitea 的实时同步是在 GitHub 侧 配置钩子指向 NAS 接收端,而不是在 Gitea 配置。
五、脚本锁规则(实现层面)
- 同步脚本使用全局锁目录
$WORK_DIR.lock(如/tmp/github_gitea_sync.lock),通过mkdir原子性获取锁。 - 获取不到锁时,每 5 秒重试,超过
SYNC_LOCK_WAIT秒(默认 300)则退出,不执行本次同步。 - 脚本正常或异常退出时用
trap EXIT释放锁。 - 结论:cron 与 webhook 可同时配置,两者都触发同一脚本,由锁保证同一时刻只跑一个同步,无冲突。
六、Web 钩子接收端(实时触发同步)
- 位置:
scripts/webhook_receiver.py(Python 3,仅标准库)。 - 在 NAS 上运行:
cd /volume1/docker/gitea && nohup python3 webhook_receiver.py >> webhook.log 2>&1 &
默认监听 9999 端口,环境变量WEBHOOK_PORT可改。 - 行为:对任意路径的 POST(如
http://NAS或frp地址:9999/sync)执行同步;若 body 为 JSON 且含repository.name(GitHub/Gitea 格式),则只同步该仓库,否则全量同步。GET/、/sync、/health返回 200 用于探活。 - GitHub 配置:仓库或组织 → Settings → Webhooks → Add webhook → Payload URL 填
http://你的NAS公网或frp地址:9999/sync,Content type 选application/json,事件选 “Just the push event” 即可。 - Gitea 配置(仅当需要 Gitea→GitHub 反向时):用户设置 → Web 钩子 → 添加 Web 钩子 → URL 填上述地址,触发选「推送」。
七、相关文件
| 文件 | 说明 |
|---|---|
scripts/sync_github_to_gitea.sh |
带锁的同步脚本,GitHub → Gitea |
scripts/webhook_receiver.py |
NAS 上 Web 钩子接收端(被 GitHub/Gitea 调用) |
references/GitHub全仓同步到CKB_NAS_Gitea_方案与双向说明.md |
全量同步与部署说明 |
版本:v1.0