You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于Python watchdog实现GitHub repo master分支变更监控与自动同步

基于Python的GitHub仓库Push自动同步Watchdog实现

核心思路

Watchdog类监控的本质是主动定期比对GitHub远端仓库和本地部署仓库的commit差异,不需要服务器暴露公网端口,比Webhook模式更适配自有服务器无公网IP的场景,实现成本极低。

前置准备

  • 在自有服务器上提前克隆目标GitHub仓库的master分支,配置Git拉取的免密凭证(可用SSH密钥或GitHub PAT配合credential helper实现,避免pull操作时手动输入账号密码)
  • 安装所需Python依赖:pip install PyGithub schedule
  • 在GitHub账号下生成拥有目标仓库读取权限的Personal Access Token,配置为服务器环境变量,不要硬编码在脚本中
  • 注意:Token需要配置最小权限,只勾选仓库读取权限即可,不要开放多余的写权限

核心逻辑流程

  • 脚本启动时,从本地隐藏文件.last_sync_hash中读取上次成功同步的commit hash值,首次运行时自动读取本地仓库当前的HEAD hash作为初始值,避免启动时无意义的全量拉取
  • 按照预设的轮询周期(一般设60-120秒即可),调用GitHub API获取远端master分支的最新commit hash
  • 比对远端最新hash和本地记录的同步hash:
  • hash一致时,直接进入下一轮等待
  • hash不一致时,判定存在新的push操作,触发同步流程
  • 同步流程:进入本地仓库目录执行git pull origin master拉取最新代码,根据部署需求处理本地未提交的修改,拉取成功后将最新的远端commit hash更新写入本地记录文件,同时输出运行日志

可直接运行的核心参考代码

import os
import subprocess
import time
from github import Github
import schedule

# 配置项
GITHUB_TOKEN = os.getenv("GITHUB_PAT")
REPO_FULL_NAME = "你的GitHub用户名/目标仓库名"
LOCAL_REPO_PATH = "/opt/deploy/本地对应仓库的绝对路径"
LAST_HASH_FILE = os.path.join(LOCAL_REPO_PATH, ".sync_watchdog_hash")
POLL_INTERVAL = 120  # 轮询间隔,单位秒

def get_last_synced_hash():
    if not os.path.exists(LAST_HASH_FILE):
        result = subprocess.run(
            ["git", "-C", LOCAL_REPO_PATH, "rev-parse", "HEAD"],
            capture_output=True, text=True
        )
        return result.stdout.strip()
    with open(LAST_HASH_FILE, "r") as f:
        return f.read().strip()

def save_synced_hash(commit_hash):
    with open(LAST_HASH_FILE, "w") as f:
        f.write(commit_hash)

def check_and_sync():
    try:
        g = Github(GITHUB_TOKEN)
        repo = g.get_repo(REPO_FULL_NAME)
        latest_remote_hash = repo.get_branch("master").commit.sha
        last_synced = get_last_synced_hash()

        if latest_remote_hash != last_synced:
            print(f"检测到远端新提交:{latest_remote_hash},开始执行同步")
            pull_result = subprocess.run(
                ["git", "-C", LOCAL_REPO_PATH, "pull", "origin", "master", "--force"],
                capture_output=True, text=True
            )
            if pull_result.returncode == 0:
                save_synced_hash(latest_remote_hash)
                print(f"同步完成,当前本地版本hash:{latest_remote_hash}")
            else:
                print(f"同步失败,错误信息:{pull_result.stderr}")
    except Exception as e:
        print(f"Watchdog运行异常:{str(e)}")

if __name__ == "__main__":
    check_and_sync()
    schedule.every(POLL_INTERVAL).seconds.do(check_and_sync)
    while True:
        schedule.run_pending()
        time.sleep(1)

说明:如果本地需要保留环境特有的配置修改,不要加--force参数,可在pull前先执行git stash暂存本地修改,拉取完成后再执行git stash pop恢复修改,避免覆盖本地配置。

运维注意事项

  • 将脚本配置为systemd常驻服务,设置开机自启、异常崩溃自动重启,不要仅靠nohup手动拉起
  • 轮询间隔不要设置过短,带Token的GitHub接口限流为每小时5000次,按2分钟一次的频率运行全天仅触发720次请求,远低于限流阈值
  • 将脚本的输出日志重定向到本地文件,方便后续排查同步失败、网络异常等问题
  • 如果后续需要更高的实时性,可以在服务器有公网可达端口的前提下,将轮询逻辑替换为接收GitHub Webhook的触发逻辑,实现push后秒级同步,但无公网IP的场景下轮询Watchdog是最稳定省事的方案

内容的提问来源于stack exchange,提问作者Agosti Alessio

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.28 21:45:08