はじめに
セーフィー株式会社の AI Vision グループでテックリードを務めます橋本貴博です。
私たちのチームでは、レビューの属人化や特定のメンバーへの負担の集中が課題となっていました。どのメンバーがレビューするかによって、そのやり方やフィードバックの質にバラつきが出ることも少なくなく、これがコードの品質に影響を及ぼしていました。
そのため、チーム全体でレビューを行うことで、コードの知識を全員で共有し、レビューのやり方や品質を標準化したいと考えていました。こうすることで、誰がレビューしても同じように高品質なコードが保たれるようになります。
さらに、Pull Request (PR) の数をKPIとして考え、それに基づいて実装を推進することも重要視しました。PRの数を定量的な指標にすることで、チームの成果を把握し、開発の効率化を図りたいと考えました。
そこで、GitHubのPRを解析して可視化するツールを開発し、オープンソースで公開することにしました。このツールを使うことで、PRの状況を簡単に把握できるだけでなく、レビューの分散や効率化にもつながると考えています。
本記事では、開発したツールの機能と活用、利用している GitHub REST API、ツールの使い方について示します。
機能
特定の期間において、指定されたメンバーが author、reviewer、もしくは requested review されているPRの数を集計します。結果を可視化して png 画像として出力します。出力される図は以下の通りです。
- 積み上げ縦棒グラフ
- ヒートマップ
- ネットワークグラフ
- ノードの大きさ: PR作成数とレビューした数の合計
- エッジの太さ: レビューした数と、レビューされた数の合計
- サンキーダイアグラム
以下では、2024年9月の1か月のPRを集計した結果を例として説明をします。
積み上げ縦棒グラフ
Author はPRを作成した数です。極端にPR数が少ない場合、実装に時間がかかっていたり、実装以外の業務の割合が多くなっているといった理由が考えられるので注意しています。
Review-requested は現時点でレビュー依頼されている数です。レビュー依頼が特定のメンバーに溜まっている場合は再割り当てが必要な可能性があるので注意しています。
Review-completed は、レビューが完了している数です。PRに対して1回以上のレビュー(comment, approve, request changes)を行った数から、完了していない場合を除くため、現時点でレビュー依頼されている数を除いています。私たちのチームでは特定のメンバーにレビューが片寄ることを防ぐため、可能であればレビュー数が少ないメンバーにレビュー依頼を行うことを推奨しています。
ヒートマップ
積み上げ縦棒グラフは、各メンバーがレビューした総数は分かりますが、レビュー依頼元の内訳を読み取ることはできません。そこで、依頼元と依頼先の関係を可視化するためにヒートマップを出力するようにしました。ヒートマップの縦軸は依頼元、横軸は依頼先を示しています。PR作成者によっては、依頼先が偏りレビュー属人化の傾向があることが読み取れると思います。
ネットワークグラフ
ネットワークグラフは、ヒートマップの情報をさらに直感的に分かりやすく可視化することができます。ノードの大きさは各メンバーのPR作成数とレビュー数の合計から、エッジの太さは2人のメンバーの間でレビューした数とレビューされた数の合計から決定しています。
ノードの位置は Spectral Layout を用いています。これにより結びつきが強いノードは近くに配置されます。したがって、コードやレビューの知識共有が近接するメンバーで密に行われており、逆に離れたメンバにはあまり共有が行われていないのではないかと仮説を立てることができます。
サンキーダイアグラム
サンキーダイアグラムは、ある量とその流れを可視化します。ここでは、レビュー依頼の量とその流れを見ることができます。下図において、左端の列はレビューの依頼元と依頼の量を、右端の列はレビューの依頼先と依頼された量を示しています。依頼元から依頼先への流れがグレーの帯で示されています。サンキーダイアグラムを用いると、直感的に誰から誰へどれくらいの量が分配されたのか把握できると思います。
GitHub REST API
ここでは、GitHub REST API を用いたPR情報の取得方法について説明します。このツールでは3種類のAPIを利用しています。
まず、REST API for search (Search API) を用いて集計に含めるPRのリストを取得しています。次に、個々のPRについて、REST API endpoints for pull request reviews (Reviews API)と、REST API endpoints for review requests (Review Requests API)を用いて、レビューのステータスとレビュー依頼のステータスを取得しています。
集計の高速化のため、過去に取得した時点から更新が無いリポジトリについてはキャッシュを利用しています。
Search API
Search API は、github.com/search と同様のクエリを用いてGitHub 内のオブジェクトを検索することができます。例えば、特定の期間、特定の組織で、特定のメンバが作成したPRを検索するには検索窓に以下のクエリを入力できます。
type:pr org:Safie author:member-a author:member-b author:member-c created:2024-09-01..2024-09-30
上記に対応して、REST API のURLは次のようになります。
https://api.github.com/search/issues?q=type:pr+org:Safie+author:member-a+author:member-b+author:member-c+created:2024-09-01..2024-09-30&sort=created&order=desc&per_page=100
Reviews API
レビューしたメンバーを確認するのに Reviews API を用います。リポジトリのオーナーを {owner}
、リポジトリの名前を {repo}
、PRの番号を {pull_number}
として、URLは以下になります。
https://api.github.com/repos/{owner}/{repo}/pulls/{pull_number}/reviews
Review Requests API
現時点でレビュー依頼されているメンバーを確認するのに、Review Requests API を用います。Reviews APIと同様に、リポジトリのオーナーを {owner}
、リポジトリの名前を {repo}
、PRの番号を {pull_number}
として、URLは以下になります。
https://api.github.com/repos/{owner}/{repo}/pulls/{pull_number}/requested_reviewers
使い方
config.py に GitHub token と集計したいメンバーのアカウント名を記載します。
github_token = "ghp_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" authors = [ "member-a", "member-b", "member-c", ]
以下のコマンドを実行します。
python analyze.py # 直近1か月の集計 python analyze.py --from_date 2024-09-01 --to_date 2024-09-30 # 期間の指定
詳細な使い方は、リポジトリの README.md をご覧ください。
ソースコード
こちら でソースコードを公開しています。ぜひ使ってみてください。
むすび
GitHub REST API を使ってPRを集計し、PRの属人化やチームの生産性の分析に利用する方法を紹介しました。もし同じような課題に直面しているチームがいれば、ぜひこのツールを活用してみてください。
セーフィーでは、新卒・中途を問わず、さまざまな職種の仲間を積極的に募集しています。詳細はセーフィー採用サイトをご覧ください。