こんにちは。Photoraitエンジニアのヒエイです。
全社エンジニアが参加する開発定例「クリトラ定例」の運営をしています。
「クリトラ」ってなに?についてはこちらをご覧ください。
四半期末の定例では振り返り会を実施しており、エンジニアの頑張りや活動量を発表しました。
この活動量について
- プロジェクト毎のリリース数
- プルリクエスト(以下、PR)・マージリクエスト(以下、MR)数やコメント数
これらの数値をグラフ化し、前回振り返り時とも比較しつつエンジニア自身の活動量が数値化された発表を見て
みんなでわちゃわちゃ盛り上がる会となりました。
今回はこの、「PR・MR数やコメント数」を集計した話を書きます。
どんな発表をしたか
集計したデータをグラフ化し、以下を発表しました。
月毎のPR・MR数やメンバー毎のPR・MR数

メンバーのレビューコメント数

レビューに対する平均コメント数

集計対象と集計内容
ウエディングパークでは、GitHubとGitLabを活用しています。何故二種類あるのかはここでは説明を省きます。
GitHubとGitLab双方から以下を集計させます。
PR・MR数
メンバー毎のPR・MR提出数を出します。
この集計により、月毎やプロジェクト毎のコードレビュー依頼数も見えてきます。
PR・MRに対する開発メンバーのコメント数
先述の通りPR・MRに対するコメント数を集計します。
つまり、コードレビューに対してどれぐらいコメントをしたかを出します。
PR・MRへのレビューアサイン数
PR・MRにアサインされた数を集計します。
コードレビューにアサインされた数を出します。
APIエンドポイント
GitHub API、GitLab APIの以下のエンドポイントを利用します。
エンドポイント
GitHub
GraphQLを使います。
https://api.github.com/graphql
https://docs.github.com/ja/graphql/reference/queries
GitLab
弊社のGraphQL APIのバージョン都合上 REST APIを利用します。
https://docs.gitlab.com/ee/api/merge_requests.html#list-merge-requests
https://docs.gitlab.com/ee/api/discussions.html#merge-requests
GitHub集計
Organizationに紐づくリポジトリからPR一覧、PR作成者、レビューアサインメンバー、コメント一覧を取得します。
{
organization(login: "Organization名") {
repositories(first: 100) {
edges {
node {
name
pullRequests(first: 10, after: null, orderBy: {field: CREATED_AT, direction: DESC}) {
pageInfo {
endCursor
}
edges {
node {
createdAt
author {
login
}
assignees(first: 10) {
edges {
node {
login
}
}
}
comments(first: 100) {
edges {
node {
author {
login
}
body
}
}
}
}
}
}
}
}
}
}
}
GraphQLなのでまとめて取得できるのが便利です。集計自体はスクリプト側に任せます。
PR数やコメント数も制限をかけてリクエストしているので、良しなにページネーションさせて細かくリクエストさせます。
GitLab集計
こちらはREST APIを利用だったので、スクリプト織り交ぜて載せます。PHPで取得。
$date = '2022-04-01T00:00:00+09:00';
$url = "https://{GitLabドメイン}/api/v4/merge_requests?created_after=%s&per_page=100&scope=all&page=%s";
// 日付に制限をかけて取得させる
$mrUrl = sprintf($url, $date);
$headers = [
"Authorization: Bearer {トークン値}",
];
page = 1;
// apiリクエストをする例
while ($mrList = $this->request($mrUrl, $page)) {
foreach ($mrList as $mrValue) {
$authorName = $mrValue['author']['username'];
// author(MR作成者)ごとのMR数をインクリメントさせる例
$this->incrementAuthor($authorName);
if (!empty($mrValue['assignee'])) {
$assigneeName = $mrValue['assignee']['username'];
// assignee(レビュー者)ごとのMR数(レビュー依頼数)をインクリメントさせる例
$this->incrementAssignee($assigneeName);
}
$mr = [
'prjId' => $mrValue['project_id'],
'mrIid' => $mrValue['iid'],
'authorId' => $mrValue['author']['id'],
];
// この部分は以下で解説
$this->sumComment($mr);
}
$page ++;
}
コメント部分は別で取得しなければならず、ソース上の`$this->sumComment($mr)`部分の取得は以下のような形です。
private function sumComment($mr)
{
$mrDiscussionUrl = "https://{GitLabドメイン}/api/v4/projects/%s/merge_requests/%s/discussions?per_page=100";
$path = sprintf($mrDiscussionUrl, $mr['prjId'], $mr['mrIid']);
$page = 1;
// apiリクエストをする例
while ($discussions = $this->requestPath($path, $page)) {
foreach ($discussions as $comments) {
foreach ($comments['notes'] as $note) {
// システム(CIによる投稿など)による内容ならスルー
if ($note['system']) {
continue;
}
// 投稿者がMR作成者ならばスルー(レビュー依頼者によるコメントは除きました)
if ($note['author']['id'] == $mr['authorId']) {
continue;
}
$authorName = $note['author']['username'];
// レビューコメントした人ごとのコメント数をインクリメントさせる例
$this->incrementCommenter($authorName);
}
}
$page ++;
}
}
GraphQLを使ったGitHub集計も上記のようなスクリプトで集計させています。
集計したものを発表
数値は簡単にスプレッドシートにまとめてグラフ化しました。グラフは先述の通りです。
この発表をし、前回より増えたねーなどの声も上がったり、レビューに対して沢山コメントしてくれる人、PR数が多い人など、人によって数値の差が大きく、面白い発表になりました。
そして多い少ないが分かるだけでなく、
レビュー時に沢山コメントしてくれるメンバーが、隅々までコードを見てくれる点や分かりやすいコメント内容だったという声が上がったり
PR数が多いのは、どの粒度でコードレビューを出しているか、それによるコードレビューのスピード感やリリース数などの相関関係も見えてきたり
今度PRを覗いてみよう、と話が発展することもありました。
単純な数値の発表から、生産性を考えたり、レビュワーに感謝を伝えるきっかけにもなったりと発見が多い発表になりました。
というわけで今月末も振り返り会を実施します。
集計発表が楽しみです。