webhooks部署Github、GitLab、Gitee

假設,我們有三個環境:

線上倉庫。如Github、GitLab或Gitee(開源中國)

本地倉庫。日常開發用的。

服務器倉庫。一般是自動在測試服務器,或者生產服務器。

這裡我們要達到的目的是,

當有新的本地 commit push 到線上倉庫時,服務器倉庫自動pull最線上倉庫新的代碼。

1 工作原理

Webhooks工作原理很簡單,如下圖。

當我們push 代碼到線上倉庫,線上倉庫必然知道這個push操作,就會hook(回調)我們預留的URL。

而這個URL對應一段後臺代碼,這段代碼執行了git pull,這樣就實現下拉代碼操作。

上圖是以PHP為例,實際上用Java、Javascrtip等都可以,理論上一行代碼就可以搞定。

不過實際稍微複雜一點,需要進行一些安全驗證。

2 準備工作

首先,我們需要在服務器(生產或者測試等等)做一些準備工作。

最先應該做的,就是在服務器上安裝git(哈哈,這個應該都沒問題)

然後,克隆代碼:

$ cd /var/www/html # 代碼存放目錄

$ git clone https://github.com/yeszao/fastphp.git

因為這是公共倉庫,所以這裡我們使用的是https方式。

如果用SSH方式,需要配置SSH KEY,請參考這裡。

克隆完成後,代碼就在這個目錄裡面了:

/var/www/html/fastphp

這個就是服務器上的一個網站根目錄了,而且通過域名也是可以訪問其下的index.php等文件的。

3 PHP代碼

Github、GitLab和Gitee(開源中國,碼雲)雖然都是git倉庫平臺,但是發送的webhooks請求的數據格式有些差別。

Github支持application/json和application/x-www-form-urlencoded兩種格式,安全token需通過請求頭X-Hub-Signature加密發給URL,服務器需要解密後驗證。瞭解更多。

GitLab支持application/json格式,安全token通過請求頭HTTP_X_GITLAB_TOKEN明文發給URL。瞭解更多。

Gitee也支持application/json和application/x-www-form-urlencoded兩種格式,安全token放在請求體明文發給URL,名稱是password。瞭解更多。

請求頭我們可以通過$_SERVER全局變量獲得請求的值,比如$_SERVER['X-Hub-Signature']。

請求體則分為兩種:

如果是application/json格式,用這個方式獲得:

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

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

$payload = $_POST['payload'];

完整代碼如下(GitLab):

/ 本地倉庫路徑

$local = '/var/www/html/awaimai';

// 安全驗證字符串,為空則不驗證

$token = '123456';

// 如果啟用驗證,並且驗證失敗,返回錯誤

$httpToken = isset($_SERVER['HTTP_X_GITLAB_TOKEN']) ? $_SERVER['HTTP_X_GITLAB_TOKEN'] : '';

if ($token && $httpToken != $token) {

header('HTTP/1.1 403 Permission Denied');

die('Permission denied.');

}

// 如果倉庫目錄不存在,返回錯誤

if (!is_dir($local)) {

header('HTTP/1.1 500 Internal Server Error');

die('Local directory is missing');

}

//如果請求體內容為空,返回錯誤

$payload = file_get_contents('php://input');

if (!$payload) {

header('HTTP/1.1 400 Bad Request');

die('HTTP HEADER or POST is missing.');

}

/*

* 這裡有幾點需要注意:

*

* 1.確保PHP正常執行系統命令。寫一個PHP文件,內容:

* `

* 在通過瀏覽器訪問這個文件,能夠輸出目錄結構說明PHP可以運行系統命令。

*

* 2、PHP一般使用www-data或者nginx用戶運行,PHP通過腳本執行系統命令也是用這個用戶,

* 所以必須確保在該用戶家目錄(一般是/home/www-data或/home/nginx)下有.ssh目錄和

* 一些授權文件,以及git配置文件,如下:

* ```

* + .ssh

* - authorized_keys

* - config

* - id_rsa

* - id_rsa.pub

* - known_hosts

* - .gitconfig

* ```

*

* 3.在執行的命令後面加上2>&1可以輸出詳細信息,確定錯誤位置

*

* 4.git目錄權限問題。比如:

* `fatal: Unable to create '/data/www/html/awaimai/.git/index.lock': Permission denied`

* 那就是PHP用戶沒有寫權限,需要給目錄授予權限:

* ``

* sudo chown -R :www-data /data/www/html/awaimai`

* sudo chmod -R g+w /data/www/html/awaimai

* ```

*

* 5.SSH認證問題。如果是通過SSH認證,有可能提示錯誤:

* `Could not create directory '/.ssh'.`

* 或者

* `Host key verification failed.`

*

*/

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操作。

git push -u origin master


分享到:


相關文章: