根據(jù)業(yè)務(wù)需求,已部署GitLab-CE,網(wǎng)站代碼上線流程如下圖:
開發(fā)者 push 推送代碼之后,網(wǎng)站代碼仍沒更新,還需要操作多一步:登錄前端web服務(wù)器,手動git pull 拉取更新的代碼。這一步是運(yùn)維的工作,很無趣又煩瑣。
幸虧,GitLab提供了Webhooks功能,可以輕松實(shí)現(xiàn)網(wǎng)站代碼自動更新部署。
一、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,用于觸發(fā)push或其他事件時進(jìn)行自定義操作。
例如,當(dāng)開發(fā)者push代碼到GitLab服務(wù)器,會觸發(fā)push事件,GitLab會發(fā)送一個POST請求連帶數(shù)據(jù)(數(shù)據(jù)格式)給webhooks指定的URL,該URL可以是前端web的php程序或Python程序等。這樣,每當(dāng)GitLab有push事件,就能在前端web服務(wù)器上執(zhí)行一個腳本程序。
使用webhooks的步驟:
- 在前端web服務(wù)器上安裝Git客戶端,用于拉取遠(yuǎn)程倉庫 git pull
- 創(chuàng)建并添加公鑰,以便免密碼拉取遠(yuǎn)程倉庫
- 創(chuàng)建腳本程序,并配置webhooks
二、安裝Git客戶端
在前端web服務(wù)器上,執(zhí)行以下安裝命令
# yum install git
三、創(chuàng)建并添加公鑰
前端web服務(wù)器的 nginx 和 php-fpm 都是以 www 用戶來運(yùn)行的,所以要為www用戶創(chuàng)建并添加公鑰。
www 用戶的家目錄是: /home/www/
修改 www 用戶的 shell 為 /bin/bash
www:x:511:511::/home/www:/bin/bash
創(chuàng)建用戶的公鑰
# su www
$ ssh-keygen -t rsa
遇到交互,全部回車就好。
最后會在/home/www/.ssh 目錄下生成兩個文件,私鑰文件:id_rsa,公鑰文件:id_rsa.pub
添加公鑰到GitLab后臺
獲取www用戶的公鑰文件內(nèi)容:
cat /home/www/.ssh/id_rsa.pub
復(fù)制公鑰內(nèi)容,添加公鑰,GitLab后臺添加公鑰的位置:管理員 > Settings > SSH Keys
修改網(wǎng)站根目錄的權(quán)限
修改網(wǎng)站根目錄( /home/www/test/ ) 的權(quán)限,否則以www用戶git pull 會報權(quán)限問題。
# chmod 775 /home/www/test/ -R
# chown www.www /home/www/test/ -R
測試
測試www用戶基于公鑰是否能從Git服務(wù)器遠(yuǎn)程拉取代碼
手動執(zhí)行pull操作
# su www
$ cd /home/www/test/
$ git pull
四、部署webhooks
編寫webhooks應(yīng)用的PHP程序
在前端web服務(wù)器的網(wǎng)站根目錄(/home/www/test/)下新建一個webhooks.php
<?php
//網(wǎng)站目錄
$www_file='/home/www/test/';
//打開網(wǎng)站目錄下的hooks.log文件,需要在服務(wù)器上創(chuàng)建,并給寫權(quán)限
$fs = fopen('/home/www/test/hooks.log', 'a');
fwrite($fs, '================ Update Start ==============='.PHP_EOL.PHP_EOL);
//自定義字串掩碼 用于驗(yàn)證
$access_token = 'QhNO8YHqym5PHQQsexapF7041xOhzm62DRH';
//接受的ip數(shù)組,也就是允許哪些IP訪問這個文件 這里是gitlab服務(wù)器IP
$access_ip = array('192.168.1.15','14.xxx.xxx.19');
//如果使用www.xxx.com/xxx.php?token=xxxxxxx 的方式來傳送驗(yàn)證字符串,則用這個方法獲取
# $client_token = $_GET['token'];
// 獲取請求端的secret token
$client_token = $_SERVER["HTTP_X_GITLAB_TOKEN"];
//獲取請求端的IP
$client_ip = $_SERVER['REMOTE_ADDR'];
//把請求的IP和時間寫進(jìn)log
fwrite($fs, 'Request on ['.date("Y-m-d H:i:s").'] from ['.$client_ip.']'.PHP_EOL);
//驗(yàn)證token 有錯就寫進(jìn)日志并退出
if ($client_token !== $access_token)
{
echo "error 403";
fwrite($fs, "Invalid token [{$client_token}]".PHP_EOL);
exit(0);
}
//驗(yàn)證ip
if ( !in_array($client_ip, $access_ip))
{
echo "error 503";
fwrite($fs, "Invalid ip [{$client_ip}]".PHP_EOL);
exit(0);
}
//獲取請求端發(fā)送來的信息,具體格式參見gitlab的文檔
$json = file_get_contents('php://input');
$data = json_decode($json, true);
//如果有需要 可以打開下面,把傳送過來的信息寫進(jìn)log
# fwrite($fs, 'Data: '.print_r($data, true).PHP_EOL);
//執(zhí)行shell命令并把返回信息寫進(jìn)日志
$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配置
因?yàn)閣ebhooks用到的php代碼中使用了 shell_exec 函數(shù),一般配置php會禁止這個函數(shù),需要打開 shell_exec 函數(shù)。
修改前端web服務(wù)器上php.ini的 disable_functions 列表,去掉 shell_exec 。
重啟php-fpm服務(wù)。
配置GitLab
project > Settings > Integrations
Secret Token中字符串的值,要跟webhooks.php中$access_token 的值相同。
Enable SSL verification 不要勾。
可以按 [Test] 按鈕,測試配置是否生效。
五、遇到的問題
在部署webhooks中,遇到了個很詭異的問題。
前提說明
GitLab-CE 版本:9.2.6
使用xhang項(xiàng)目對GitLab-CE進(jìn)行漢化過
問題描述:
已成功部署webhooks,按 [Test] 按鈕測試正常。
但在實(shí)際使用中,開發(fā)者push代碼后,webhooks.php沒有被執(zhí)行,前端web代碼沒有g(shù)it pull 記錄,日志也沒有記錄。GitLab沒有檢測到開發(fā)者的push事件。
問題分析:
- 通過另外部署一套同版本的、不打漢化補(bǔ)丁的GitLab-CE,發(fā)現(xiàn)不是漢化補(bǔ)丁的問題。
- 回想起之前遇到的一個問題,在GitLab-CE上新創(chuàng)建test項(xiàng)目時,開發(fā)者push后,GitLab上仍然顯示該項(xiàng)目是空項(xiàng)目,無法檢測到push事件,后來還是通過修改項(xiàng)目名來使得其能識別push事件。
問題解決:
后來偶然發(fā)現(xiàn),webhooks時GitLab沒有及時檢測到開發(fā)者的push事件,是因?yàn)閷?/var/opt/gitlab/ 目錄做了軟鏈接的緣故。
去掉軟鏈接,改為正常的目錄路徑。