こんにちは!
ポーラ・オルビスホールディングスのITプロダクト開発チームでスクラムマスターをしている川田です。
Claude CodeやGitHub Copilotなどを利用していると、AIによってどれだけ生産性があがったか報告が求められたり、組織のKPIになっていたりするケースがあると思います。
そこまでは求められていなくても、チームとして状況を見える化しておくことは重要ですよね🤩
今回は、AIによって作られたPRの数をカウントすることで行う簡易的な生産性の計測を、GitHub Actionsを使って実現してみようと思います。
前提
この記事においては、AIによって作られたPRの定義を以下と定めます。
- コミットがGitHub CopilotなどのAIエージェントによって作成された内容のみで構成されている
- Devinが作成したもの
コミット内容がAIエージェントによって作成されているかについては、
- コミットメッセージに
[ai]という文字列が含まれている - コミットメッセージに
Apply suggestion from @Copilotが含まれている
のどちらかを満たしているかどうかで判定しています。
1の条件については、例えばClaude Codeなら settings.json にある attribution設定 の commit に設定しておくと入力漏れが防げるため便利です。
また2の条件については、PR上でGitHub CopilotからのCommit suggestionを受け入れたときのコミットメッセージとなるので、こちらも対象としています。
GitHub Actionsでの判定とラベル付け
PRが変更されたタイミングで、前提に記載した条件にあてはまるか判定するGitHub Actionsを動かすようにします。
条件にあてはまった場合は、そのPRに ai-only ラベルを付与することで後からカウントできるようにします。
なお、ラベルは対象のリポジトリで事前に作成しておいてください。
実際のコードは以下の通りです。
name: Label AI-only PRs
on:
pull_request:
types: [opened, reopened, edited, synchronize, ready_for_review, closed]
permissions:
contents: read
pull-requests: write
jobs:
check-and-label:
runs-on: ubuntu-latest
steps:
- name: Check pull request for AI-only
id: check
uses: actions/github-script@v7
with:
script: |
const pr = context.payload.pull_request;
if (!pr) {
core.setOutput('ai_only', 'false');
return;
}
// --- PRの作成者だけでAI利用と判断するユーザー名のリスト ---
const aiIntegrationBots = [
'devin-ai-integration[bot]',
'devin-ai-integration',
'app/devin-ai-integration'
];
if (aiIntegrationBots.includes(pr.user.login)) {
core.setOutput('ai_only', 'true');
return;
}
const per_page = 100;
let page = 1;
let commits = [];
while (true) {
const { data } = await github.rest.pulls.listCommits({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: pr.number,
per_page,
page
});
commits = commits.concat(data);
if (data.length < per_page) break;
page++;
}
// --- ここで「PR内部の merge commit(親が2つ以上)」を除外する ---
const commitsForCheck = commits.filter(c => {
const parentCount = Array.isArray(c.parents) ? c.parents.length : (c.commit?.parents?.length ?? 0);
return parentCount <= 1; // parentが2つ以上 = merge commit → 除外
});
if (commitsForCheck.length === 0) {
core.setOutput('ai_only', 'false');
return;
}
const isAiOnly = commitsForCheck.every(c => {
const msg = (c.commit?.message || '').trim().toLowerCase();
return msg.includes('[ai]') || msg.includes('apply suggestion from @copilot');
});
core.setOutput('ai_only', String(isAiOnly));
- name: Add label if ai-only
if: steps.check.outputs.ai_only == 'true'
uses: actions-ecosystem/action-add-labels@v1
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
labels: ai-only
- name: Remove label if not ai-only
if: steps.check.outputs.ai_only != 'true'
uses: actions-ecosystem/action-remove-labels@v1
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
labels: ai-only
実装のポイントは以下の通りです。
- PRの作成者の名前が
aiIntegrationBotsに含まれるものと一致するかチェックしています- Devinはおそらく中央の1つだけあればよいと思います(他は念のため・・・)
- 将来的に新しいAIエージェントも対象とする場合は、このリストに1行追加するだけでOKです
- GitHub APIの List Commits を利用して、各コミットメッセージが条件を満たすかチェックしています
- ステップの最後に、前段で判定した条件をもとにラベルの付け外しを行っています
カウント方法
あとは ai-only ラベルが付いたPRの数をカウントするだけです。
カウント方法はいくつかあるので、お好みの方法で実施してください。
GitHub API でカウントする
Search API を利用してカウントし、jq を利用して結果から total_count のみを抜き出します。
repo を複数指定することで、複数のリポジトリの合算を算出することも可能です。
curl -s -L \
-H "Accept: application/vnd.github+json" \
-H "Authorization: Bearer TOKEN" \
-H "X-GitHub-Api-Version: 2026-03-10" \
"https://api.github.com/search/issues?q=repo:OWNER/REPO+is:pr+label:ai-only" | jq '.total_count'
ghコマンドを利用した方法でも同様に実行可能です。
gh api \
-H "Accept: application/vnd.github+json" \
-H "Authorization: Bearer TOKEN" \
-H "X-GitHub-Api-Version: 2026-03-10" \
search/issues?q=repo:OWNER/REPO+is:pr+label:ai-only | jq '.total_count'
GitHub上でカウントする
APIと同じ検索方法で、ブラウザからGitHubにアクセスして確認することも可能です。
リポジトリの複数指定も可能です。
https://github.com/pulls?q=repo:OWNER/REPO+is:pr+label:ai-only
上記にアクセスすると、PRのリストの上部に合計が表示されています。
おまけ:NewRelicで可視化してみる
とりあえず困ったらNewRelicに送っちゃおう😎ということで、ラベルの付与状況をNewRelicに送ることで、ダッシュボードを作って可視化してみました。
PRがcloseしたタイミングでPRのメトリクスを計測するため、NewRelicのカスタムイベントを送る既存のGitHub Actionsがあったので、そのイベントに以下のように処理した内容を追加しました。
// 対象のPRにai-onlyラベルが付いている場合はai-only, そうでない場合はhuman-madeをセット
const isAIOnly = context.payload.pull_request.labels.some(label => label.name === "ai-only") ? "ai-only" : "human-made";
この処理結果を ai_only という項目名称、PullRequest というイベントタイプでNewRelicに送信した場合、以下のクエリで集計が可能です。
SELECT count(*)
FROM PullRequest
FACET ai_only
集計した結果は pie chartで表示するといい感じです👍
さいごに
今回はPRの数という観点で生産性の簡易的な計測を行ってみました。
GitHubのコミット情報と紐づけられたので、将来的には変更行数など、もう一歩踏み込んだ分析も実施したいと思います!💪

