git hookを使って更新ファイルの内容次第でpush前にテストやデプロイを行うようにします
middlemanで作成したプロジェクトで、静的サイト用のファイルがpushされようとしているときにhookを使ってデプロイ作業も行ってしまおうというものです
実際に行うプロジェクトではrubyのスクリプトもあるのでそちらはlib以下の更新ファイルが合った場合はhookでテストを実行するというような感じにしました
まぁ小規模なプロジェクトならこれで良いんじゃない?というような内容かなと思います
git hooks
.git/hoooks に実行可能なファイルを適切な名前で置くことで読み取ってくれる
クライアント側で動作するクライアントサイドフック、リポジトリ側で行うサーバサイドフックがある
今回はrubyの実行環境を前提としたコマンドを用いたいためクライアントサイドフックを用います
いくつか探してみたところ、pre-pushが今回の要件に合いそうでした
rubyスクリプトと、middlemanで作ったサイトを例にやってみます
スクリプト
Gitのフックの説明と挙動の検証 を参考にどんな値が標準入力で渡されるのか確認したところ
pushする対象のCommitIDが入力されるようなのでそれを使って下記のように実装しました
- .git/hooks/pre-push
#!/bin/bash
publish_files=("data/" "source")
lib_file_prefix=("lib" "darts.rb" "helpers" "spec")
echo_line() {
echo "${0##*/} ********************************************"
}
publish() {
echo "rake publish --------------------"
rake publish
}
spec() {
echo "rspec spec/* --------------------"
rspec spec/*
[ "$?" -ne 0 ] && echo "Test Failed!!" && echo_line && exit 1
}
is_commited() {
start_id=$1
end_id=$2
filenames=(${@:3})
for filename in "${filenames[@]}"
do
count=$( git log --name-only ${start_id}..${end_id} | grep -c ${filename} )
echo "${filename} : ${count}" 1>&2
[ "${count}" -gt 0 ] && echo 1 && return
done
echo 0
}
echo_line
while read local_ref local_sha remote_ref remote_sha; do
echo $local_ref
echo $local_sha
echo $remote_ref
echo $remote_sha
# master へのpushのみ適用
if [ "$local_ref" == "refs/heads/master" ] && [ "$remote_ref" == "refs/heads/master" ]; then
if [ -n "${remote_sha}" ] && [ -n "${local_sha}" ]; then
# lib 以下に更新があるか(テスト実行対象か)
commited_lib=$( is_commited ${remote_sha} ${local_sha} ${lib_file_prefix[@]} )
echo "lib commited: ${commited_lib}"
[ "${commited_lib}" == 1 ] && spec
# source以下に更新があるか(midleman deployの対象か)
commited_publish=$( is_commited ${remote_sha} ${local_sha} ${publish_files[@]} )
echo "source commited: ${commited_publish}"
[ "${commited_publish}" == 1 ] && publish
fi
fi
echo_line
done
exit 0
最終的にできるようになったのは下記
lib以下に更新があった場合
- テストを走らせる(rspec)
- 失敗したらpush拒否
source以下に更新があった場合
- gh-pagesにpush(middlemanのdeploy)
まとめ
これでpushするだけで自動でテストやデプロイまでやってくれるようになりました
静的サイトとか小規模なプロジェクトならこれだけでも十分な気がします