コードレビューは品質保証の要ですが、手動では大量の時間とコストを消費します。本稿では、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 の全体構成は以下の通りです:
- GitHub Webhook:PR 作成・更新イベントをキャプチャ
- レビュコラー:差分ファイルを解析し、AI にレビュー依頼
- HolySheep AI API:コードレビュー用の LLM 呼び出し
- GitHub API:レビューコメントの投稿
- エラー監視:障害発生時の通知と自動復旧
実装コード: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: