
GitHub Actions × Claude APIで、pushのたびにコミット要約をSlackへ送る
チームで開発していると、「今日なにがmainに入ったのか」を追うのが地味に手間です。コミットログを毎回読むのは大変なので、GitHub ActionsとClaude APIで、pushのたびにコミットの要約をSlackへ投稿する仕組みを作りました。
この記事では、同じことを再現できる最小構成のサンプルを紹介します。紹介するコードは記事用に書き起こしたもので、自分の環境のコードそのものではありません。外部のライブラリは使わず、ワークフロー1つとスクリプト1つで動く形にしています。
この記事が関係する人・関係しない人
関係する人
GitHub Actions を使っていて、main に入った変更をチームの Slack に流したい人
CI から Claude API を呼ぶ最小構成(Secrets の置き方、pushイベントの読み方)を知りたい人
関係しない人
GitHub Actions を使っていない人(この記事のサンプルは GitHub Actions のワークフロー前提です)
ファイル単位の変更まで要約したい人は、このサンプルだけでは足りません。Actions に渡される push イベントには、各コミットの追加・削除・変更ファイルの一覧が含まれないため、GitHub の API で別に取得する必要があります
自分が当てはまるかの確認方法
Secrets を登録できるかは、リポジトリの Settings → サイドバーの「Security」にある Secrets and variables → Actions を開いて確認できます
Slack 側は、Slack App の設定画面で Incoming Webhooks を有効にし、Add New Webhook to Workspace から投稿先のチャンネルを選べるかを確認します
仕組み
流れは次のとおりです。
mainブランチにpushすると、GitHub Actionsのワークフローが動く
スクリプトが、pushイベントの情報からコミットの一覧を取り出す
Claude APIに一覧を渡して、短く要約してもらう
要約を、SlackのIncoming Webhookで指定のチャンネルに投稿する
APIキーとWebhookのURLは、どちらもGitHubのSecretsに入れて、コードには書きません。

準備
1. SlackでIncoming WebhookのURLを作る
Slack Appの設定画面で、Incoming Webhooksを有効にし、投稿先のチャンネルを選んでWebhook URLを発行します。Incoming Webhookは、発行されたURLにJSONをPOSTするだけでメッセージを投稿できる仕組みです。このURLを知っている人は誰でも投稿できてしまうので、APIキーと同じように秘密情報として扱います。
Your webhook URL contains a secret. Don't share it online, including via public version control repositories.
訳: webhook の URL には秘密情報が含まれています。公開されたバージョン管理のリポジトリを含め、オンラインで共有しないでください。(Sending messages using incoming webhooks)
2. GitHubのSecretsに2つ登録する
リポジトリの設定から、Actions用のSecretsに次の2つを登録します。
ANTHROPIC_API_KEY: ClaudeのAPIキー
SLACK_WEBHOOK_URL: 1で発行したWebhook URL

ワークフロー
.github/workflows/commit-summary.yml に置きます。
name: Commit summary to Slack
on:
push:
branches: [main]
jobs:
summarize:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
- name: Summarize commits and post to Slack
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
run: node .github/scripts/summarize.mjs対象を main に絞っているのは、作業ブランチへのpushのたびにAPIを呼ばないようにするためです。
スクリプト
.github/scripts/summarize.mjs に置きます。Node.jsの標準機能(fs と fetch)だけで書いているので、npm install は要りません。
// .github/scripts/summarize.mjs
import fs from "node:fs";
// pushイベントの情報から、コミットの一覧を取り出す
const event = JSON.parse(fs.readFileSync(process.env.GITHUB_EVENT_PATH, "utf8"));
const lines = (event.commits ?? []).map(
(c) => `- ${c.message.split("\n")[0]} (${c.author.name})`
);
if (lines.length === 0) {
console.log("要約するコミットがありません");
process.exit(0);
}
// 1. Claude APIでコミット一覧を要約する
const res = await fetch("https://api.anthropic.com/v1/messages", {
method: "POST",
headers: {
"x-api-key": process.env.ANTHROPIC_API_KEY,
"anthropic-version": "2023-06-01",
"content-type": "application/json",
},
body: JSON.stringify({
model: "claude-haiku-5-5", // 使うモデルIDに置き換える
max_tokens: 500,
messages: [
{
role: "user",
content: `次のコミット一覧を、チーム向けに日本語で3行以内に要約してください。\n\n${lines.join("\n")}`,
},
],
}),
});
if (!res.ok) throw new Error(`Claude API error: ${res.status} ${await res.text()}`);
const data = await res.json();
const summary = data.content
.filter((b) => b.type === "text")
.map((b) => b.text)
.join("\n");
// 2. SlackのIncoming Webhookに投稿する
const slack = await fetch(process.env.SLACK_WEBHOOK_URL, {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify({
text: `*${event.repository.full_name}* に ${lines.length} 件のコミットがpushされました\n${summary}\n${event.compare}`,
}),
});
if (!slack.ok) throw new Error(`Slack error: ${slack.status} ${await slack.text()}`);実装のポイント
コミット一覧はイベント情報から取る
GitHub Actionsでは、ワークフローを起動したイベントの中身が、GITHUB_EVENT_PATH が指すJSONファイルに入っています。pushイベントには、pushされたコミットの配列(commits)が含まれるので、git log を自分で叩かなくても一覧が作れます。
注意点が2つあります。GitHubのドキュメントによると、commits に入るのは最大2048件です。また、Actionsに渡されるpushイベントの情報には、各コミットで追加・削除・変更されたファイルの一覧が含まれません。ファイル単位の変更まで要約したい場合は、GitHubのAPIでコミットの詳細を取りに行く必要があります。
The array includes a maximum of 2048 commits.
訳: この配列(commits)には、最大2048件のコミットが含まれます。(Webhook events and payloads)
The webhook payload available to GitHub Actions does not include the added, removed, and modified attributes in the commit object.
訳: GitHub Actions で使える webhook のペイロードには、コミットオブジェクトの added、removed、modified の属性が含まれません。(Events that trigger workflows)
送るのはコミットメッセージだけにする
このサンプルでClaude APIに送るのは、コミットメッセージの1行目と作者名だけです。コードの差分まで送ると要約の質は上がりますが、外部のAPIにソースコードを渡すことになります。業務のリポジトリで使う場合は、社内のルールを先に確認してください。
要約は軽いモデルで足りる
コミット一覧の要約は、長い推論が要らない作業です。pushのたびに呼ぶので、速くて安いモデルを選ぶのが向いていると考えています。モデルIDは更新されるので、Claudeの公式ドキュメントで最新のものを確認して置き換えてください。
失敗したら、ワークフローを失敗させる
APIやSlackがエラーを返したときは、例外を投げてワークフローを失敗させています。黙って何も投稿されないより、Actionsの画面で失敗に気づけるほうが運用しやすいからです。
動作確認
Secretsの2つを登録したことを確認する
ワークフローとスクリプトをmainにpushする
GitHubのActionsタブで、ワークフローが成功しているかを見る
Slackのチャンネルに要約が届いているかを見る
まとめ
pushイベントの情報(GITHUB_EVENT_PATH)からコミット一覧を取り、Claude APIで要約して、SlackのIncoming Webhookに投稿する
APIキーとWebhook URLはGitHubのSecretsに入れる
Claude APIに送る範囲は必要最小限にし、モデルは軽いもので足りる
関連記事
出典:
GitHub Docs「Webhook events and payloads」 https://docs.github.com/en/webhooks/webhook-events-and-payloads
GitHub Docs「Events that trigger workflows」 https://docs.github.com/en/actions/reference/workflows-and-actions/events-that-trigger-workflows
GitHub Docs「Using secrets in GitHub Actions」 https://docs.github.com/en/actions/how-tos/write-workflows/choose-what-workflows-do/use-secrets
Slack「Sending messages using incoming webhooks」 https://docs.slack.dev/messaging/sending-messages-using-incoming-webhooks
Claude Platform Docs「Messages」 https://platform.claude.com/docs/en/api/messages
仕様は更新されるので、最新の内容は各公式ページで確認してください。
開発ツールの仕様変更・提供終了の情報を毎朝お届けしています。見逃したくない方は、フォローしてください。