GitHubのWebhookを使い、git pushしたら自動でdeployする仕組みを作る
GitHubのWebhook機能を利用して、 git pushしたら自動でdeployする仕組みを作る方法についてメモをまとめます。
仕組みの全体像
このエントリでは以下のような仕組みを作ることにします。
deployサーバは、大きく以下の2つのモジュールで構成します。
- Webhookの受け付けイベント管理ファイルをtouchするWebサーバ
- 定期的にイベント管理ファイルを確認しdeployを実行するスクリプト
仕組みを作る手順
Webサーバの構築
deployサーバに、apache/phpがインストールされている前提で、 以下のようなphpスクリプトを配置します。
イベント管理ファイルを配置するディレクトリを作成し、 apacheの実行ユーザに書き込み権限を与えておきます。 (以下の例では「/home/deploy/webhook/event/」ディレクトリ)
SECRET_KEYには、パスワードツールなどで生成した文字列を指定しておきます。
/var/www/html/github_webhook.php
<?php
$SECRET_KEY = '<ここに鍵>';
if (! isset($_SERVER['HTTP_X_HUB_SIGNATURE'])) die();
if (! $_SERVER['HTTP_X_HUB_SIGNATURE'] === sha1($SECRET_KEY)) die();
$json_string = file_get_contents('php://input');
$payload = json_decode($json_string, true);
if (! $payload['ref']) die();
if ($payload['repository']['full_name'] === '<ユーザ>/<リポジトリ>' && $payload['ref'] === 'refs/heads/deploy/staging') {
touch('/home/deploy/webhook/event/hookfile');
}
?>
ok
GitHubのリポジトリ画面から、以下のようにたどってWebhookの管理画面を表示します。
GitHubのリポジトリ → Setting → Webhooks & services
「Add Webhook」を選び、「Payload URL」と「Secret」を指定して設定を追加します。
PayloadURLは先ほどのphpのURL、SecretはSECRET_KEYに設定した文字列です。
ここまでの手順を終えた後、githubの「deploy/staging」ブランチにpushすると、deployイベントファイル「/home/deploy/webhook/event/hookfile」が作られることを確認します。
うまくファイルが出来ない場合は、 GitHubのWebhooks&service画面に出てくる「Recent Deliveries」に表示されるリクエストの結果を見ながら、原因を調べます。
deployスクリプトの構築
deployサーバに、以下のようなスクリプトを配置します。
/home/deploy/webhook/deploy.sh
#!/bin/sh
WORK_PATH=/home/deploy/webhook
# 二重起動制御
touch $WORK_PATH/deploy.$$
ln -s $WORK_PATH/deploy.$$ $WORK_PATH/deploy > /dev/null 2>&1
if [ $? == "1" ]; then
rm $WORK_PATH/deploy.$$
exit 0
fi
# hookファイルのチェック
if [ ! -f $WORK_PATH/event/hookfile ]; then
rm $WORK_PATH/deploy $WORK_PATH/deploy.$$
exit 0
fi
# deploy開始slack通知
curl -X POST --data-urlencode 'payload={"text": "staging環境 デプロイ いきます!", "username": "deploy-user", "icon_url": "<アイコンのURL>"}' https://hooks.slack.com/services/<slackのwebhookのurl>
# deployの実行
<ここにdeploy手続きを記載>
# deploy開始slack通知
curl -X POST --data-urlencode 'payload={"text": "staging環境 デプロイ しました!", "username": "deploy-user", "icon_url": "<アイコンのURL>"}' https://hooks.slack.com/services/<slackのwebhookのurl>
# hookファイルの削除
rm $WORK_PATH/event/hookfile
# LOCKファイル削除
rm $WORK_PATH/deploy $WORK_PATH/deploy.$$
shell scriptに実行権を与えたら、以下のようにcrontabに設定します。
crontab -e
* * * * * /home/deploy/webhook/deploy.sh
ここまでの手順を終えた後、もう一度githubの「deploy/staging」ブランチにpushすると、デプロイ手続きが実行され、slackに通知が送られます。
次のような感じで。
後は使いやすいように。deployの成功/失敗でslackのメッセージを変えるとか、deploy時のログをメールで送るとか、shellscriptを変更したりなどすれば良いかと思います。