环境

开发环境A,B,C...
Github仓库

目的

某一个开发环境修改代码后push到Github仓库时,所有开发环境都自动pull到本地,保证最新版本。做到一处push处处更新。

如果你的仓库并没有托管在Github上,而是自建的仓库,那么本文并不适用,下面这篇文章才是你想要的

方案

使用Github的webhook(官方称之挂钩事件,一般直接叫钩子或网络钩子)功能。在执行github的各种操作时,github会在特定的事件发生时调用你指定的网络api从而做你想做的事。
你可以简单的理解为Github里面的事件驱动,Github支持的事件有很多,甚至比git原生支持的事件更多,具体请参见官方中文说明
基于我的需求只需要用到push这个事件,当仓库接收Push请求并完成以后会调用这个hook。(类似于原生git的post-receive事件)

触发机制有了,我们还需要实现一个API供Github在发生Push时调用。

自己写?不不,找一个现成的轮子就行,笔者使用的是go语言开发的开源工具webhook。下面开工。

1-准备shell文件

新建一个工作目录,比如/home/mango/webhook

在工作目录下新建一个shell文件pull-all.sh,内容如下,该shell用来被hook调用,ssh到各个开发机并执行giit pull

#!/bin/sh

ssh -tt xxx@A << EOF
cd 环境A的Git目录
git pull
exit
EOF

ssh -tt xxx@B << EOF
cd 环境B的Git目录
git pull
exit
EOF

# ...

ssh -tt xxx@N << EOF
cd 环境N的Git目录
git pull
exit
EOF

保存文件并赋予可执行权限
chmod +x pull-all.sh

2-准备hook文件

在工作目录下继续新建一个文件hooks.json,内容如下

[
    {
      "id": "pull-all",
      "execute-command": "/etc/webhook/pull-all.sh",
      "command-working-directory": "/etc/webhook/"
    }
]

参数说明

  • id : hook名,可随便起,会影响最终提供服务的URL
  • execute-command : 第一步新建的shell。(容器内部的路径)
  • command-working-directory : shell运行目录(容器内部的路径)

3-用docker中一键下载并启动webhook

执行以下命令(用到刚才新建的文件)

docker run -d -p 9999:9000 -v /home/mango/webhook:/etc/webhook --name=webhook almir/webhook -verbose -hooks=/etc/webhook/hooks.json -hotreload

参数说明

  • 使用镜像 : almir/webhook
  • p: 宿主端口9999映射到容器内部端口9000
  • v:宿主机工作目录绑定到容器内部目录/etc/webhook
  • name:容器名
  • almir/webhook:别人做好的镜像名
  • verbose:输出更多调试信息
  • hooks:指定hook文件
  • hotreload:hook文件有更新时自动重新载入

由于需要在容器里使用ssh命令连接各开发机所以还要在容器内安装ssh客户端。

先进入容器

docker exec -it webhook /bin/sh

然后用apk安装openssh-client

apk add openssh-client

安装完后生成密钥对,输入以下命令后一路默认回车即可。

ssh-keygen

最后由于使用了ssh免密登录,所以要提前做好免密登录。执行以下命令经过一次密码登录以后即可免密。(服务器的公钥加入各开发机的.ssh/authorized_keys中)

ssh-copy-id xxx@A

4-在GitHub上设置webhook

进入仓库的Settings-Webhooks,点Add webhook添加一条webhook,如下
在Github添加Webhook
这里的端口就是之前docker run命令里指定的宿主机端口,如有必要记得还要开放或映射端口。
其他设置默认即可,trigger就用默认的Just the push event,只在push发生时触发。
最后点Add webhook启用即可。
搞定。现在不管哪台开发机push到Github都会自动让所有开发机pull最新代码。

最终流程图

Github Webhook

小结

其实整体流程跟下面这篇关于原生Git自动pull大致一样。都是利用了仓库的hook功能,只不过Github的钩子不能直接运行ssh需要依靠webhook做一下中转而已。
有兴趣可以看看介绍原生git-hook的文章,思路是一样的。

系列文章

Last modification:May 8, 2021
If you think my article is useful to you, please feel free to appreciate