◉CLAUDE LABEN
●2.1.301 — vim の % モーション、VS Code パネルでの LaTeX 数式表示、使用量上限待ちのリトライ監視の上限が入りました(10/15)●2.1.299 — 200K トークン超で約54分放置した会話はアイドル圧縮。MCP の許可ルールは名指ししたサーバーだけに一致します●SONNET 4.5 — Claude API での提供終了は 11/30、残り45日。移行先は Sonnet 5.5●WINDOWS — 日本語の環境でだけフックが黙って壊れる報告があり、文字コードの確認が呼びかけられています●FAST MODE — Opus 5.5 の Fast mode がリサーチプレビューを終え、ベータヘッダーが不要になりました(10/15)●NEW — Cowork に渡したフォルダの先頭に、十行の約束ファイルを置いてみました●2.1.301 — vim の % モーション、VS Code パネルでの LaTeX 数式表示、使用量上限待ちのリトライ監視の上限が入りました(10/15)●2.1.299 — 200K トークン超で約54分放置した会話はアイドル圧縮。MCP の許可ルールは名指ししたサーバーだけに一致します●SONNET 4.5 — Claude API での提供終了は 11/30、残り45日。移行先は Sonnet 5.5●WINDOWS — 日本語の環境でだけフックが黙って壊れる報告があり、文字コードの確認が呼びかけられています●FAST MODE — Opus 5.5 の Fast mode がリサーチプレビューを終え、ベータヘッダーが不要になりました(10/15)●NEW — Cowork に渡したフォルダの先頭に、十行の約束ファイルを置いてみました
記事一覧/API & SDK
⬡ API & SDK/2026-04-17上級

Claude API で作る GitHub PR レビューボット — Webhook統合からセキュリティスキャン・品質スコアリングまで実装

Claude API × GitHub Webhook で PR レビューボットを実装します。Tool Use で構造化スコアリングとセキュリティ検査を自動化し、署名検証が手元でだけ通る落とし穴、202 応答が失敗を隠す挙動、デバウンスとコスト管理まで実測を添えてお伝えします。

Claude API127GitHub6PR レビューTool Use6Webhook4TypeScript24自動化87コードレビュー5

✦ プレミアム記事

チームの規模が5人を超えたころから、コードレビューの「ムラ」が気になり始めました。同じようなバグパターンを、あるメンバーは毎回指摘するのに、別のメンバーは見過ごしてしまいます。疲れているときはレビューが甘くなります。そして何より、全員がレビューの「基準」を共有できていません。

Claude API を使えば、このムラを大きく減らせます。ただし「コードを渡してレビューして」と素朴にお願いするだけでは、返ってくる内容がいつも違って運用に耐えません。重要なのは、Tool Use を使って構造化されたレビュー結果を得ることと、GitHub Webhook から一気通貫のパイプラインを設計することです。

ここではGitHub に PR が作成されたときに自動でレビューコメントを投稿するボットを、実際に動くコードで構築します。アーキテクチャ設計から本番デプロイまで、各ステップで「なぜそう実装するのか」の理由も含めてお伝えします。

システム全体のアーキテクチャ

まず全体像を把握しましょう。処理の流れはシンプルです。

GitHub PR 作成/更新
    ↓
Webhook イベント送信(POST /webhook)
    ↓
Express サーバー(署名検証)
    ↓
GitHub API で PR diff 取得
    ↓
Claude API(Tool Use)でレビュー生成
    ↓
GitHub API でレビューコメント投稿

技術スタックは以下の通りです。

  • ランタイム: Node.js 22 + TypeScript
  • Webフレームワーク: Express.js 4.x
  • Claude API: @anthropic-ai/sdk v1.x
  • GitHub API: @octokit/rest v21
  • デプロイ先: Railway / Render(常時起動が前提)

なぜ常時起動サーバーが必要か

GitHub Webhook はリアルタイムで POST リクエストを送ってきます。Cloudflare Workers や Vercel Serverless Functions でも動作しますが、コールドスタートが発生するアーキテクチャは避けたほうが無難です。GitHub は Webhook のタイムアウトを10秒に設定しているため、コールドスタートで応答が遅れると再送ループに入ることがあります。

Railway であれば月$5程度から常時起動できます。個人プロジェクトや小規模チームには十分です。

まず依存関係をインストールします。

npm init -y
npm install express @anthropic-ai/sdk @octokit/rest
npm install -D typescript @types/express @types/node ts-node

Step 1: GitHub Webhook サーバーの実装

Webhook の受信から始めます。最初に詰まりやすいのが署名検証です。GitHub は Webhook リクエストに X-Hub-Signature-256 ヘッダーを付けて送ってきます。これを検証しないと、第三者から偽のリクエストを送られても判別できません。

// src/webhook.ts
import express from 'express';
import crypto from 'crypto';
import { handlePullRequestEvent } from './handlers/pullRequest';
 
const app = express();
 
// ⚠️ 重要: raw body が必要なため express.json() は使わない
app.use(
  express.raw({ type: 'application/json' })
);
 
function verifyWebhookSignature(
  rawBody: Buffer,
  signature: string,
  secret: string
): boolean {
  const hmac = crypto.createHmac('sha256', secret);
  hmac.update(rawBody);
  const expectedSignature = `sha256=${hmac.digest('hex')}`;
 
  // タイミング攻撃を防ぐため timingSafeEqual を使う
  try {
    return crypto.timingSafeEqual(
      Buffer.from(signature),
      Buffer.from(expectedSignature)
    );
  } catch {
    // 長さが違う場合は false(timingSafeEqual は同じ長さ必須)
    return false;
  }
}
 
app.post('/webhook', async (req, res) => {
  const signature = req.headers['x-hub-signature-256'] as string;
  const eventType = req.headers['x-github-event'] as string;
 
  if (!signature) {
    return res.status(401).json({ error: 'Missing signature' });
  }
 
  const isValid = verifyWebhookSignature(
    req.body as Buffer,
    signature,
    process.env.GITHUB_WEBHOOK_SECRET!
  );
 
  if (!isValid) {
    console.error('Invalid webhook signature — possible spoofed request');
    return res.status(401).json({ error: 'Invalid signature' });
  }
 
  // レスポンスを先に返す(GitHub のタイムアウト10秒対策)
  res.status(202).json({ accepted: true });
 
  const payload = JSON.parse((req.body as Buffer).toString());
 
  if (
    eventType === 'pull_request' &&
    ['opened', 'synchronize'].includes(payload.action)
  ) {
    // 非同期で処理(レスポンス後に実行)
    handlePullRequestEvent(payload).catch(err => {
      console.error('[PR handler] Unhandled error:', err);
    });
  }
});
 
app.get('/health', (_req, res) => {
  res.json({ status: 'ok', timestamp: new Date().toISOString() });
});
 
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
  console.log(`Webhook server listening on port ${PORT}`);
});

2つの重要なポイントがあります。

express.raw() を使う理由: express.json() は body をパースしてから渡してきます。しかし署名検証は生の bytes に対して HMAC を計算する必要があります。パース後の JSON 文字列では計算結果が一致しません。ここで詰まる方が非常に多いです。

レスポンスを先に返す理由: GitHub の Webhook タイムアウトは10秒です。Claude API の呼び出しには数秒かかることがあるため、202 Accepted を即座に返してから処理を非同期で続けます。レスポンスを待ってから処理すると、タイムアウトで GitHub が再送し、同じ PR が2回レビューされる事態になります。

✦

ここまでお読みいただきありがとうございます。

この記事の続きを読む

この先には、実装コードやベンチマーク結果など、実務でお役に立てる内容をご用意しています。このサイトは広告を掲載しておらず、サーバーや開発にかかる費用はメンバーの皆様のご支援で成り立っています。もしお役に立てていましたら、ご支援いただけますと大変ありがたいです。

この記事で得られること
✦express.json() の署名検証は Node 22 実測で 8 通りの body 中 2 通りだけ通る——手元で合格して本番でのみ 401 になる仕組みと、express.raw() での回避
✦Tool Use(tool_choice: any)で overall_score・security_issues を構造化し、指数バックオフで本番のばらつきを抑える設計
✦202 を先に返す設計では失敗が配信履歴に出ない実測——.catch 忘れはプロセスごと停止し、受付・完了・失敗を別に数える終端記録で検知する
Stripe による安全な決済 · いつでもキャンセル可能
✦

この記事を購入する

この先の内容をすべてお読みいただけます。一度のご購入で、いつでも何度でもアクセスできます。このサイトは広告を掲載しておらず、皆さまのご支援がサーバー費用などの運営を支えています。

または
メンバーシップなら全記事が読み放題 →
シェア

お読みいただきありがとうございます

Claude Lab は広告なしで運営しており、サーバー費用などの運営コストはメンバーシップのご支援で賄っています。実装コード・ベンチマーク・本番設計パターンなど、実務でお役立ていただける記事を毎日更新しています。もし読んでよかったと感じていただけましたら、ぜひご覧ください。

  • ✦コピー&ペーストで使える実装コード付き
  • ✦毎日新しい上級ガイドを追加
  • ✦¥580/月 または ¥1,480 の永久アクセス
メンバーシップを見る →

関連記事

⬡ API & SDK2026-08-01
会話の途中でツールを差し替える — プロンプトキャッシュを守るツールレジストリの設計
ターン間でツールを追加・削除できるようになった一方、ツール定義はキャッシュプレフィックスの最前列にあります。12種類の変更を指紋で実測し、安定コアと揮発テールに分けるレジストリ設計とガード実装をまとめました。
⬡ API & SDK2026-06-13
Claude Vision API 実装パターン — 画像解析・PDF 処理・OCR を本番品質で動かすまで
Claude API のビジョン機能を本番投入するための実装パターンをまとめました。Base64・URL・Files API の使い分け、ネイティブ PDF 処理、Tool Use による壊れない構造化抽出、Batch API でのコスト削減、エラー対処まで動くコードで解説します。
⬡ API & SDK2026-05-15
壁紙アプリの一括カテゴリ分類を Claude Vision API で自動化した話 — 実運用で見えた精度と限界
個人開発の壁紙アプリで画像のカテゴリ分類をClaude Vision APIに任せた実体験の記録です。SonnetとHaikuのモデル選択、75枚の手動検証で確かめた分類精度、実運用で踏んだ落とし穴、途中で落ちても再開できるバッチ設計、そして実際にかかったコストの感覚まで正直に書きました。