Webサイトをgithubで管理してpush時に自動的に同期する方法
Webサーバに Subversion のサーバを立てておき、HTML や CSS を commit することでWebサイトを更新する方法は、良く知られているテクニック、らしいですね*1。更新の履歴を残すことができるし、ましてチマチマとFTPやsftpでアップロードするよりずっと簡単です。
しかし SVN の代わりに git を使おうとすると、pushしてもリポートリポジトリではファイルを更新してくれません。
また、リポジトリはWebサーバ上に作るよりも、便利な管理インタフェースがある github(や噂のgitosis)に置いておきたいところです。
そこで、github の Post-Receive Hook を使うと、リポジトリに変更を push すると同時に、Webサーバにも同期させることができます*2。
Webサーバに同期する前に、Sphinxでドキュメントを整形したり、SassをCSSに変換したり、あるいはJavaのソースからJavaDocを生成したりと、色々な前処理を走らせることもできます。
流れは下図のようになります。Post-Recieve Hook を設定しておくと、リポジトリに変更が push されたときに指定しておいたURLに POST リクエストを送信してくれます。この POST リクエストを受け取ったタイミングで github から変更を pull し、色々な前処理を実行した後に、Webサーバにアップロードすれば完了です。
実際に、msgpack.org ではこの方法を使ってWebサイトを管理しています。
サーバスクリプト
まず、github から Post-Recive Hookを受け取って、同期スクリプトを起動する簡単なWebサーバを用意します。
POSTされるデータには、payload というパラメータ名でJSON形式のデータが含まれています。
Ruby の Sinatra を使って書くと↓こうなります。
#!/usr/bin/env ruby require 'sinatra' require 'json' here = File.dirname(__FILE__) SYNC_SCRIPT = "#{here}/update-website.sh" post '/' do begin push = JSON.parse(params[:payload]) system(SYNC_SCRIPT) "ok." rescue "error." end end
同期スクリプト
次に、githubから変更をpullしてWebサーバに同期するスクリプトを用意します。
同期する方法は、同期先のWebサーバで使える方法を選択してください。ここでは ssh + rsync を使ってみます:
- update-website.sh
#!/bin/sh tmpdir=/home/viver/gitsync/work/msgpack-website repo=git://github.com/msgpack/website.git rsyncto=viver@example.com:htdocs/ rsync='rsync -e "ssh -i ~/.ssh/id_rsa_nopass" -vrtl --delete' if [ -d "$tmpdir" ];then cd "$tmpdir" if git pull; then $rsync ./ "$rsyncto" exit 0 fi fi dirname=`dirname "$tmpdir"` basename=`basename "$tmpdir"` mkdir -p "$dirname" cd "$dirname" rm -rf "$basename" if git clone "$repo" "$basename"; then cd "$basename" $rsync ./ "$rsyncto" fi
githubの設定
最後に、githubで Post-Receive Hook を発行するURLを設定します。
リポジトリのトップページで [スパナアイコン] Admin ボタンをクリックし、サイドバーから Service Hook を選んで、Post-Receive URLs にサーバスクリプトへのURLを入力してください。
Service Hookの用途
Webサイトにコンテンツを同期する代わりに、push時にテストケースを走らせたり、新しいtagが作成されたタイミングでリリースビルドを作成するなど、発想次第で色々なことができそうです。
面倒な作業はどんどん自動化してみてください^^;