この記事は GMOアドマーケティング Advent Calendar 2023 5日目の記事です。
皆さん、お久しぶりです。GMOアドマーケティングのGood!Apps開発担当のharuです。
最近、弊社の開発部ではFour Keysを導入し、開発者体験や生産性の向上に注力しています。今回は、Four Keysの計測に必要な処理の一部を自動化しましたので、その詳細についてお話しできればと思います。
Four Keysとは
まず、Four Keysについて簡単に説明します。
Four Keysは、GoogleのDevOps Research and Assessmentチームが提唱した、ソフトウェア開発チームのパフォーマンスを評価するためのフレームワークです。このフレームワークは以下の4つの指標で構成されています。
- デプロイの頻度: 本番環境へのリリースの頻度を示します。頻繁なリリースは、アジャイルな開発プロセスを反映し、迅速な変更への対応を示します。
- 変更のリードタイム: コミットから本番環境での稼働までの所要時間を示します。短いリードタイムは、開発プロセスの効率性を示し、素早いリリースを可能にします。
- 変更障害率: デプロイによって引き起こされた本番環境の障害の割合を示します。低い変更障害率は、安定性を高めることを示します。
- サービス復元時間: 本番環境での障害からの回復にかかる時間を示します。短い復元時間は、障害への対応の迅速さを示し、サービスの可用性を高めます。
これらの指標を用いて、個人やチームのDevOpsレベルを可視化し、生産性の向上を目指します。Four Keysは、DevOpsの評価において広く一般的なフレームワークであるため、他社との比較も可能です。
今回はFour Keysが主題ではないため、この程度に留めておきます。
自動化の経緯
さて、前述したFour Keysのいくつかの指標を算出するためには、エンジニアがタスクに着手した時刻(開始時刻)の情報が必要です。弊社の開発部では、これをGitの新規ローカルブランチを作成した時点としています。この情報をGitで記録することで、リモートpush時などに自動的に取得して集計できます。
ただし、Gitではブランチの作成時刻が自動的に記録されないので、ブランチ作成(checkout)後すぐに空コミット(コミットメッセージなしのコミット)を行い、「First Commit = 開始時刻」として記録する必要があります。
私はこの空コミットをよく忘れてしまうので、新規ローカルブランチ作成後の空コミットを自動化してみることにしました。
Git Hooksを使用した自動化
Gitには、commitやcheckoutなどのアクションの前後に処理(スクリプト)を呼び出す(フックする)ことができる標準機能、Git Hooksがあります。今回は、この中のpost-checkoutフックを使用して自動化を行いました。post-checkoutフックは、git checkout後に呼び出されます。
以下が、使用したシェルスクリプトのコードです。フックはさまざまな言語で記述できますが、今回はシェルスクリプトを使用しました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
#!/bin/sh # post-checkout hooksが受け取るパラメータ ## $1: checkout前のHEADのref, $2: checkout後のHEADのref, $3: checkoutの種類(ブランチのチェックアウトなら1, ファイルのチェックアウトなら0) before_head=$1 after_head=$2 checkout_type=$3 # post-checkoutフックのトリガーとなったgitコマンドを取得 git_command=$(ps -ocommand= -p $PPID) # 次の3点で新規ブランチのチェックアウトかどうかを判断する ## 1. gitコマンドがbオプション付きか(git switchを使用している場合はcに変更してください) ## 2. checkout前のHEADのrefが同じか ## 3. ブランチのチェックアウトか if [[ $git_command =~ ([[:space:]]\-b[[:space:]]) ]] && [ $before_head == $after_head ] && [ $checkout_type == 1 ]; then # 新規ブランチ名を取得 new_branch_name=$(git rev-parse --abbrev-ref HEAD) # 新規ブランチ名をコミットメッセージにして空コミットを作成 eval "git commit --allow-empty -m \"$new_branch_name\"" exit 1 fi exit 0 |
post-checkoutフックは、git checkoutコマンド全てをトリガーとするため、新規ブランチ作成時以外にも実行されてしまいます。そのため、新規ブランチ作成時のみ空コミットを作成するように、条件分岐を行っています。
注:上記スクリプトは、git checkout -bで新規ブランチの作成を行うことを前提としています。git branch&git checkoutで新規ブランチの作成を行う場合は、異なる条件分岐が必要です。
特定のローカルリポジトリに作成したフックを適用する
以下の手順で、フックを適用します。
- 上記スクリプトをpost-checkoutというファイル名でローカルリポジトリの.git/hooksディレクトリに配置
- post-checkoutファイルに実行権限を付与
- chmod a+x {post-checkoutのパス}
これにより、新規ブランチ作成時に自動的に空コミットが作成されます。
全てのローカルリポジトリに作成したフックを適用する
上述の方法では、ローカルリポジトリを作成する都度post-checkoutファイルをコピーして、フックを適用する必要があります。空コミットを忘れる私は、間違いなくこの作業も忘れるので、フックを全てのローカルリポジトリ(今後新規に作成するものも含めて)に適用する、つまりグローバルフックを設定することにしました。
具体的な手順は以下の通りです。
- グローバルフックディレクトリを作成(以下は~/.config/git/hooksとした例)
- mkdir -p ~/.config/git/hooks
- 上記スクリプトをpost-checkoutというファイル名で、1で作成したディレクトリに配置
- post-checkoutファイルに実行権限を付与
- chmod a+x {post-checkoutのパス}
- グローバルGit configでcore.hooksPathを指定(.gitconfigファイルのパスはMacの場合)
- vi ~/.gitconfig
- [core] hooksPath = ~/.config/git/hooks
これにより、Gitが参照するフックディレクトリがデフォルトの$GIT_DIR/hooksから変更され、全てのローカルリポジトリに作成したフックが適用されます。
注:上記と併せてローカルフックも使用したい場合は、グローバルフックのコード内からローカルフックを呼び出すことで実現できます。今回は、ローカルフックを使用しないため、その実装は割愛します。
さいごに
これで、今後はFirst Commitのことは気にせずに開発できるようになりました。みなさんもよかったら試してみてください。それではよいFour Keysライフを!
明日はH.Tさんによる「Four Keys導入で感じた良かった事と課題」です。
引き続き、GMOアドマーケティング Advent Calendar 2023 をお楽しみください!
■採用ページはこちら!
■GMOアドパートナーズ 公式noteはこちら!