Webhook,顧名思義就是鉤子,簡而言之,能夠在特定狀況下觸發特定的操做。例如在遠程git倉庫中進行了push、tag等操做時,自動在遠程server端自動拉取、編譯代碼。 如下是一個push代碼到遠程倉庫後,自動拉取代碼進行編譯後,將生成的Webassembly相關的文件(.js,.wasm)和版本號push到遠程倉庫中的demo。php
首先,須要擁有項目的管理者權限,點擊項目首頁上方的管理,而後點擊左側菜單下方的WebHooks,進入到如下截圖的設置頁面。 html
在上面的的界面中,我已經添加了一個Webhook,觸發類型爲push,同時還有一個密碼。 當你push代碼到遠程倉庫時,會往這裏設置的URL發送一個攜帶着設置好密碼的POST請求。固然你也能夠勾選其餘的操做類型。nginx
<?php
// 本地倉庫路徑
$local = '/data/wwwroot/default/hooks/laserbox';
// 安全驗證字符串,爲空則不驗證
$token = '123456';
// payload爲字符串,須要通過解析
$payload = file_get_contents('php://input');
if (!$payload) {
header('HTTP/1.1 400 Bad Request');
die('HTTP HEADER or POST is missing.');
}
$content = json_decode($payload, true);
// 若是啓用驗證,而且驗證失敗,返回錯誤
if ($token && $content['password'] != $token) {
header('HTTP/1.1 403 Permission Denied');
die('Permission denied.');
}
//最後會執行一個腳本編譯代碼,而後再push代碼到遠程
//因此會重複觸發WebHooks,所以此處判斷是不是本地的推送
if($content['commits'][0]['author']['name'] == 'handsomeTaoTao'){
header('HTTP/1.1 403 Permission Denied');
die('self push.');
}
/*
* 這裏有幾點須要注意:
*
* 1.確保PHP正常執行系統命令。寫一個PHP文件,內容:
* `<?php echo shell_exec('ls -la')`
* 在經過瀏覽器訪問這個文件,可以輸出目錄結構說明PHP能夠運行系統命令。
*
* 二、PHP通常使用www-data或者nginx用戶運行,PHP經過腳本執行系統命令也是用這個用戶,
* 在經過瀏覽器訪問這個文件,可以輸出目錄結構說明PHP能夠運行系統命令。
*
* 二、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.`
*
*/
// shell_exec函數默認是禁止的,沒法使用的話須要進php.ini修改相關配置
//執行shell時,沒有sudo彷彿會執行不成功,只執行一小段,加了sudo以後執行成功,能夠爲運行php的用戶添加sudo權限,參考資料有相關問題
echo shell_exec("cd {$local} && sudo sh ./autoCompiled.sh");
die("done " . date('Y-m-d H:i:s', time()));
複製代碼
#!/bin/sh
source /data/git/emsdk/emsdk_env.sh // 載入命令,不然在命令行中沒法使用emcc等編譯用的命令
cd /data/git/Webassembly-Lib/Demo/ // 進入到執行命令的目錄中
git pull
rm -f src/version.h
git rev-list HEAD | sort > config.git-hash
LOCALVER=`wc -l config.git-hash | awk '{print $1}'`
if [ $LOCALVER \> 1 ] ; then
VER=`git rev-list origin/master | sort | join config.git-hash - | wc -l | awk '{print $1}'`
if [ $VER != $LOCALVER ] ; then
VER="$VER+$(($LOCALVER-$VER))"
fi
if git status | grep -q "modified:" ; then
VER="${VER}M"
fi
VER="$VER $(git rev-list HEAD -n 1 | cut -c 1-7)"
GIT_VERSION=r$VER
else
GIT_VERSION=
VER="x"
fi
rm -f config.git-hash
cat version.h.template | sed "s/\$FULL_VERSION/$GIT_VERSION/g" > src/version.h
# 編譯和提交代碼
make
git add .
git commit -m 'Auto Compiled By handsomeTaoTao'
git push
複製代碼
目前這個demo還只是實現了比較簡單的功能,能夠進一步優化功能,例如在瀏覽器訪問該地址時顯示上一次編譯是否成功的信息,失敗的話則顯示錯誤信息,這樣子能夠方便調試。git
參考資料
stackoverflow: php-sudo-in-shell-exec
Gitee 配置文檔
Github、GitLab、Gitee使用Webhooks實現代碼自動部署 shell