美文网首页Github项目管理
利用GitLab的Webhooks功能,实现网站代码自动更新部署

利用GitLab的Webhooks功能,实现网站代码自动更新部署

作者: hjqjk | 来源:发表于2017-09-15 00:06 被阅读955次

    根据业务需求,已部署GitLab-CE,网站代码上线流程如下图:

    开发者 push 推送代码之后,网站代码仍没更新,还需要操作多一步:登录前端web服务器,手动git pull 拉取更新的代码。这一步是运维的工作,很无趣又烦琐。

    幸亏,GitLab提供了Webhooks功能,可以轻松实现网站代码自动更新部署。

    一、webhooks原理

    Webhooks的原理

    Project webhooks allow you to trigger a URL if for example new code is pushed or a new issue is created.
    You can configure webhooks to listen for specific events like pushes, issues or merge requests. GitLab will send a POST request with data to the webhook URL.
    Webhooks can be used to update an external issue tracker, trigger CI jobs, update a backup mirror, or even deploy to your production server.

    简单说明

    webhooks允许指定一个URL,用于触发push或其他事件时进行自定义操作。
    例如,当开发者push代码到GitLab服务器,会触发push事件,GitLab会发送一个POST请求连带数据(数据格式)给webhooks指定的URL,该URL可以是前端web的php程序或Python程序等。这样,每当GitLab有push事件,就能在前端web服务器上执行一个脚本程序。

    使用webhooks的步骤:

    • 在前端web服务器上安装Git客户端,用于拉取远程仓库 git pull
    • 创建并添加公钥,以便免密码拉取远程仓库
    • 创建脚本程序,并配置webhooks

    二、安装Git客户端

    在前端web服务器上,执行以下安装命令

    # yum install git
    

    三、创建并添加公钥

    前端web服务器的 nginx 和 php-fpm 都是以 www 用户来运行的,所以要为www用户创建并添加公钥。

    www 用户的家目录是: /home/www/

    修改 www 用户的 shell 为 /bin/bash

    www:x:511:511::/home/www:/bin/bash
    

    创建用户的公钥

    # su www
    $ ssh-keygen -t rsa
    

    遇到交互,全部回车就好。
    最后会在/home/www/.ssh 目录下生成两个文件,私钥文件:id_rsa,公钥文件:id_rsa.pub

    添加公钥到GitLab后台

    获取www用户的公钥文件内容:

    cat /home/www/.ssh/id_rsa.pub
    

    复制公钥内容,添加公钥,GitLab后台添加公钥的位置:管理员 > Settings > SSH Keys

    修改网站根目录的权限

    修改网站根目录( /home/www/test/ ) 的权限,否则以www用户git pull 会报权限问题。

    # chmod 775 /home/www/test/ -R
    # chown www.www /home/www/test/ -R
    

    测试

    测试www用户基于公钥是否能从Git服务器远程拉取代码

    手动执行pull操作

    # su www
    $ cd /home/www/test/  
    $ git pull
    

    四、部署webhooks

    编写webhooks应用的PHP程序

    在前端web服务器的网站根目录(/home/www/test/)下新建一个webhooks.php

    <?php
    //网站目录
    $www_file='/home/www/test/';
    
    //打开网站目录下的hooks.log文件,需要在服务器上创建,并给写权限
    $fs = fopen('/home/www/test/hooks.log', 'a');
    
    fwrite($fs, '================ Update Start ==============='.PHP_EOL.PHP_EOL);
    
    //自定义字串掩码 用于验证
    $access_token = 'QhNO8YHqym5PHQQsexapF7041xOhzm62DRH';
    
    //接受的ip数组,也就是允许哪些IP访问这个文件 这里是gitlab服务器IP
    $access_ip = array('192.168.1.15','14.xxx.xxx.19');
    
    //如果使用www.xxx.com/xxx.php?token=xxxxxxx 的方式来传送验证字符串,则用这个方法获取
    # $client_token = $_GET['token'];
    
    // 获取请求端的secret token
    $client_token = $_SERVER["HTTP_X_GITLAB_TOKEN"];
    
    //获取请求端的IP
    $client_ip = $_SERVER['REMOTE_ADDR'];
    
    //把请求的IP和时间写进log
    fwrite($fs, 'Request on ['.date("Y-m-d H:i:s").'] from ['.$client_ip.']'.PHP_EOL);
    
    //验证token 有错就写进日志并退出
    if ($client_token !== $access_token)
    {
        echo "error 403";
        fwrite($fs, "Invalid token [{$client_token}]".PHP_EOL);
        exit(0);
    }
    
    //验证ip
    if ( !in_array($client_ip, $access_ip))
    {
        echo "error 503";
        fwrite($fs, "Invalid ip [{$client_ip}]".PHP_EOL);
        exit(0);
    }
    
    //获取请求端发送来的信息,具体格式参见gitlab的文档
    $json = file_get_contents('php://input');
    $data = json_decode($json, true);
    
    //如果有需要 可以打开下面,把传送过来的信息写进log
    # fwrite($fs, 'Data: '.print_r($data, true).PHP_EOL);
    
    //执行shell命令并把返回信息写进日志
    $output=shell_exec("cd $www_file && git pull 2>&1");
    fwrite($fs, 'Info:'. $output.PHP_EOL);
    
    fwrite($fs,PHP_EOL. '================ Update End ==============='.PHP_EOL.PHP_EOL);
    
    $fs and fclose($fs);
    
    ?>
    

    修改PHP配置

    因为webhooks用到的php代码中使用了 shell_exec 函数,一般配置php会禁止这个函数,需要打开 shell_exec 函数。
    修改前端web服务器上php.ini的 disable_functions 列表,去掉 shell_exec 。
    重启php-fpm服务。

    配置GitLab

    project > Settings > Integrations

    Secret Token中字符串的值,要跟webhooks.php中$access_token 的值相同。
    Enable SSL verification 不要勾。

    可以按 [Test] 按钮,测试配置是否生效。

    五、遇到的问题

    在部署webhooks中,遇到了个很诡异的问题。

    前提说明

    GitLab-CE 版本:9.2.6
    使用xhang项目对GitLab-CE进行汉化过

    问题描述:

    已成功部署webhooks,按 [Test] 按钮测试正常。
    但在实际使用中,开发者push代码后,webhooks.php没有被执行,前端web代码没有git pull 记录,日志也没有记录。GitLab没有检测到开发者的push事件。

    问题分析:

    • 通过另外部署一套同版本的、不打汉化补丁的GitLab-CE,发现不是汉化补丁的问题。
    • 回想起之前遇到的一个问题,在GitLab-CE上新创建test项目时,开发者push后,GitLab上仍然显示该项目是空项目,无法检测到push事件,后来还是通过修改项目名来使得其能识别push事件。

    问题解决:

    后来偶然发现,webhooks时GitLab没有及时检测到开发者的push事件,是因为对 /var/opt/gitlab/ 目录做了软链接的缘故。
    去掉软链接,改为正常的目录路径。

    相关文章

      网友评论

        本文标题:利用GitLab的Webhooks功能,实现网站代码自动更新部署

        本文链接:https://www.haomeiwen.com/subject/wgijsxtx.html