課題
弊社ではレビューコメントに対してフォーマットを指定する規則を設けている。
規則を設けた者として運用の評価を行いたいが、手動でのデータ集計に手間がかかる。
解決方法
GitHubではAPIが設けられているのでこれを利用する。
https://docs.github.com/ja/rest
https://docs.github.com/ja/graphql
RESTとGraphQL
APIが2種類提供されているが今回は「GraphQL」形式を選択した。
理由
- GraphQLが実装されたAPIを触ってみたかったから
- APIの呼び出しが1つで、欲しいオブジェクト毎にエンドポイントが変わらない事
- Enterprise版とドキュメントが共通っぽい(REST APIはドキュメントが違って苦労した)
Let's 開発
という訳で抽出するプログラムを作っていく。
抽出の仕様
- 団体"organization"を指定する
- リポジトリ"repository"を指定する
- 抽出期間(開始日~終了日)を指定する
抽出1:対象のプルリクを抽出する
過去の評価が目的なのでクローズ済みかつマージされたプルリクのみ抽出します。
do whileで回しつつhasNextPage
がFALSEになるまで取得させるよ。
$pr_query_string = implode(' ', [
"repo:{$org}/{$repo}",
'is:pr',
'is:closed',
'is:merged',
'merged:2023-05-08..2023-05-12',
'sort:updated-desc',
]);
$request_string = <<< __EOF
{
search(type:ISSUE, query: "{$pr_query_string}", first: 100, after: null) {
issueCount
pageInfo {
hasNextPage
endCursor
}
nodes {
... on PullRequest {
number
title
}
}
}
}
__EOF;
参考
抽出2:対象プルリクからレビューを抽出する
1で抽出したプルリク番号を基に指定プルリクのレビューコメントを抽出するクエリを逐次実行させます。弊社ではプルリクは小さく切る方針なので、レビュー個数や1レビューのスレッドが100を超えることは無い。無いよね?もし、溢れるような巨大なプルリクを作る方針なら、各コネクションのpageInfoからカーソルを取って適当にページネーションを実装しましょう。
$request_string = <<< __EOF
{
repository(owner: "{$org}", name: "{$repo}") {
pullRequest(number: {$pr_number}) {
title
reviews(first: 100) {
totalCount
nodes {
commit {
author {
name
}
}
comments(first: 100) {
totalCount
nodes {
body
author {
login
}
}
}
}
}
}
}
}
__EOF;
また、GitHub APIでは一度のリクエストで取得できるオブジェクト数に上限があるので注意して設計してください。
参考
GraphQLを使ってみた所感
今回の規模なら1個のリクエストで全部取得できたかもしれないが、長期間の抽出を考慮するとオブジェクト上限に引っ掛かりそうな予感がしたのでリクエストを2段階に分けました。
REST APIだとレビュワーのユーザーは取れるけど、レビューイ(レビュー受ける = コミットした人)のユーザー情報を取るには別途で個別のコミット情報を取得するAPIをリクエストする必要がある。つまり、レビューコメントの数だけ追加リクエストする必要があった。しかし、GraphQLだと1回のクエリで取得できたのでGraphQLのメリットを享受できた感じはある。