GitHubのwebhook機能を使うと、Pushされた時に自動でサーバーに通知を送ることができます。
その通知を処理して、自動でgit pullを実行し、サーバー上のレポジトリを最新に保つスクリプトを書きました。
webhookの設定は、GitHubのレポジトリの「Settings」→「Webhooks & services」→「Add webhook」から行ってください。
以下のスクリプトをサーバー上に設置し、「Payload URL」にスクリプトのアドレスを指定してください。
PHPの場合
<?php
// 設定
$LOG_FILE = dirname(__FILE__).'/hook.log';
$SECRET_KEY = 'your key';
$header = getallheaders();
$hmac = hash_hmac('sha1', $HTTP_RAW_POST_DATA, $SECRET_KEY);
if ( isset($header['X-Hub-Signature']) && $header['X-Hub-Signature'] === 'sha1='.$hmac ) {
$payload = json_decode($HTTP_RAW_POST_DATA, true); // 受け取ったJSONデータ
// ここに実行したいコードを書く
exec('git pull 2>&1');
file_put_contents($LOG_FILE, date("[Y-m-d H:i:s]")." ".$_SERVER['REMOTE_ADDR']." git pulled: ".$payload['after']." ".$payload['commits'][0]['message']."\n", FILE_APPEND|LOCK_EX);
} else {
// 認証失敗
file_put_contents($LOG_FILE, date("[Y-m-d H:i:s]")." invalid access: ".$_SERVER['REMOTE_ADDR']."\n", FILE_APPEND|LOCK_EX);
}
hash_hmac()を使ってハッシュ値をつくり、X-Hub-Signatureヘッダーと一致するか調べます。
一致しなければ、正しくGithubから送られてきたものでないので何もせず終了します。
$SECRET_KEYには、githubに設定したキーをそのまま設定してください。
Rubyの場合
#!/usr/bin/env ruby
# coding: utf-8
# 設定
LOG_FILE = 'hook.log'
SECRET_KEY = 'your key'
require 'openssl'
require 'json'
require 'logger'
log = Logger.new(LOG_FILE)
body = STDIN.read # 生のPOSTデータの受け取り
HMAC_DIGEST = OpenSSL::Digest.new('sha1')
hmac_signature = 'sha1='+OpenSSL::HMAC.hexdigest(HMAC_DIGEST, SECRET_KEY, body)
if ENV["HTTP_X_HUB_SIGNATURE"] == hmac_signature
payload = JSON.parse( body )
# ここに実行したいコードを書く
system('git pull')
log.info "#{ENV['REMOTE_ADDR']} git pulled: #{payload['after']} #{payload['commits'][0]['message']}"
else
# 認証失敗
log.warn "invalid access from #{ENV['REMOTE_ADDR']}"
end
puts "Content-Type: text/html\n\n"
やっていることは、PHPの場合と同じです。
参考
https://developer.github.com/v3/repos/hooks/#create-a-hook
http://blog.manaten.net/entry/573 (情報が古いです)