飘易博客(作者:Flymorn)
订阅《飘易博客》RSS,第一时间查看最新文章!
飘易首页 | 留言本 | 关于我 | 订阅Feed

Gitlab或者GitHub利用webhook实现push时项目自动部署

Author:飘易 Source:飘易
Categories:Linux技术 PostTime:2016-8-6 10:20:01
正 文:

前提:

1、Git服务器是指已经安装了Gitlab的Git管理服务器(Github的很多功能和Gitlab类似);

2、生产服务器是指配置好网站运行环境的测试服务器,默认apache的运行用户身份是www用户。


Git webhook以www用户实现自动部署的步骤

1、在Git服务器上创建一个普通git用户(无需密码),如server-115.159.10.10,然后把这个用户加入到目标项目里的成员里,只需要有pull权限即可,飘易一般设置为Reporter。


2、在生产服务器上为www用户生成 SSH 公钥,路径一般在 /home/www/.ssh/,把生成的公钥 id_rsa.pub 复制粘贴到Git服务器上第一步里的普通用户的ssh公钥里

生成命令:

sudo -u www ssh-keygen


3、【可选切换用户身份从root变成www,注意要把www的默认shell从/sbin/nologin改成/bin/bash,不然无法cd和git pull等;注:www用户没有密码,而Linux的pam验证拒绝没有密码的用户登录系统,所以我们不用担心www用户可以直接登录系统

su - www


4、首次从git服务器上抓取资源用clone,指定目录需要为空

git clone git@git.a.net:li/test.git /storage/wwwroot/qy.a.net/

如果上面的第3步不做的话,可以模拟www用户身份执行:

sudo -u www git clone git@git.a.net:li/test.git /storage/wwwroot/qy.a.net/


5、先cd到项目根目录,后续再抓取直接pull

git pull

模拟www用户身份执行:

sudo -u www git pull


6、网站根目录下放置 git-webhook-handler.php 自动部署文件,然后Git服务器的对应项目的 webhooks 配置上该文件的网址(Push events),需启用php的shell_exec函数。

其中Webhooks的push推送事件发生时,会向设置的URL上推送一个json消息,消息格式如下:

Push events

Triggered when you push to the repository except when pushing tags.


Request header:

X-Gitlab-Event: Push Hook

Request body:

{
  "object_kind": "push",
  "before": "95790bf891e76fee5e1747ab589903a6a1f80f22",
  "after": "da1560886d4f094c3e6c9ef40349f7d38b5d27d7",
  "ref": "refs/heads/master",
  "checkout_sha": "da1560886d4f094c3e6c9ef40349f7d38b5d27d7",
  "user_id": 4,
  "user_name": "John Smith",
  "user_email": "john@example.com",
  "user_avatar": "https://s.gravatar.com/avatar/d4c74594d841139328695756648b6bd6?s=8://s.gravatar.com/avatar/d4c74594d841139328695756648b6bd6?s=80",
  "project_id": 15,
  "project":{
    "name":"Diaspora",
    "description":"",
    "web_url":"http://example.com/mike/diaspora",
    "avatar_url":null,
    "git_ssh_url":"git@example.com:mike/diaspora.git",
    "git_http_url":"http://example.com/mike/diaspora.git",
    "namespace":"Mike",
    "visibility_level":0,
    "path_with_namespace":"mike/diaspora",
    "default_branch":"master",
    "homepage":"http://example.com/mike/diaspora",
    "url":"git@example.com:mike/diaspora.git",
    "ssh_url":"git@example.com:mike/diaspora.git",
    "http_url":"http://example.com/mike/diaspora.git"
  },
  "repository":{
    "name": "Diaspora",
    "url": "git@example.com:mike/diaspora.git",
    "description": "",
    "homepage": "http://example.com/mike/diaspora",
    "git_http_url":"http://example.com/mike/diaspora.git",
    "git_ssh_url":"git@example.com:mike/diaspora.git",
    "visibility_level":0
  },
  "commits": [
    {
      "id": "b6568db1bc1dcd7f8b4d5a946b0b91f9dacd7327",
      "message": "Update Catalan translation to e38cb41.",
      "timestamp": "2011-12-12T14:27:31+02:00",
      "url": "http://example.com/mike/diaspora/commit/b6568db1bc1dcd7f8b4d5a946b0b91f9dacd7327",
      "author": {
        "name": "Jordi Mallach",
        "email": "jordi@softcatala.org"
      },
      "added": ["CHANGELOG"],
      "modified": ["app/controller/application.rb"],
      "removed": []
    },
    {
      "id": "da1560886d4f094c3e6c9ef40349f7d38b5d27d7",
      "message": "fixed readme",
      "timestamp": "2012-01-03T23:36:29+02:00",
      "url": "http://example.com/mike/diaspora/commit/da1560886d4f094c3e6c9ef40349f7d38b5d27d7",
      "author": {
        "name": "GitLab dev user",
        "email": "gitlabdev@dv6700.(none)"
      },
      "added": ["CHANGELOG"],
      "modified": ["app/controller/application.rb"],
      "removed": []
    }
  ],
  "total_commits_count": 4
}


自动部署文件 git-webhook-handler.php 代码如下

<?php
//git webhook 自动部署脚本
//项目存放物理路径
$path = "/storage/wwwroot/qy.a.net/";
$requestBody = file_get_contents("php://input");
if (empty($requestBody)) {
    die('send fail');
}
$content = json_decode($requestBody, true);
//若是主分支且提交数大于0
if ($content['ref']=='refs/heads/master' && $content['total_commits_count']>0) {
    $res = shell_exec("cd {$path} && git pull 2>&1");//以www用户运行
    $res_log = '-------------------------'.PHP_EOL;
    $res_log .= $content['user_name'] . ' 在' . date('Y-m-d H:i:s') . '向' . $content['repository']['name'] . '项目的' . $content['ref'] . '分支push了' . $content['total_commits_count'] . '个commit:' . PHP_EOL;
    $res_log .= $res.PHP_EOL;
    file_put_contents("git-webhook.txt", $res_log, FILE_APPEND);//追加写入
}


如果本地有修改,希望强制用远程的库更新:

git fetch --all
git reset --hard origin/master


当我们希望不使用cd命令先到项目根目录的时候(对应上面不做第3步),可以使用git参数 --git-dir 和 --work-tree:

以www用户身份执行:
shell_exec("cd {$path} && git pull 2>&1")
改成:
shell_exec("git --git-dir={$path}.git fetch && git --git-dir={$path}.git --work-tree={$path} merge origin/master 2>&1")


注意,centos6上默认的git版本是1.7,而git 1.7在使用git pull时是有bug的,所以需要我们先fetch再merge!

cd /
sudo -u www git --git-dir=/storage/wwwroot/test/.git fetch
sudo -u www git --git-dir=/storage/wwwroot/test/.git --work-tree=/storage/wwwroot/test/ merge origin/master


而在git 1.8.5以上则可以直接使用下面的命令:

sudo -u www git --work-tree=/storage/wwwroot/test/ --git-dir=/storage/wwwroot/test/.git pull



上述的

shell_exec("cd {$path} && git pull 2>&1")

也可以使用下面的命令:

cd $path
git reset --hard origin/master
git clean -f
git pull
git checkout master

php里执行:

shell_exec("cd {$path} && git reset --hard origin/master && git clean -f && git pull 2>&1 && git checkout master")


【补充】:如何 clone git 项目到一个非空目录

如果我们往一个非空的目录下 clone git 项目,就会提示错误信息:

fatal: destination path '.' already exists and is not an empty directory.


解决的办法是:

1. 进入非空目录,假设是cd /workdir/proj1

2. git clone --no-checkout https://git.oschina.net/NextApp/platform.git tmp

3. mv tmp/.git .   #将 tmp 目录下的 .git 目录移到当前目录

4. rmdir tmp

5. git reset --hard HEAD

然后就可以进行各种正常操作了。



【参考】:

1、通过gitlab的webhook进行项目的自动部署所遇问题总结

2、利用gitlab的web hook和钉钉做代码review工作

3、使用 GitHub / GitLab 的 Webhooks 进行网站自动化部署


作者:飘易
来源:飘易
版权所有。转载时必须以链接形式注明作者和原始出处及本声明。
上一篇:CENTOS 6.5安装ffpmeg和 ffmpeg-php 扩展(LNMPA)的方法
下一篇:前端JS RSA加密,PHP后端解密实现密码安全传输
0条评论 “Gitlab或者GitHub利用webhook实现push时项目自动部署”
No Comment .
发表评论
名称(*必填)
邮件(选填)
网站(选填)

记住我,下次回复时不用重新输入个人信息
© 2007-2019 飘易博客 Www.Piaoyi.Org 原创文章版权由飘易所有