webhook 实现自动部署

Git Hook(钩子) 是 Git 在代码提交、推送、合并等工作流程中引入的事件触发器,其中最常用的场景是代码检查,持续集成,自动部署等,本文主要讲解利用webhook 实现自动部署的两种方式。

一、什么是Git webhook

Git 的 hook 分为本地仓库 hook 和服务器仓库 hook。

(一)本地 hook

本地 hook 通常在代码的 .git/hooks 目录下,如下所示:

$ hooks git:(master) ls
applypatch-msg.sample     pre-commit.sample             prepare-commit-msg.sample
commit-msg.sample         update.sample
post-update.sample        pre-push.sample
pre-applypatch.sample     pre-rebase.sample

默认情况下,这些脚本不会生效。使用时,只需将 .sample 后缀去掉,然后赋予脚本执行权限即可。
本地 hook 主要用于代码静态分析、REVIEW、代码规范、命名规范等。

  • pre-commit
    提交之前的代码检查,包括是否通过单元测试,静态代码分析
  • prepare-commit-msg
    提交信息之前,可用来生成默认的提交信息
  • commit-msg
    提交信息之后,可用来检查提交信息是否符合特定的格式
  • post-commit
    提交代码之后,一般用来通知代码已提交。
  • post-checkout
    checkout 代码之后,可用来设置工作目录、生成文档、生成静态资源等工作
  • post-merge
    合并代码之后,可用来保存 merge 操作中,git 没有保存的信息。
  • pre-push
    push 代码之前,可用来检查本次 push 的 commits 是否符合特定的标准。

(二)服务器 hook

服务器 hook 指代码传输到服务器时,在服务器端所做的一系列操作。

  • pre-receive
    处理 push 操作之前,可以检查本次 push 的 commits 和文件是否符合特定的标准。
  • update
    update 与 pre-receive 操作类似,不同的是 pre-receive 只执行一次,而 update 可能执行多次。
  • post-receive
    整个提交过程完成之后,可用于更新其它服务或通知用户,比如发邮件告诉开发人员已提交代码,通知持续集成 (Continuous Integration) 服务器部署代码

(三)webhook

如果 Git 服务部署在自己的服务器上,如用 GitLab 搭建一套 Git 服务,则可以使用服务器 hook。如果使用了 GitHub、Bitbucket 等云端平台,那么只能使用 webhook 来完成脚本。
webhook 本质上属于服务器 hook,因为发送通知的方式是网络请求,因此得名。使用 webhook 的步骤如下:

  1. 设置用于接收请求的 URL。
  2. 服务器收到 push、pull request、merge、tag 等操作时,会将相应信息发送给步骤 1 里的 URL。
  3. URL 对应的程序收到网络请求后,执行自动部署、邮件通知等操作。

二、部署 webhook

部署webhook有很多方式,本文仅讲解使用github-webhook工具和在nginx+php环境下部署webhook的两种方式

(一)github-webhook工具

github-webhook 文档

使用github-webhook

1.Go环境搭建

安装Sudo、Curl、Wget、Git、Vim
apt update && apt install sudo wget vim curl
(1)下载GO并解压
curl -O https://dl.google.com/go/go1.14.2.linux-amd64.tar.gz
tar xvf  go1.14.2.linux-amd64.tar.gz
sudo chown -R root:root ./go
sudo mv go /usr/local

注意:虽然/usr/local/go是官方推荐的位置,但有些用户可能更喜欢或需要不同的路径。

(2)设置Go路径

设置Go的根值,告诉Go在哪里查找其文件:

vi ~/.profile

在文件末尾添加以下行:

export GOPATH=$HOME/work
export PATH=$PATH:/usr/local/go/bin:$GOPATH/bin

如果为Go选择了不同的安装位置,则应将以下行添加到此文件中

export GOROOT=$HOME/go
export GOPATH=$HOME/work
export PATH=$PATH:$GOROOT/bin:$GOPATH/bin

注意:export GOROOT=$HOME/go在主目录中安装Go时所需的行
在Go安装到位并设置必要的环境路径后,让我们通过编写一个简短的程序来确认我们的设置是否有效

source ~/.profile

2.下载github-webhook工具

wget http://img.sgfoot.com/github-webhook1.4.1.linux-amd64.tar.gz

3.运行github-webhook

(1)安装
tar -zxvf github-webhook1.4.1.linux-amd64.tar.gz
cp github-webhook /usr/bin/
chmod u+x /usr/bin/github-webhook
(2)运行
  • 默认端口: 2020
  • 有效访问地址: http://ip:2020/web-hook
  • -b 是shell脚本路径参数
  • -s 是github webhook设置的密码
# 非后台运行
github-webhook -b [shell脚本路径] -s [github webhook设置的密码]

# 后台运行
nohup github-webhook -b [shell脚本路径] -s [github webhook设置的密码] & 

# 定向日志输出
nohup github-webhook -b ~/webhook.sh -s sopsopsop >> ~/webhook.log 2>&1 &
(3)webhook.sh
#! /bin/bash
SITE_PATH='/var/www/html'
USER='www-data'
USERGROUP='www-data'
cd $SITE_PATH
git reset --hard origin/master
git clean -f
git pull
git checkout master
chown -R $USER:$USERGROUP $SITE_PATH

赋予webhook.sh可执行权限

chmod +x webhook.sh

这样每次在客户端 push 代码,服务器会发请求给 github-webhook,github-webhook检查通过后,启动 webhook.sh 进行自动部署。

配置github webhook

  • 填写你服务器的地址, http://ip:2020/web-hook
  • 设置的密码必须与服务器运行github-webhook -s 设置的密码一致

(二)nginx+php环境下部署webhook

环境

Item Value
域名 www.qq.com
接收请求的URL https://www.qq.com/webhook.php
项目部署目录 /var/www/html
webhook.sh路径 ~/webhook.sh
webhook.php /var/www/html/webhook.php
环境 nginx php
用户组 www-data

Git config

Git 项目需要使用 SSH 地址,如 git@github.com:xxx/xxx.git 。如果之前采用了 HTTPS 链接,需要修改 .git/config 文件里的 url 字段:

vi .git/config
[remote "origin"]
    url = git@github.com:xxx/xxx.git
    fetch = +refs/heads/*:refs/remotes/origin/*

部署 SSH 无密码登录

首先需要生成 SSH key

sudo  -u www-data ssh-keygen -t rsa -C "nginx"

然后复制你的 public key,粘贴到项目的“SSH 公钥”设置里

cat /var/www/.ssh/id_rsa.pub

Github仓库中 Settings -> Deploy keys 选择 Add deploy key

添加完毕后,可以运行 ssh -T git@github.com 来验证是否设置成功。首次运行时会看到一条 RSA key 指纹的连接确认信息,输入 yes 回车即可

Hi username! You've successfully authenticated, but GitHub does not
provide shell access.

webhook.php

webhook.php 用来接收 webhook 请求,一般要做以下操作:

  • 监测请求来源合法性。检查方法:密码,AES等。
  • 检查是否为特定分支,如 master 分支。
  • 启动自动部署脚本,如完成拉取最新代码,重新设置目录权限等
<?php
$raw_data = file_get_contents("php://input");
$pay_load = json_decode($raw_data,true);
//监测请求来源合法性,
if($pay_load['password'] != 'pass'){
    exit('ok 400');
}
//检查是否为master分支
if($pay_load["ref"] != "refs/heads/master"){
    exit('ok 401');
}

exec('sh ~/webhook.sh');

webhook.sh

webhook.sh和github-webhook中脚本一样

三、声明

本文所有内容,包括文字、图片等来源以下地址,版权归原作者所有。
1.百里江山的博客,《github-webhook工具实现github自动构建》
2.David's world,《Git webhook 实现自动部署教程》