Git hooks を使ってコミットのたびに go test してもらう
先に
ざっくり以下の手順でOKです。
1. Git hooks の参照先ディレクトリを変更する
git config --local core.hooksPath .githooks
pre-commit
を書く
2. #!/bin/sh
# Run go test
output=$(go test -v ./...)
exit_code=$?
# Check if the test failed
if [ $exit_code -ne 0 ]; then
echo "go test failed:"
echo "$output"
exit 1 # Return Error Code
fi
# Output succeeded
echo "$output"
exit 0
pre-commit
に実行権限を与える
3. chmod a+x ./.githooks/pre-commit
なにか書いてコミットしてみる
$ git add calc/num.go
vscode ➜ /workspace (main) $ git commit -m "multiplyを追加"
? go-unittest [no test files]
? go-unittest/calc [no test files]
[main 80d05b3] multiplyを追加
1 file changed, 5 insertions(+), 1 deletion(-)
$ git add calc/num_test.go
vscode ➜ /workspace (main) $ git commit -m "add num_test"
? go-unittest [no test files]
=== RUN TestAdd
--- PASS: TestAdd (0.00s)
PASS
ok go-unittest/calc (cached)
[main fbb1309] add num_test
1 file changed, 19 insertions(+)
create mode 100644 calc/num_test.go
git add calc/num_test.go
vscode ➜ /workspace (main) $ git commit -m "mod num_test"
go test failed:
? go-unittest [no test files]
=== RUN TestAdd
num_test.go:18:
Error Trace: /workspace/calc/num_test.go:18
Error: Not equal:
expected: 8
actual : 7
Test: TestAdd
--- FAIL: TestAdd (0.00s)
FAIL
FAIL go-unittest/calc 0.003s
FAIL
$ git status
On branch main
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
modified: calc/num_test.go
テストにfailするとcommit処理が止まるため、直後のgit statusでcommitされていないことがわかります。
説明
今回の手順のポイントを説明します。
.git/hooks
はgit管理できない
Git hooks の機能はデフォルトではそのリポジトリの.git/hooks
下を参照するようになっています。お手元にリポジトリがあるなら見ていただければと思いますが、hooks
以下にはサンプルとして各hookのサンプルコードが格納されているので、例えば./git/hooks/pre-commit.sample
を./git/hooks/pre-commit
とリネームし、中身をよしなに編集すればそのまま使うことができます。
しかしながら、.git
ディレクトリの内容はgit管理することができないため、このままでは実行したいスクリプトそのものをバージョン管理することができません。
そこでgit config --local core.hooksPath .githooks
というコマンドを使うと、そのリポジトリにおけるGit hooksの格納先を.githooks
に変更することができます。[1]
これにより、スクリプト本体もリポジトリに含めることができ、バージョン管理も行えるようになります。
終了コードで処理を切り分ける
go test
の結果は$output
、終了コードは特殊変数$?
に格納されます。$?
を検査してgo test
が成功したかどうかをチェックし、failしていたらexit 1
でスクリプトを終了するようにします。
Git hooksのpre-commit
は、終了コードが0
以外だった場合はコミット処理を中止する仕組みになっています。
作ったhooksには実行権限を与える
作成したスクリプトファイルはそのままでは実行権限がないので、事前に実行権限を与えておきます。これを行わないとGit hooksはスクリプトファイルを実行することができず、権限不足で実行できないことは特にcommit時にも出力されないようです。[2]
まとめ
以上です!
今回はGit hooksのpre-commit
を使って、コミットのたびにgo test
を実行させる環境を作ってみましたが、スクリプトの内容次第でさまざまなことが行えますので、他の言語や開発環境にも応用できそうです。
ではまた!
おまけ
VSCodeのCommitボタンでもちゃんと発動します。
「Open Git Log」や「Show Command Output」を押すと結果を確認することができます。
おまけ2
pre-commit
をスルーしたい場合には--no-verify
オプションをつけてcommitしましょう。乱用は禁物です。
git commit -m "testしないでいったんコミット" --no-verify
Discussion