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するだけで自動でテストやデプロイまでやってくれるようになりました
静的サイトとか小規模なプロジェクトならこれだけでも十分な気がします