将GitHub项目部署到服务器,Gitlab或者GitHub利用webhook实现push时项目自动部署

正 文:

前提:

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 [email protected]:li/test.git /storage/wwwroot/qy.a.net/

如果上面的第3步不做的话,可以模拟www用户身份执行:sudo -u www git clone [email protected]:li/test.git /storage/wwwroot/qy.a.net/

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

模拟www用户身份执行:sudo -u www git pull

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

将GitHub项目部署到服务器,Gitlab或者GitHub利用webhook实现push时项目自动部署_第1张图片

其中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": "[email protected]",

"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":"[email protected]: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":"[email protected]:mike/diaspora.git",

"ssh_url":"[email protected]:mike/diaspora.git",

"http_url":"http://example.com/mike/diaspora.git"

},

"repository":{

"name": "Diaspora",

"url": "[email protected]:mike/diaspora.git",

"description": "",

"homepage": "http://example.com/mike/diaspora",

"git_http_url":"http://example.com/mike/diaspora.git",

"git_ssh_url":"[email protected]: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": "[email protected]"

},

"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 代码如下:

//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

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

【参考】:

你可能感兴趣的:(将GitHub项目部署到服务器)