はじめに
LIFULL Advent Calendar 2024 7日目の記事です。
界隈では多様な手法でエンジニアの開発生産性を計測し、向上させようという動きは珍しくありません。
弊社でも複数の活動ログから生産性計測を行っていますが、まずはやはりGitHub上での活動を分析するのが定石かと思います。
とはいえGitHubから得られる情報は膨大で、GraphQLのオブジェクト仕様を見ながらいちいち試すのも大変です。
そこで、はじめの一歩として一旦これだけ取っておけばよいのでは?と思う情報をピックアップしたGraphQLを共有します。
GraphQL
項目の説明は後述するとして、GraphQL全体は以下です。
超ザックリ説明すると、Organization配下の全リポジトリに対してマージ済みPRの情報を期間指定で取得します。
※1日1回、前日のデータを取得して蓄積することを想定しています。
query {
search(query: "type:pr is:merged org:YOUR_ORG_NAME merged:YYYY-MM-DDT00:00:00+09:00..YYYY-MM-DDT23:59:59+09:00", type: ISSUE, first: 100, after: "PrevPage_endCursor") {
pageInfo {
hasNextPage
endCursor
}
issueCount
nodes {
... on PullRequest {
id
repository {
name
}
title
createdAt
mergedAt
author {
login
}
url
baseRefName
headRefName
changedFiles
additions
deletions
commits(first:1) {
totalCount
nodes {
commit {
authoredDate
}
}
}
timelineItems(itemTypes:READY_FOR_REVIEW_EVENT,last:1){
nodes {
... on ReadyForReviewEvent {
createdAt
}
}
}
reviews(first:1) {
totalCount
nodes {
createdAt
state
author {
login
}
}
}
latestOpinionatedReviews(first:1) {
nodes {
createdAt
state
author {
login
}
}
}
}
}
}
}
search
PR情報取得するクエリは多様ですが、今回はsearchを使います。
queryの記法について詳しくはこちらをご参照ください。
search(query: "type:pr is:merged org:{ORG_NAME} merged:YYYY-MM-DDT00:00:00+09:00..YYYY-MM-DDT23:59:59+09:00", type: ISSUE, first: 100, after: {endCursor}) {}
query | 説明 |
---|---|
type:pr | PullRequestに限定する |
is:merged | マージ済みのものに限定する |
org:YOUR_ORG_NAME | Organizationを指定する |
merged:YYYY-MM-DDT00:00:00+09:00..YYYY-MM-DDT23:59:59+09:00 | PRがマージされた期間を指定する。(日本時間で指定するためにYYYY-MM-DDT00:00:00+09:00の形式を使う) |
pageInfo
ページング処理のための情報です。
FIELDS | 説明 |
---|---|
hasNextPage | 次ページの有無 |
endCursor | 次ページを取得する際上記のsearch「after:」句で指定します |
... on PullRequest
PRに含まれる情報です。
FIELDS | 説明 |
---|---|
repository{name} | リポジトリ名 |
title | PRタイトル |
createdAt | PR作成日時 |
mergedAt | PRマージ日時 |
author{login} | PR作成者 |
url | URL |
baseRefName | マージ先ブランチ名 |
headRefName | マージ元ブランチ名 |
changedFiles | 変更ファイル数 |
additions | 追加行数 |
deletions | 削除行数 |
commits(first:n) | コミット情報(最初のコミットを取得するためn=1を指定,totalCountでPRに含まれるコミット総数を取得) |
timelineItems(itemTypes:READY_FOR_REVIEW_EVENT,last:n) | 「Ready for review」イベントの情報(Draft PR利用時) |
reviews(first:n) | レビュー情報(最初のレビューを取得するためn=1を指定,totalCountでPRに含まれるレビュー総数を取得) |
latestOpinionatedReviews(first:n) | レビュワー毎の最新のレビュー情報(state=APPROVEDの情報を取得するために利用。n数は自由) |
注意点
Organization管理ルールやAPI実行者の権限よって取得できる情報が変わってきます。
owner権限ユーザで実行すれば全て取得できるでしょうが、そうでない場合ご自身の欲しい情報が得られるか、権限周りの確認をしてみてください。
何が測れるのか
上記の情報を定期的に取得することで、以下のような集計、分析が可能になります。
- 期間単位でのPR数の集計
- authorやrepositoryあるいはbranchで絞ることも可能
- authorを組織やチームで紐づけることにより組織単位での計測も可能
- PRサイズ
- 変更行数や変更ファイル数、あるいはコミット数からPRのボリュームが推し測れます
- サイクルタイム
- 開発フローによって多少順番が前後するかもしれませんが以下の順にタイムスタンプが得られるため、開発フロー上で時間がかかっている点を分析できます
- 最初のコミット時間
- PR作成時間
- レビュー可能になった(Ready for review)時間
- 最初にレビューが付いた時間
- レビューがAPPROVEDされた時間
- PRがマージされた時間
- 開発フローによって多少順番が前後するかもしれませんが以下の順にタイムスタンプが得られるため、開発フロー上で時間がかかっている点を分析できます
最後に
弊社ではこのような情報をBigQueryに投入して分析していますが
気軽に始めるのであれば
GASでAPI実行 → Googleスプレッドシートに蓄積 → LookerStudioで分析
がオススメです。