您现在的位置: 365建站网 > 365文章 > 使用Git的webhooks自动部署Github、GitLab、Gitee代码

使用Git的webhooks自动部署Github、GitLab、Gitee代码

文章来源:365jz.com     点击数:1620    更新时间:2018-07-25 10:39   参与评论

假设,我们有三个环境:

  1. 线上仓库。如Github、GitLab或Gitee(开源中国)

  2. 本地仓库。日常开发用的。

  3. 服务器仓库。一般是自动在测试服务器,或者生产服务器。

这里我们要达到的目的是,

当有新的本地 commit push 到线上仓库时,服务器仓库自动pull最线上仓库新的代码。

1 工作原理

Webhooks工作原理很简单,如下图。

当我们push 代码到线上仓库,线上仓库必然知道这个push操作,就会hook(回调)我们预留的URL。

而这个URL对应一段后台代码,这段代码执行了git pull,这样就实现下拉代码操作。

上图是以PHP为例,实际上用Java、Javascrtip等都可以,理论上一行代码就可以搞定。

不过实际稍微复杂一点,需要进行一些安全验证。

2 准备工作

首先,我们需要在服务器(生产或者测试等等)做一些准备工作。

最先应该做的,就是在服务器上安装git(哈哈,这个应该都没问题)

然后,克隆代码:

</>code

  1. $ cd /var/www/html           # 代码存放目录$ git clone https://github.com/yeszao/fastphp.git

因为这是公共仓库,所以这里我们使用的是https方式。

如果用SSH方式,需要配置SSH KEY,请参考这里。

克隆完成后,代码就在这个目录里面了:

</>code

  1. /var/www/html/fastphp

这个就是服务器上的一个网站根目录了,而且通过域名也是可以访问其下的index.php等文件的。

3 PHP代码

Github、GitLab和Gitee(开源中国,码云)虽然都是git仓库平台,但是发送的webhooks请求的数据格式有些差别。

  • Github支持application/jsonapplication/x-www-form-urlencoded两种格式,安全token需通过请求头X-Hub-Signature加密发给URL,服务器需要解密后验证。了解更多。

  • GitLab支持application/json格式,安全token通过请求头HTTP_X_GITLAB_TOKEN明文发给URL。了解更多。

  • Gitee也支持application/jsonapplication/x-www-form-urlencoded两种格式,安全token放在请求体明文发给URL,名称是password。了解更多。

请求头我们可以通过$_SERVER全局变量获得请求的值,比如$_SERVER['X-Hub-Signature']

请求体则分为两种:

如果是application/json格式,用这个方式获得:

</>code

  1. $payload = json_decode(file_get_contents('php://input'), true);

如果是application/x-www-form-urlencoded,就要用$_POST获得:

</>code

  1. $payload = $_POST['payload'];

完整代码如下(GitLab):

</>code

  1. <?php/ 本地仓库路径
  2. $local = '/var/www/html/awaimai';// 安全验证字符串,为空则不验证$token = '123456';// 如果启用验证,并且验证失败,返回错误$httpToken = isset($_SERVER['HTTP_X_GITLAB_TOKEN']) ? $_SERVER['HTTP_X_GITLAB_TOKEN'] : '';if ($token && $httpToken != $token) {
  3.     header('HTTP/1.1 403 Permission Denied');    die('Permission denied.');
  4. }// 如果仓库目录不存在,返回错误if (!is_dir($local)) {
  5.     header('HTTP/1.1 500 Internal Server Error');    die('Local directory is missing');
  6. }//如果请求体内容为空,返回错误$payload = file_get_contents('php://input');if (!$payload) {
  7.     header('HTTP/1.1 400 Bad Request');    die('HTTP HEADER or POST is missing.');
  8. }/*
  9.  * 这里有几点需要注意:
  10.  *
  11.  * 1.确保PHP正常执行系统命令。写一个PHP文件,内容:
  12.  * `<?php shell_exec('ls -la')`
  13.  * 在通过浏览器访问这个文件,能够输出目录结构说明PHP可以运行系统命令。
  14.  *
  15.  * 2、PHP一般使用www-data或者nginx用户运行,PHP通过脚本执行系统命令也是用这个用户,
  16.  * 所以必须确保在该用户家目录(一般是/home/www-data或/home/nginx)下有.ssh目录和
  17.  * 一些授权文件,以及git配置文件,如下:
  18.  * ```
  19.  * + .ssh
  20.  *   - authorized_keys
  21.  *   - config
  22.  *   - id_rsa
  23.  *   - id_rsa.pub
  24.  *   - known_hosts
  25.  * - .gitconfig
  26.  * ```
  27.  *
  28.  * 3.在执行的命令后面加上2>&1可以输出详细信息,确定错误位置
  29.  *
  30.  * 4.git目录权限问题。比如:
  31.  * `fatal: Unable to create '/data/www/html/awaimai/.git/index.lock': Permission denied`
  32.  * 那就是PHP用户没有写权限,需要给目录授予权限:
  33.  * ``
  34.  * sudo chown -R :www-data /data/www/html/awaimai`
  35.  * sudo chmod -R g+w /data/www/html/awaimai
  36.  * ```
  37.  *
  38.  * 5.SSH认证问题。如果是通过SSH认证,有可能提示错误:
  39.  * `Could not create directory '/.ssh'.`
  40.  * 或者
  41.  * `Host key verification failed.`
  42.  *
  43.  */echo shell_exec("cd {$local} && git pull 2>&1");die("done " . date('Y-m-d H:i:s', time()));

GitHub验证方式请看:https://gist.github.com/milo/daed6e958ea534e4eba3

4 Webhooks配置

4.1 Github

4.2 Githab

4.3 Gitee

请求数据格式默认是application/json格式,application/x-www-form-urlencoded格式的话需要选择:Old format

5 测试

以上我们都订阅了push事件。

这样只要我们本地仓库有push命令,都会执行一遍服务器仓库的git pull操作。

</>code

  1. git push -u origin master


相信很多码农都玩过了Git,如果对Git只是一知半解,可以移步LV写的 GIT常用操作总结,下面介绍到的一些关于 Git 的概念就不再赘述。

为啥想写这篇文章?主要是因为部门服务器因为安全性原因不允许SCP上传文件进行应用部署,然后有一些应用是放在Github上的,然后部署应用的步骤就变成:

1.git clone github项目 本地目录
2.配置一下应用的pm2.json并reload
3.Nginx配置一下反向代理并restart

当然如果只是一次性部署上去就不再修改的话并没啥问题,但是要是项目持续性修改迭代的话,就比较麻烦了,我们就在不断的重复着上面的步骤。作为一个码农,怎么允许不断的重复同样的工作,于是Github webhooks闪亮登场。

关于Github webhooks

让我们看看 官方 关于Github webhooks的解释:

Webhooks allow you to build or set up integrations which subscribe to certain events on GitHub.com.

提炼出来几个点:

  • 必须是Github上面的项目

  • 订阅了确定的事件(包括push/pull等命令)

  • 自动触发

刚好符合了这几个条件,那接下来就看看如何进行网站自动化部署,主要会从下面几点来讲解:

1.自动化shell脚本
2.服务端实现
3.配置github webhooks

自动化脚本

我之前翻译过一篇文章 使用Node.JS创建命令行脚本工具,但是我们现在的自动化脚本直接用 shell 来实现,假设名称为auto_build.sh

</>code

  1. #! /bin/bash
  2. SITE_PATH='/export/Data/aotu.jd.com/index/cnt1992.github.io'
  3. USER='admin'
  4. USERGROUP='admin'
  5. cd $SITE_PATH
  6. git reset --hard origin/master
  7. git clean -f
  8. git pull
  9. git checkout master
  10. chown -R $USER:$USERGROUP $SITE_PATH



Note: 在执行上面shell脚本之前我们必须第一次手动git clone项目进去,例如:

git clone github远程项目 /export/Data/aotu.jd.com/index/cnt1992.github.io


shell脚本其实就跟直接在终端运行命令一样,类似于windows下面的BAT批处理命令,更多详细可以查阅资料。

服务端实现

Github webhooks需要跟我们的服务器进行通信,确保是可以推送到我们的服务器,所以会发送一个带有X-Hub-SignaturePOST请求,为了方便我们直接用第三方的库github-webhook-handler来接收参数并且做监听事件的处理等工作。

现在我们可以在shell脚本的同级目录下面执行下面命令初始化一个package.json:


npm init -f


然后执行下面命令安装上面提到的第三方库:


npm i -S github-webhook-handler


接下来创建我们的服务主入口文件index.js


</>code

  1. touch index.js


紧接着参考github-webhook-handlerdemo编辑我们的index.js

</>code

  1. var http = require('http');
  2. var spawn = require('child_process').spawn;
  3. var createHandler = require('github-webhook-handler');
  4. // 下面填写的myscrect跟github webhooks配置一样,下一步会说;path是我们访问的路径
  5. var handler = createHandler({ path: '/auto_build', secret: '' });
  6. http.createServer(function (req, res) {
  7.   handler(req, res, function (err) {
  8.     res.statusCode = 404;
  9.     res.end('no such location');
  10.   })
  11. }).listen(6666);
  12. handler.on('error', function (err) {
  13.   console.error('Error:', err.message)
  14. });
  15. // 监听到push事件的时候执行我们的自动化脚本
  16. handler.on('push', function (event) {
  17.   console.log('Received a push event for %s to %s',
  18.     event.payload.repository.name,
  19.     event.payload.ref);
  20.   runCommand('sh', ['./auto_build.sh'], function( txt ){
  21.     console.log(txt);
  22.   });
  23. });
  24. function rumCommand( cmd, args, callback ){
  25.     var child = spawn( cmd, args );
  26.     var response = '';
  27.     child.stdout.on('data', function( buffer ){ resp += buffer.toString(); });
  28.     child.stdout.on('end', function(){ callback( resp ) });
  29. }
  30. // 由于我们不需要监听issues,所以下面代码注释掉
  31. //  handler.on('issues', function (event) {
  32. //    console.log('Received an issue event for %s action=%s: #%d %s',
  33. //      event.payload.repository.name,
  34. //      event.payload.action,
  35. //      event.payload.issue.number,
  36. //      event.payload.issue.title)
  37. });

然后利用node管理工具跑起来服务,这里使用了pm2


pm2 start index.js


到这一步服务已经跑起来了,但是对外网并不能直接访问到,所以还需要配置一下Nginx做一下反向代理:

</>code

  1. ···
  2. server {
  3.     listen 80;
  4.     server_name aotu.jd.com;
  5.     ···
  6.     location /auto_build {
  7.         proxy_pass http://127.0.0.1:6666;
  8.     }
  9.     ···
  10. }

OK,到这里整个服务已经搭建完成,下一步就只需要配置Github webhooks

配置github webhooks

我们可以在我们的Github上面最右边有一个Settings的Tab,找到Webhooks & services,如下图:

Github Webhooks

然后点击新建,输入Payload URLSecret,确定即可。

验证

绑定成功之后,我们可以试试提交一下代码,然后来到Github看看是否自动触发了接口,如下图:

Github Webhooks接口触发

然后随便选择一个点击一下,可以看到200的响应:

Github Webhooks接口触发

小结

上面就是利用Github webhooks进行网站自动化部署的全部内容了,不难发现其实这项技术还是有局限性的,那就是依赖于github,一般我们选择的都是免费github账号,所有项目都对外,一些敏感项目是不适合放置上去的。


如对本文有疑问,请提交到交流论坛,广大热心网友会为你解答!! 点击进入论坛

发表评论 (1620人查看0条评论)
请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
昵称:
最新评论
------分隔线----------------------------

快速入口

· 365软件
· 杰创官网
· 建站工具
· 网站大全

其它栏目

· 建站教程
· 365学习

业务咨询

· 技术支持
· 服务时间:9:00-18:00
365建站网二维码

Powered by 365建站网 RSS地图 HTML地图

copyright © 2013-2024 版权所有 鄂ICP备17013400号