一、Webhook 介紹與作用簡介
Webhook,顧名思義就是鉤子,簡而言之,可以在特定情況下觸發特定的操作。例如在遠端git倉庫中進行了push、tag等操作時,自動在遠端server端自動拉取、編譯程式碼。
以下是一個push程式碼到遠端倉庫後,自動拉取程式碼進行編譯後,將生成的Webassembly相關的檔案(.js,.wasm)和版本號push到遠端倉庫中的demo。
二、demo實現
1. 倉庫設定(以gitee為例)
首先,需要擁有專案的管理者許可權,點選專案首頁上方的管理,然後點選左側選單下方的WebHooks,進入到以下截圖的設定頁面。
]
在上面的的介面中,我已經新增了一個Webhook,觸發型別為push,同時還有一個密碼。
當你push程式碼到遠端倉庫時,會往這裡設定的URL傳送一個攜帶著設定好密碼的POST請求。當然你也可以勾選其他的操作型別。
2. PHP程式碼實現
- hooks.php
<?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可以執行系統命令。
*
* 2、PHP一般使用www-data或者nginx使用者執行,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.`
*
*/
// 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()));
複製程式碼
- autoCompiled.sh
#!/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還只是實現了比較簡單的功能,可以進一步優化功能,例如在瀏覽器訪問該地址時顯示上一次編譯是否成功的資訊,失敗的話則顯示錯誤資訊,這樣子可以方便除錯。
參考資料
stackoverflow: php-sudo-in-shell-exec
Gitee 配置文件
Github、GitLab、Gitee使用Webhooks實現程式碼自動部署