継続的インテグレーションの 3 つの Git フック

Discover how Git hooks enforce clean builds on feature branches and more.

Sarah Goff-Dupont Sarah Goff-Dupont

If you've used Git for a while, you've probably heard of Git hooks. Maybe you've even played around with them a bit. Git hooks are awesome in the context of continuous integration, so in this article I'll dive into three use cases and point you to ready-made hooks you can add to your workflow. If you're new to Git hooks, no worries: we'll start with the basics.

Understanding Git hooks

Hooks are Git's native mechanism for triggering custom scripts before or after operations like commit and merge. Think of them as Git’s plugin system. If you look in the .git directory of any Git repository you’ll see a directory named “hooks” which contains a set of example hook scripts. 

.git/hooks

Installing Git hooks is straightforward and well-documented, so I won't get into that here.

There are two broad classes of hooks: client-side and server-side. Client-side hooks run on your local workstation, while server-side hooks run on your Git server.

フックは pre- と post- フックにも分類できます。Pre-receive フックは特定の Git 操作の前に呼び出され、必要に応じてオプションで操作をキャンセルすることができます。このフックは、自分やチームメイトが誤ったコードをコミットしないようにリポジトリを外部から守る機能があります。Post-receive フックは操作が完了してから実行されるため、操作をキャンセルするオプションはありません。代わりに、post-receive フックは開発ワークフローの一部を自動化します。

Using #Git hooks is like having little robot minions to carry out your every wish (muwa-ha-haaaa!).

Git フックは次のような操作を自動化します。

  • verifying that you included the associated JIRA issue key in your commit message
  • enforcing preconditions for merging
  • チームのチャットルームに通知を送信する
  • 別のブランチに切り替えた後、ワークスペースを設定する

フィーチャーブランチでクリーンビルドを実行する

Server-side pre-receive hooks are an especially powerful compliment to continuous integration because they can prevent developers from pushing code to master, unless the code meets certain conditions – like elite ninja guardians, protecting it from bad code.

Developers are generally conscientious enough not to merge to master when there are broken tests on their branch. But sometimes we forget to check. Or when we’re sharing a branch with other people, sometimes more changes get made since we last checked the branch build… stuff happens.

So you can add a server-side hook that looks for incoming merges to master. When it finds one, the script checks the latest build on your branch, and if there are any failing tests, the merge is rejected. My colleague and Atlassian developer advocate Tim Petterson wrote a hook script for this, designed to work with Bamboo, and made it available on Bitbucket. You can grab it, customize it, and add it to your repo.

苦労して得たコードカバレッジを保護する

Something I’ve seen lots of teams struggle with is maintaining code coverage. Often times they’ve had to retroactively cover their code base with tests, and it’s really frustrating to see that hard-earned coverage slip away as more features get added without tests shoring them up. So Tim also wrote a pre-receive server-side hook to protect master from declining code coverage.

This hook also looks for incoming merges to master. It then calls out to the continuous integration server to check current code coverage on master, and coverage on the branch. If the branch has inferior coverage, the merge is rejected.

Most continuous integration servers don't expose code coverage data through their remote APIs, so the script pulls down the code coverage report. To do this, the build must be configured to publish the report as a shared artifact, both on master and on the branch build. Once published, you can grab the latest coverage report from master by calling the continuous integration server. For branch coverage, you fetch the coverage report either from the latest build, or for builds related to the commit being merged.

And just to be clear, this all assumes you already have code coverage running. The hook doesn’t magically do that – it just looks for the coverage data in your build results. This one also works with Bamboo by default, as well as Clover (Atlassian's code coverage tool for Java and Groovy). But it can be customized to integrate with any build server or code coverage tool.

Checking the status of branch builds

Because friends don't let friends check out broken branches.

Here's a chance to play with client-side Git hooks: a post-checkout hook script that exposes branch build status right inside your terminal window, also from Tim. The script gets the branch's head revision number from your local copy, then queries the continuous integration server to see whether that revision has been built – and if so, whether the build succeeded.

master からブランチを作成するとします。このフックは master の HEAD コミットが正常にビルドされたかを確認し、このコミットからフィーチャーブランチを作成しても「安全」かどうかを知らせます。または、あるリビジョンのビルドが失敗したことをフックが示しているにもかかわらず、チームのウォールボードでは緑色のビルドが表示されている (またはその逆) とします。これは、ローカルコピーが最新ではないことを示しています。最新版をプルするか、現在のローカルコピーで作業を続けるかはユーザーの自由です。

このフックを使用することで、アトラシアン開発者を悩ませていた無数の頭痛の種が取り除かれました。上述したサーバーサイドのフックの採用についてチームを説得できなかった場合は、少なくともローカルワークステーションでこちらのクライアントサイドのフックをインストールしてください。決して後悔しないでしょう。

こちらの記事で紹介した、継続的インテグレーションのすべての Git フックは、初期設定では Bamboo、Clover、Bitbucket で機能します。ただし、Git フックはベンダーに依存しないため、カスタマイズすればお手持ちのどのようなツールスタックとも使用できます。自動化で成功を勝ち取りましょう!