环境
开发环境A,B,C...
Github仓库
目的
某一个开发环境修改代码后push到Github仓库时,所有开发环境都自动pull到本地,保证最新版本。做到一处push处处更新。
方案
使用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,如下
这里的端口就是之前docker run命令里指定的宿主机端口,如有必要记得还要开放或映射端口。
其他设置默认即可,trigger就用默认的Just the push event
,只在push发生时触发。
最后点Add webhook启用即可。
搞定。现在不管哪台开发机push到Github都会自动让所有开发机pull最新代码。
最终流程图
小结
其实整体流程跟下面这篇关于原生Git自动pull大致一样。都是利用了仓库的hook功能,只不过Github的钩子不能直接运行ssh需要依靠webhook做一下中转而已。
有兴趣可以看看介绍原生git-hook的文章,思路是一样的。
系列文章
- Git hook: post-receive 多客户端中任意一个客户端Push到仓库时自动让所有客户端进行Pull操作
- Github webhook: 多客户端中任意一个客户端Push到Github仓库时自动让所有客户端进行Pull操作【当前文章】