🔎

GitHub APIを使ってコードレビューの偏りを簡易的に可視化する

2024/08/26に公開

概要

所属するチームのKPTで「コードレビューでレビュアーとレビュイーに偏りがある気がする」という意見が出たことがありました。
実際のところ、これは感覚によるものなのか、ファクトなのかどうか
Pull Requestは作成された時刻やAPPROVEされた時刻などをメタデータとして保持しており、GitHub APIを使って取得可能です。
そこでPull Requestの「Author」と「Approveした人」の行列を作成して、コードレビュー状況を可視化することにしました。

やり方

GitHub API

https://docs.github.com/ja/github-cli/github-cli/about-github-cli

今回はコマンドラインツールである gh を使い以下のフィールドを取得します。
最低限必要なのは最初の3つですが、APPROVEまでのリードタイム計測にも使えるよう日次も取得しています。

  1. author
  2. reviews
  3. title
  4. createdAt
  5. mergedAt

直近5件のマージ済みPull Requestに対してのメタデータ取得するには以下を実行します。

gh pr list -s "merged" -L 5 --json 'author,createdAt,mergedAt,reviews,title'

これを実行すると以下のようなjsonが返ってくるので、次のSTEPで必要なフィールドをparseします。
また reviews (レビューコメント)には複数の値が返ってくるのでflattenします。

[
    {
      "author":{
         "id":"...",
         "is_bot":false,
         "login":"user_a",
         "name":"User A"
      },
      "createdAt":"2024-08-20T08:43:52Z",
      "mergedAt":"2024-08-21T08:30:20Z",
      "reviews":[
         {
            "id":"...",
            "author":{
               "login":"user_a"
            },
            "authorAssociation":"CONTRIBUTOR",
            "body":"",
            "submittedAt":"2024-08-20T08:47:09Z",
            "includesCreatedEdit":false,
            "reactionGroups":[

            ],
            "state":"COMMENTED",
            "commit":{
               "oid":"..."
            }
         },
         ...
         {
            "id":"...",
            "author":{
               "login":"user_b"
            },
            "authorAssociation":"CONTRIBUTOR",
            "body":"LGTM",
            "submittedAt":"2024-08-20T13:27:12Z",
            "includesCreatedEdit":false,
            "reactionGroups":[

            ],
            "state":"APPROVED",
            "commit":{
               "oid":"..."
            }
         }
      ],
      "title":"Sample Pull Request"
   }
   ...
]

jqでパーズ

続いてjqで必要なフィールドをパーズします。
先程の review フィールドではAPPROVEされたPRののみをフィルターし、GitHubのUser NameとsubmittedAtに分解します。
クエリが長いので filter.jq などのファイルにしておくと便利です。

[
    .[] | {
        author: .author.login,
        approved_by: .reviews[]
            | select(.state == "APPROVED")
            | { login: .author.login, submittedAt: .submittedAt },
        created_at: .createdAt,
        merged_at: .mergedAt,
        title: .title
    }
]

最終的にTSV(あるいは任意の形式)で出力するため、以下を実行します。

gh pr list -s "merged" -L 100 --json 'author,createdAt,mergedAt,reviews,title' | jq -f filter.jq | jq '.[] | [.title, .author, .created_at, .approved_by.login, .approved_by.submittedAt, .merged_at]|@tsv'

結果はTSVファイルでも良いですし、集計が楽なGoogle SpreadsheetやExcelなどに貼り付けてもいいでしょう。

集計

Google Spreadsheetを使う場合は

  1. データの整形(列の分割+ヘッダー行の追加)
  2. ピボットテーブルによる集計

を行います

まずデータを整形して以下のようなテーブルを作成します

.title .author .created_at .approved_by.login .approved_by.submittedAt .merged_at
Lorem Ipsum user_A 2024-08-23T10:03:55Z user_C 2024-08-23T10:05:37Z 2024-08-23T10:21:18Z
is simply dummy user_A 2024-08-23T10:03:53Z user_B 2024-08-23T10:05:19Z 2024-08-23T10:21:18Z
text of the printing user_C 2024-08-20T11:03:10Z user_A 2024-08-23T09:37:20Z 2024-08-23T09:39:53Z
and typesetting industry. user_B 2024-08-20T08:43:52Z user_C 2024-08-20T13:27:12Z 2024-08-21T08:30:20Z
...

これにピボットテーブルを適用して

  • 行: reviewee (.author)
  • 列: reviewer (.approved_by.login)
  • 値: COUNT(title)

で行列を作成します

結果

作成した行列がこちら。
メンバー user_c はレビューのみを行っているので author 側にはいません。

result

ボットが作成したPRについても可視化することができました。
こうすると user_b のPRを user_auser_d が多くAPPROVEしていることが分かります。
そもそもPRを出す数が user_b が多いので、全体としてはある程度均一にレビューされているものの「なんとなくレビューばかりしている」といった感覚になってしまうこともあるのかもしれません。

なお今回は使用しませんでしたが、createdAtmergedAt も出しているので、マージまでのリードタイムも計測可能です。
これにより「PRのレビューが遅い」といった状況もある程度可視化可能なように思います。

また私のチームは複数のリポジトリを開発・運用しているので、それぞれのリポジトリにおいて異なる傾向が出ており、技術可用性やトラックナンバー問題を可視化するのにも役に立ちました。

まとめ

チーム開発においては、どうしてもこういった感覚的な課題感は一定発生してしまいますが、GitHubには開発のうえでの様々な記録がデータとして集約されています。
専用のBIツールを使うことで可視化することもできますが、カンタンな統計値程度であればAPIを叩いて見ることができるのでぜひ皆さんも試してみて下さい。

Discussion