コードレビューは品質保証の要ですが、手動では大量の時間とコストを消費します。本稿では、HolySheep AI を使用して Pull Request 自動レビュー Bot を構築する完整な解决方案を解説します、実際のエラーシュエーションとその対処法を交えながら説明します。

問題提起:手動レビューの限界

エンジニアリングチームでよく遭遇する实际问题として、以下のようなシナリオがあります:

ConnectionError: timeout - GitHub API requests exceeded rate limit
at PullRequestReviewer.checkDiff (/app/reviewer.js:142:15)
at async main (/app/index.js:28:10)
{ statusCode: 403, message: 'API rate limit exceeded. Retry after 3600 seconds' }

このようなタイムアウトやレートリミットエラーにより、レビューボットが停止することは珍しくありません。また、以下のような认证エラーも頻繁に発生します:

401 Unauthorized - Invalid or expired GitHub token
at verifyWebhookSignature (/lib/auth.js:34:8)
{ error: 'JWT validation failed', github_status: 'deactivated' }

403 Forbidden - Repository access denied
at PullRequestReviewer.fetchFiles (/app/reviewer.js:89:12)
{ required_permissions: ['pull_requests', 'commit_statuses'] }

本稿では、これらのエラーを適切に 处理し、安定して動作する PR Review Bot を構築する方法を詳しく解説します。

システム構成アーキテクチャ

PR Review Bot の全体構成は以下の通りです:

実装コード:PR Review Bot

環境構築

# 必要なパッケージのインストール
npm install @octokit/rest express crypto-js dotenv

ディレクトリ構成

project/ ├── src/ │ ├── index.js # メインエントリーポイント │ ├── webhook.js # Webhook ハンドラー │ ├── reviewer.js # AI レビュコラー │ ├── holysheep.js # HolySheep API クライアント │ ├── github.js # GitHub API 操作 │ └── errors.js # エラー処理 ├── .env # 環境変数 └── package.json

設定ファイル(.env)

# HolySheep AI - レートのacherge ¥1=$1(公式比85%節約)
HOLYSHEEP_API_KEY=YOUR_HOLYSHEEP_API_KEY
HOLYSHEEP_BASE_URL=https://api.holysheep.ai/v1

GitHub Settings

GITHUB_TOKEN=ghp_your_github_personal_access_token WEBHOOK_SECRET=your_webhook_secret REPO_OWNER=your-org-name REPO_NAME=your-repository-name

Bot Configuration

BOT_NAME=holysheep-reviewer AUTO_REVIEW_LABELS=["needs-review", "ai-review"] REVIEW_MODEL=gpt-4.1 # または claude-sonnet-4.5, gemini-2.5-flash

HolySheep API クライアント(holysheep.js)

const HOLYSHEEP_BASE_URL = process.env.HOLYSHEEP_BASE_URL || 'https://api.holysheep.ai/v1';

/**
 * HolySheep AI API クライアント
 * レート ¥1=$1(公式比85%節約)、登録で無料クレジット付き
 */
class HolySheepClient {
  constructor(apiKey) {
    this.apiKey = apiKey;
    this.baseUrl = HOLYSHEEP_BASE_URL;
    this.maxRetries = 3;
    this.retryDelay = 1000;
  }

  /**
   * APIリクエストの共通処理(リトライ機能付き)
   */
  async request(endpoint, options = {}, retries = 0) {
    const url = ${this.baseUrl}${endpoint};
    const headers = {
      'Authorization': Bearer ${this.apiKey},
      'Content-Type': 'application/json',
      ...options.headers
    };

    try {
      const response = await fetch(url, {
        ...options,
        headers
      });

      // 429 Rate Limit の場合はリトライ
      if (response.status === 429 && retries < this.maxRetries) {
        const retryAfter = parseInt(response.headers.get('Retry-After') || '60');
        console.log(Rate limited. Retrying after ${retryAfter} seconds...);
        await this.sleep(retryAfter * 1000);
        return this.request(endpoint, options, retries + 1);
      }

      // 401 Unauthorized の処理
      if (response.status === 401) {
        throw new Error('HOLYSHEEP_API_KEYが無効です。APIキーを確認してください。');
      }

      // 5xx Server Error の場合はリトライ
      if (response.status >= 500 && retries < this.maxRetries) {
        console.log(Server error (${response.status}). Retrying...);
        await this.sleep(this.retryDelay * Math.pow(2, retries));
        return this.request(endpoint, options, retries + 1);
      }

      const data = await response.json();
      
      if (!response.ok) {
        throw new Error(HolySheep API Error: ${data.error?.message || response.statusText});
      }

      return data;
    } catch (error) {
      if (error.code === 'ENOTFOUND' || error.code === 'ECONNREFUSED') {
        throw new Error(HolySheep APIに接続できません。ネットワークを確認してください。);
      }
      throw error;
    }
  }

  /**
   * コードレビュー用のプロンプト生成
   */
  generateReviewPrompt(diff, context) {
    return {
      model: 'gpt-4.1',  // $8/MTok - 高品質レビュー
      messages: [
        {
          role: 'system',
          content: `あなたは経験豊富なコードレビュコラーです。
以下の Pull Request の差分をレビューし、以下の観点を報告してください:

1. **セキュリティ**: SQLインジェクション、XSS、認証の問題
2. **バグの可能性**: NPE、メモリリーク、論理解エラー
3. **パフォーマンス**: 非効率な処理、不要なAPI呼び出し
4. **コード品質**: 命名規則、コメント、ドキュメント
5. **ベストプラクティス**: 設計パターン、エラー処理

回答はJSON形式としてください:
{
  "summary": "全体的な要約(100文字以内)",
  "severity": "high|medium|low|none",
  "issues": [
    {
      "file": "ファイルパス",
      "line": 行番号,
      "type": "security|bug|performance|quality|best-practice",
      "severity": "high|medium|low",
      "description": "問題の説明",
      "suggestion": "修正案"
    }
  ],
  "praise": ["良い点のリスト"]
}`
        },
        {
          role: 'user',
          content: Context: ${context}\n\nDiff:\n${diff}
        }
      ],
      temperature: 0.3,
      max_tokens: