Github 通过 Action 自动从上游同步代码, 接近实时

在 GitHub fork 一个仓库后,原仓库更新了,下游可以通过 GitHub Action 自动拉取上游的更新,与上游同步。


网上找了很多 Action 脚本,都不能在私有仓库工作。我详细说一下情况: Organization 有一个私有仓库,要部署到 Vercel 上,可 Vercel 部署 Organization 的仓库要 team(付费),为了免费,创建了一个 GitHub 帐号(叫他 worker),fork Organization 的仓库,由 Vercel 部署 worker 帐号中的仓库,这样就避免了付费。同时组织中不同人可能 push,所以 worker 帐号要实时同步。

网上找了很多 Action 脚本,用了 GitHub cli 或者 actions/checkout@v3 等,都不能正常工作,提示找不到上游仓库,猜测是因为权限问题,可是该给的权限都给了,同样的步骤在本地可以正常执行,查看 actions/checkout@v3 的操作,发现很多为了安全的命令,因此推断 actions/checkout@v3 特殊的操作有影响权限的地方。因此直接用暴力手段同步:clone 下 fork 的仓库,添加原版的 remote (起名叫 upstream),强行 merge ,最后 push。甚至可以直接 clone 下原版的仓库,添加 worker 的 remote,强行 push。

# .github/workflows/fetch.yml

name: Merge upstream branches
on:
  schedule:
    - cron:  '* * * * *'
  workflow_dispatch:
jobs:
  merge:
    runs-on: ubuntu-latest
    steps:
      - name: Merge upstream
        run: |
          git config --global user.name 'someone'
          git config --global user.email 'someone@example.com'
          git config --global credential.helper store
          git clone https://${{ secrets.PAT_TOKEN }}@github.com/worker/website.git tmp
          cd tmp
          git remote add upstream https://${{ secrets.PAT_TOKEN }}@github.com/organization/website.git
          git fetch upstream
          git merge upstream/master
          git push origin master          

整个脚本非常简单,一部分 cron 设置运行时间,一部分设置如何 sync。 需要修改的地方有

  1. someone , someone@example.com, 改为你的账户
  2. github.com/worker/website.git,改为 worker fork 的仓库的地址
  3. github.com/organization/website.git, 改为 organization 中原始仓库的地址
  4. 在 worker 的 GitHub 帐号中,申请一个 personal access token, 加入到 worker web 仓库的 Secrets 中,起名叫 PAT_TOKEN(或者直接将 ${{ secrets.PAT_TOKEN }} 替换为 token)

上面的脚本,随便起个名,放进 .github/workflows/ 这个路径下。

需要注意的是,虽然脚本的 cron 里,设置每分钟都更新一次,可是实际的执行间隔大概有 5 - 30 分钟不等。