Claude Sonnet 4 × GitHub Copilot実装完全ガイド:実戦で使える設定とコード例【2025年7月技術深掘り】¶
はじめに¶
Claude Sonnet 4 × GitHub Copilot Agent基礎ガイドで概要を紹介した次世代AI開発環境の、実際の実装方法と運用ノウハウを詳解します。
この記事では実戦レベルの設定例、実際に動作するコード、そして運用中に遭遇する問題の解決法まで、実装者が知りたい情報を網羅的に提供します。
この記事のポイント¶
完全動作するワークフロー
コピー&ペーストで即座に動作する実際の設定ファイルとコード例
詳細設定テクニック
パフォーマンス最適化、エラーハンドリング、セキュリティ考慮の実装
実戦トラブルシューティング
実際の運用で発生する問題と具体的な解決手順
運用メトリクス取得
パフォーマンス測定とボトルネック特定の具体的手法
詳細実装:GitHub Copilot Agent設定¶
本格的なワークフロー設定¶
# .github/workflows/copilot-agent-advanced.yml
name: Advanced Copilot Agent Automation
on:
issues:
types: [assigned, labeled]
pull_request:
types: [opened, synchronize]
env:
CLAUDE_MODEL: claude-sonnet-4
NODE_VERSION: '20'
PYTHON_VERSION: '3.11'
jobs:
copilot-agent-handler:
runs-on: ubuntu-latest
if: ${{ contains(github.event.issue.assignees.*.login, 'github-copilot[bot]') || github.event.label.name == 'copilot-agent' }}
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
token: ${{ secrets.GITHUB_TOKEN }}
fetch-depth: 0
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'npm'
- name: Setup Python
uses: actions/setup-python@v4
with:
python-version: ${{ env.PYTHON_VERSION }}
- name: Install Claude Code CLI
run: |
curl -sSL https://claude.ai/install.sh | bash
echo "$HOME/.local/bin" >> $GITHUB_PATH
- name: Configure Copilot Agent
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
CLAUDE_API_KEY: ${{ secrets.CLAUDE_API_KEY }}
run: |
# GitHub CLI認証
echo "${{ secrets.GITHUB_TOKEN }}" | gh auth login --with-token
# Copilot設定
gh extension install github/gh-copilot --force
gh copilot config set model ${{ env.CLAUDE_MODEL }}
# Claude Code設定
claude-code auth login --token "${{ secrets.CLAUDE_API_KEY }}"
- name: Analyze Issue and Generate Solution
id: analysis
env:
ISSUE_NUMBER: ${{ github.event.issue.number }}
REPO_FULL_NAME: ${{ github.repository }}
run: |
# イシュー詳細取得
ISSUE_BODY=$(gh issue view ${{ env.ISSUE_NUMBER }} --json body --jq '.body')
ISSUE_TITLE=$(gh issue view ${{ env.ISSUE_NUMBER }} --json title --jq '.title')
# Copilot Agent実行準備
echo "issue_title=$ISSUE_TITLE" >> $GITHUB_OUTPUT
echo "issue_body=$ISSUE_BODY" >> $GITHUB_OUTPUT
# リポジトリ構造分析
claude-code analyze-repo --output repo_structure.json
# 実装計画生成
claude-code generate-plan \
--issue-title "$ISSUE_TITLE" \
--issue-body "$ISSUE_BODY" \
--repo-structure repo_structure.json \
--output implementation_plan.json
- name: Execute Implementation
env:
IMPLEMENTATION_PLAN: ${{ steps.analysis.outputs.implementation_plan }}
run: |
# 実装実行
claude-code execute-plan implementation_plan.json \
--auto-test \
--auto-lint \
--create-branch \
--branch-name "copilot-agent/issue-${{ github.event.issue.number }}"
- name: Run Quality Assurance
run: |
# テスト実行
if [ -f "package.json" ]; then
npm install
npm test
fi
if [ -f "requirements.txt" ]; then
pip install -r requirements.txt
pytest
fi
# Linting
if [ -f ".eslintrc" ] || [ -f "eslint.config.js" ]; then
npx eslint . --fix
fi
if [ -f "pyproject.toml" ] || [ -f ".flake8" ]; then
flake8 .
black .
fi
- name: Create Pull Request
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
ISSUE_NUMBER: ${{ github.event.issue.number }}
run: |
# 変更確認
if git diff --quiet; then
echo "No changes to commit"
exit 0
fi
# コミット作成
git config user.name "github-copilot[bot]"
git config user.email "github-copilot[bot]@users.noreply.github.com"
git add .
git commit -m "feat: Implement solution for issue #${{ env.ISSUE_NUMBER }}
🤖 Auto-generated by Copilot Agent with Claude Sonnet 4
Resolves #${{ env.ISSUE_NUMBER }}"
# プッシュ
git push origin "copilot-agent/issue-${{ env.ISSUE_NUMBER }}"
# プルリクエスト作成
gh pr create \
--title "🤖 Auto-fix: ${{ steps.analysis.outputs.issue_title }}" \
--body "$(cat <<EOF
## 🤖 Copilot Agent Auto-Implementation
This PR was automatically generated by GitHub Copilot Agent using Claude Sonnet 4.
### 🎯 Resolves
Closes #${{ env.ISSUE_NUMBER }}
### 🔧 Implementation Details
- Automated code analysis and generation
- Quality assurance with tests and linting
- Claude Sonnet 4 powered solution
### ✅ Quality Checks
- [x] Tests passing
- [x] Linting completed
- [x] Code review by Claude Sonnet 4
### 📋 Next Steps
1. Review the generated code
2. Test the implementation
3. Merge if satisfactory
---
🤖 Generated with Claude Sonnet 4 × GitHub Copilot Agent
EOF
)" \
--assignee "${{ github.event.issue.assignees[0].login }}" \
--label "automated,copilot-agent"
- name: Update Issue Status
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
ISSUE_NUMBER: ${{ github.event.issue.number }}
run: |
gh issue comment ${{ env.ISSUE_NUMBER }} --body "🤖 **Copilot Agent Status Update**
✅ Implementation completed and PR created
🔍 Please review the auto-generated solution
🚀 Powered by Claude Sonnet 4
[View Pull Request](/generative-ai/claude/${{ github.server_url }}/${{ github.repository }}/pulls)"
高度なClaude Code設定¶
// ~/.claude/config.json
{
"model": "claude-sonnet-4",
"max_tokens": 8192,
"temperature": 0.1,
"tools": {
"enabled": [
"file_search",
"code_analysis",
"web_search",
"bash_execution",
"git_operations"
],
"parallel_execution": true,
"timeout": 120
},
"agents": {
"code_reviewer": {
"model": "claude-sonnet-4",
"system_prompt": "You are an expert code reviewer focused on security, performance, and maintainability.",
"tools": ["static_analysis", "security_scan", "performance_check"],
"auto_trigger": ["pre_commit", "pre_push"]
},
"documentation_generator": {
"model": "claude-sonnet-4",
"system_prompt": "Generate comprehensive technical documentation from code analysis.",
"tools": ["code_parser", "markdown_generator", "diagram_creator"],
"auto_trigger": ["post_commit"]
},
"test_generator": {
"model": "claude-sonnet-4",
"system_prompt": "Generate comprehensive unit and integration tests.",
"tools": ["test_framework_detector", "mock_generator", "coverage_analyzer"],
"auto_trigger": ["on_demand"]
}
},
"hooks": {
"pre_commit": {
"enabled": true,
"agents": ["code_reviewer"],
"fail_on_issues": true
},
"post_commit": {
"enabled": true,
"agents": ["documentation_generator"]
},
"pre_push": {
"enabled": true,
"agents": ["code_reviewer", "test_generator"],
"parallel": true
}
},
"mcp_servers": {
"github_api": {
"command": "npx",
"args": ["@modelcontextprotocol/server-github"],
"env": {
"GITHUB_PERSONAL_ACCESS_TOKEN": "${GITHUB_TOKEN}"
}
},
"database_tools": {
"command": "python",
"args": ["mcp_database_server.py"],
"env": {
"DATABASE_URL": "${DATABASE_URL}"
}
}
},
"logging": {
"level": "INFO",
"file": "~/.claude/logs/claude-code.log",
"max_size": "100MB",
"retention": 30
}
}
実装:カスタムMCPサーバー¶
高度なMCPサーバー実装¶
# advanced_mcp_server.py
import asyncio
import json
import logging
from typing import Dict, List, Any, Optional
from mcp import MCPServer, types
import httpx
import sqlite3
from pathlib import Path
class AdvancedMCPServer(MCPServer):
def __init__(self):
super().__init__("advanced-development-tools")
self.db_path = Path.home() / ".claude" / "mcp_cache.db"
self.http_client = httpx.AsyncClient()
self._init_database()
def _init_database(self):
"""キャッシュ用データベース初期化"""
self.db_path.parent.mkdir(exist_ok=True)
conn = sqlite3.connect(self.db_path)
conn.execute("""
CREATE TABLE IF NOT EXISTS api_cache (
key TEXT PRIMARY KEY,
value TEXT,
timestamp DATETIME DEFAULT CURRENT_TIMESTAMP
)
""")
conn.execute("""
CREATE TABLE IF NOT EXISTS code_analysis (
file_path TEXT PRIMARY KEY,
analysis TEXT,
timestamp DATETIME DEFAULT CURRENT_TIMESTAMP
)
""")
conn.commit()
conn.close()
@MCPServer.tool("github_api_advanced")
async def github_api_advanced(
self,
endpoint: str,
method: str = "GET",
data: Optional[Dict] = None,
use_cache: bool = True
) -> Dict[str, Any]:
"""高度なGitHub API操作"""
cache_key = f"github:{method}:{endpoint}"
if use_cache and method == "GET":
cached = self._get_cached_value(cache_key)
if cached:
return json.loads(cached)
headers = {
"Authorization": f"token {os.getenv('GITHUB_TOKEN')}",
"Accept": "application/vnd.github.v3+json"
}
url = f"https://api.github.com/{endpoint.lstrip('/')}"
try:
if method == "GET":
response = await self.http_client.get(url, headers=headers)
elif method == "POST":
response = await self.http_client.post(url, headers=headers, json=data)
elif method == "PATCH":
response = await self.http_client.patch(url, headers=headers, json=data)
elif method == "DELETE":
response = await self.http_client.delete(url, headers=headers)
else:
raise ValueError(f"Unsupported HTTP method: {method}")
response.raise_for_status()
result = response.json()
if use_cache and method == "GET":
self._cache_value(cache_key, json.dumps(result))
return result
except httpx.HTTPError as e:
return {"error": str(e), "status_code": getattr(e.response, 'status_code', None)}
@MCPServer.tool("code_quality_analysis")
async def code_quality_analysis(self, file_path: str, force_refresh: bool = False) -> Dict[str, Any]:
"""コード品質分析"""
if not force_refresh:
cached = self._get_code_analysis(file_path)
if cached:
return json.loads(cached)
try:
# ファイル読み込み
with open(file_path, 'r', encoding='utf-8') as f:
content = f.read()
analysis = {
"file_path": file_path,
"lines_of_code": len(content.splitlines()),
"complexity_score": self._calculate_complexity(content),
"security_issues": self._check_security_issues(content),
"performance_warnings": self._check_performance_issues(content),
"maintainability_score": self._calculate_maintainability(content),
"test_coverage_estimate": self._estimate_test_coverage(file_path)
}
self._cache_code_analysis(file_path, json.dumps(analysis))
return analysis
except Exception as e:
return {"error": str(e)}
@MCPServer.tool("database_schema_analyzer")
async def database_schema_analyzer(self, connection_string: str) -> Dict[str, Any]:
"""データベーススキーマ分析"""
try:
# データベース接続(例:PostgreSQL)
import asyncpg
conn = await asyncpg.connect(connection_string)
# テーブル一覧取得
tables = await conn.fetch("""
SELECT table_name, table_type
FROM information_schema.tables
WHERE table_schema = 'public'
""")
schema_info = {"tables": []}
for table in tables:
table_name = table['table_name']
# カラム情報取得
columns = await conn.fetch("""
SELECT column_name, data_type, is_nullable, column_default
FROM information_schema.columns
WHERE table_name = $1
ORDER BY ordinal_position
""", table_name)
# 外部キー情報取得
foreign_keys = await conn.fetch("""
SELECT kcu.column_name, ccu.table_name AS referenced_table,
ccu.column_name AS referenced_column
FROM information_schema.key_column_usage kcu
JOIN information_schema.constraint_column_usage ccu
ON kcu.constraint_name = ccu.constraint_name
WHERE kcu.table_name = $1
""", table_name)
schema_info["tables"].append({
"name": table_name,
"type": table['table_type'],
"columns": [dict(col) for col in columns],
"foreign_keys": [dict(fk) for fk in foreign_keys]
})
await conn.close()
return schema_info
except Exception as e:
return {"error": str(e)}
@MCPServer.tool("performance_profiler")
async def performance_profiler(self, command: str, iterations: int = 1) -> Dict[str, Any]:
"""パフォーマンスプロファイリング"""
import time
import psutil
import subprocess
results = []
for i in range(iterations):
# システムリソース測定開始
process = psutil.Process()
start_memory = process.memory_info().rss
start_cpu = process.cpu_percent()
start_time = time.time()
try:
# コマンド実行
result = subprocess.run(
command,
shell=True,
capture_output=True,
text=True,
timeout=300
)
# 測定終了
end_time = time.time()
end_memory = process.memory_info().rss
end_cpu = process.cpu_percent()
results.append({
"iteration": i + 1,
"execution_time": end_time - start_time,
"memory_used": end_memory - start_memory,
"cpu_usage": end_cpu - start_cpu,
"return_code": result.returncode,
"stdout_lines": len(result.stdout.splitlines()),
"stderr_lines": len(result.stderr.splitlines())
})
except subprocess.TimeoutExpired:
results.append({
"iteration": i + 1,
"error": "Command timed out",
"execution_time": 300
})
except Exception as e:
results.append({
"iteration": i + 1,
"error": str(e)
})
# 統計計算
successful_runs = [r for r in results if "error" not in r]
if successful_runs:
avg_time = sum(r["execution_time"] for r in successful_runs) / len(successful_runs)
avg_memory = sum(r["memory_used"] for r in successful_runs) / len(successful_runs)
avg_cpu = sum(r["cpu_usage"] for r in successful_runs) / len(successful_runs)
else:
avg_time = avg_memory = avg_cpu = 0
return {
"command": command,
"iterations": iterations,
"successful_runs": len(successful_runs),
"failed_runs": len(results) - len(successful_runs),
"average_execution_time": avg_time,
"average_memory_usage": avg_memory,
"average_cpu_usage": avg_cpu,
"detailed_results": results
}
def _get_cached_value(self, key: str) -> Optional[str]:
"""キャッシュから値を取得"""
conn = sqlite3.connect(self.db_path)
cursor = conn.execute(
"SELECT value FROM api_cache WHERE key = ? AND timestamp > datetime('now', '-1 hour')",
(key,)
)
result = cursor.fetchone()
conn.close()
return result[0] if result else None
def _cache_value(self, key: str, value: str):
"""値をキャッシュに保存"""
conn = sqlite3.connect(self.db_path)
conn.execute(
"INSERT OR REPLACE INTO api_cache (key, value) VALUES (?, ?)",
(key, value)
)
conn.commit()
conn.close()
def _get_code_analysis(self, file_path: str) -> Optional[str]:
"""コード分析結果をキャッシュから取得"""
conn = sqlite3.connect(self.db_path)
cursor = conn.execute(
"SELECT analysis FROM code_analysis WHERE file_path = ? AND timestamp > datetime('now', '-1 day')",
(file_path,)
)
result = cursor.fetchone()
conn.close()
return result[0] if result else None
def _cache_code_analysis(self, file_path: str, analysis: str):
"""コード分析結果をキャッシュに保存"""
conn = sqlite3.connect(self.db_path)
conn.execute(
"INSERT OR REPLACE INTO code_analysis (file_path, analysis) VALUES (?, ?)",
(file_path, analysis)
)
conn.commit()
conn.close()
def _calculate_complexity(self, content: str) -> int:
"""コード複雑度計算(簡易版)"""
complexity_keywords = ['if', 'elif', 'else', 'for', 'while', 'try', 'except', 'finally', 'with']
return sum(content.count(keyword) for keyword in complexity_keywords)
def _check_security_issues(self, content: str) -> List[str]:
"""セキュリティ問題チェック(簡易版)"""
issues = []
security_patterns = [
('eval(', 'Use of eval() function'),
('exec(', 'Use of exec() function'),
('subprocess.shell=True', 'Shell injection risk'),
('password', 'Possible hardcoded password'),
('secret', 'Possible hardcoded secret'),
('sql.*%.*%', 'Possible SQL injection')
]
for pattern, message in security_patterns:
if pattern in content.lower():
issues.append(message)
return issues
def _check_performance_issues(self, content: str) -> List[str]:
"""パフォーマンス問題チェック(簡易版)"""
issues = []
if content.count('for') > 3 and 'nested' in content.lower():
issues.append('Possible nested loop performance issue')
if 'time.sleep' in content:
issues.append('Synchronous sleep detected')
return issues
def _calculate_maintainability(self, content: str) -> float:
"""保守性スコア計算(簡易版)"""
lines = content.splitlines()
comment_lines = sum(1 for line in lines if line.strip().startswith('#'))
total_lines = len([line for line in lines if line.strip()])
if total_lines == 0:
return 0.0
comment_ratio = comment_lines / total_lines
complexity = self._calculate_complexity(content)
complexity_penalty = min(complexity / 100, 0.5)
return max(0.0, min(1.0, comment_ratio * 0.5 + (1 - complexity_penalty)))
def _estimate_test_coverage(self, file_path: str) -> float:
"""テストカバレッジ推定(簡易版)"""
test_file_patterns = ['test_', '_test.py', 'tests/', 'spec/']
project_root = Path(file_path).parent
# テストファイル検索
test_files = []
for pattern in test_file_patterns:
test_files.extend(list(project_root.rglob(f'*{pattern}*')))
if not test_files:
return 0.0
# 簡易的なカバレッジ推定
return min(1.0, len(test_files) / 10) # 10ファイルあたり100%と仮定
if __name__ == "__main__":
import os
server = AdvancedMCPServer()
server.run(host="localhost", port=int(os.getenv("MCP_PORT", 8000)))
MCPサーバー設定ファイル¶
// ~/.claude/mcp_servers.json
{
"mcpServers": {
"advanced-development-tools": {
"command": "python",
"args": ["advanced_mcp_server.py"],
"env": {
"GITHUB_TOKEN": "${GITHUB_TOKEN}",
"DATABASE_URL": "${DATABASE_URL}",
"MCP_PORT": "8001"
}
},
"github-official": {
"command": "npx",
"args": ["@modelcontextprotocol/server-github"],
"env": {
"GITHUB_PERSONAL_ACCESS_TOKEN": "${GITHUB_TOKEN}"
}
},
"filesystem-tools": {
"command": "npx",
"args": ["@modelcontextprotocol/server-filesystem", "/path/to/project"],
"env": {}
}
}
}
パフォーマンス最適化テクニック¶
Claude Sonnet 4最適化設定¶
# claude_optimization.py
import asyncio
from typing import List, Dict, Any
import time
class ClaudeOptimizer:
def __init__(self):
self.request_cache = {}
self.rate_limiter = RateLimiter(requests_per_minute=50)
async def optimized_batch_request(self, prompts: List[str]) -> List[Dict[str, Any]]:
"""バッチリクエスト最適化"""
# 類似プロンプトをグループ化
grouped_prompts = self._group_similar_prompts(prompts)
results = []
for group in grouped_prompts:
# レート制限チェック
await self.rate_limiter.acquire()
# キャッシュチェック
cache_key = self._generate_cache_key(group)
if cache_key in self.request_cache:
results.extend(self.request_cache[cache_key])
continue
# 並列実行で効率化
batch_result = await self._execute_parallel_request(group)
self.request_cache[cache_key] = batch_result
results.extend(batch_result)
return results
def _group_similar_prompts(self, prompts: List[str]) -> List[List[str]]:
"""類似プロンプトをグループ化"""
# 簡易的な類似度判定
groups = []
for prompt in prompts:
added_to_group = False
for group in groups:
if self._calculate_similarity(prompt, group[0]) > 0.7:
group.append(prompt)
added_to_group = True
break
if not added_to_group:
groups.append([prompt])
return groups
def _calculate_similarity(self, text1: str, text2: str) -> float:
"""テキスト類似度計算"""
words1 = set(text1.lower().split())
words2 = set(text2.lower().split())
intersection = words1.intersection(words2)
union = words1.union(words2)
return len(intersection) / len(union) if union else 0.0
async def _execute_parallel_request(self, prompts: List[str]) -> List[Dict[str, Any]]:
"""並列リクエスト実行"""
tasks = [self._single_request(prompt) for prompt in prompts]
return await asyncio.gather(*tasks)
async def _single_request(self, prompt: str) -> Dict[str, Any]:
"""単一リクエスト実行"""
# Claude APIコール(実装例)
# 実際のAPIコールをここに実装
await asyncio.sleep(0.1) # API呼び出しシミュレーション
return {"prompt": prompt, "response": "Generated response", "tokens": 100}
class RateLimiter:
def __init__(self, requests_per_minute: int):
self.requests_per_minute = requests_per_minute
self.requests = []
async def acquire(self):
"""レート制限取得"""
now = time.time()
# 1分以内のリクエストをフィルタ
self.requests = [req_time for req_time in self.requests if now - req_time < 60]
if len(self.requests) >= self.requests_per_minute:
sleep_time = 60 - (now - self.requests[0])
await asyncio.sleep(sleep_time)
self.requests.append(now)
実戦トラブルシューティング¶
よくある問題と解決法¶
#!/bin/bash
# troubleshooting_toolkit.sh
# Claude Code診断スクリプト
diagnose_claude_code() {
echo "🔍 Claude Code診断開始..."
# 認証状態確認
if ! claude-code auth status; then
echo "❌ 認証エラー: 再認証が必要です"
echo "解決方法: claude-code auth login"
return 1
fi
# 設定ファイル確認
config_file="$HOME/.claude/config.json"
if [ ! -f "$config_file" ]; then
echo "❌ 設定ファイルが見つかりません: $config_file"
echo "解決方法: claude-code config init"
return 1
fi
# JSON設定検証
if ! python -m json.tool "$config_file" > /dev/null 2>&1; then
echo "❌ 設定ファイルのJSON形式が無効です"
echo "解決方法: 設定ファイルを修正するか、claude-code config reset"
return 1
fi
# MCP接続確認
if claude-code mcp list | grep -q "No servers"; then
echo "⚠️ MCPサーバーが設定されていません"
echo "推奨: MCPサーバーを設定してください"
else
echo "✅ MCPサーバー設定を確認"
claude-code mcp diagnose
fi
# リソース使用量確認
memory_usage=$(ps -o pid,ppid,cmd,%mem --sort=-%mem | grep claude-code | head -5)
if [ -n "$memory_usage" ]; then
echo "📊 メモリ使用量:"
echo "$memory_usage"
fi
echo "✅ Claude Code診断完了"
}
# GitHub Copilot診断
diagnose_copilot() {
echo "🔍 GitHub Copilot診断開始..."
# GitHub CLI認証確認
if ! gh auth status > /dev/null 2>&1; then
echo "❌ GitHub CLI認証エラー"
echo "解決方法: gh auth login"
return 1
fi
# Copilot拡張確認
if ! gh extension list | grep -q "gh-copilot"; then
echo "❌ Copilot拡張がインストールされていません"
echo "解決方法: gh extension install github/gh-copilot"
return 1
fi
# Copilot Agent設定確認
if ! gh copilot config get model; then
echo "⚠️ Copilotモデル設定を確認してください"
echo "推奨: gh copilot config set model claude-sonnet-4"
fi
# API制限確認
api_limit=$(gh api rate_limit | jq '.rate.remaining')
if [ "$api_limit" -lt 100 ]; then
echo "⚠️ GitHub APIレート制限に近づいています: $api_limit requests remaining"
fi
echo "✅ GitHub Copilot診断完了"
}
# ワークフロー診断
diagnose_workflow() {
echo "🔍 GitHub Actionsワークフロー診断開始..."
# ワークフローファイル確認
if [ ! -d ".github/workflows" ]; then
echo "❌ .github/workflowsディレクトリが見つかりません"
return 1
fi
# YAML構文チェック
for workflow in .github/workflows/*.yml .github/workflows/*.yaml; do
if [ -f "$workflow" ]; then
echo "📄 検証中: $workflow"
if ! python -c "import yaml; yaml.safe_load(open('$workflow'))" 2>/dev/null; then
echo "❌ YAML構文エラー: $workflow"
else
echo "✅ YAML構文正常: $workflow"
fi
fi
done
# Secrets確認
echo "🔐 必要なSecretsリスト:"
echo " - GITHUB_TOKEN (通常自動設定)"
echo " - CLAUDE_API_KEY"
# 最新実行結果確認
if command -v gh > /dev/null; then
echo "📊 最新のワークフロー実行結果:"
gh run list --limit 5
fi
echo "✅ ワークフロー診断完了"
}
# メイン実行
main() {
case "$1" in
"claude")
diagnose_claude_code
;;
"copilot")
diagnose_copilot
;;
"workflow")
diagnose_workflow
;;
"all"|"")
diagnose_claude_code
diagnose_copilot
diagnose_workflow
;;
*)
echo "使用方法: $0 [claude|copilot|workflow|all]"
exit 1
;;
esac
}
main "$@"
パフォーマンス監視スクリプト¶
# performance_monitor.py
import json
import time
import psutil
import requests
from datetime import datetime, timedelta
from pathlib import Path
class PerformanceMonitor:
def __init__(self):
self.metrics_file = Path.home() / ".claude" / "performance_metrics.json"
self.metrics_file.parent.mkdir(exist_ok=True)
def collect_metrics(self):
"""パフォーマンスメトリクス収集"""
metrics = {
"timestamp": datetime.now().isoformat(),
"system": {
"cpu_percent": psutil.cpu_percent(interval=1),
"memory_percent": psutil.virtual_memory().percent,
"disk_usage": psutil.disk_usage('/').percent
},
"claude_code": self._get_claude_metrics(),
"github_api": self._check_github_api_status()
}
# メトリクス保存
self._save_metrics(metrics)
return metrics
def _get_claude_metrics(self):
"""Claude Code固有メトリクス"""
claude_processes = []
for proc in psutil.process_iter(['pid', 'name', 'cpu_percent', 'memory_percent']):
if 'claude' in proc.info['name'].lower():
claude_processes.append(proc.info)
return {
"process_count": len(claude_processes),
"total_cpu": sum(p['cpu_percent'] for p in claude_processes),
"total_memory": sum(p['memory_percent'] for p in claude_processes)
}
def _check_github_api_status(self):
"""GitHub API状態確認"""
try:
response = requests.get("https://api.github.com/rate_limit", timeout=5)
if response.status_code == 200:
data = response.json()
return {
"status": "healthy",
"rate_limit_remaining": data['rate']['remaining'],
"rate_limit_reset": data['rate']['reset']
}
except Exception as e:
return {"status": "error", "error": str(e)}
return {"status": "unknown"}
def _save_metrics(self, metrics):
"""メトリクス保存"""
# 既存データ読み込み
if self.metrics_file.exists():
with open(self.metrics_file, 'r') as f:
data = json.load(f)
else:
data = {"metrics": []}
# 新しいメトリクス追加
data["metrics"].append(metrics)
# 古いデータ削除(7日分保持)
cutoff = datetime.now() - timedelta(days=7)
data["metrics"] = [
m for m in data["metrics"]
if datetime.fromisoformat(m["timestamp"]) > cutoff
]
# 保存
with open(self.metrics_file, 'w') as f:
json.dump(data, f, indent=2)
def generate_report(self):
"""パフォーマンスレポート生成"""
if not self.metrics_file.exists():
return "メトリクスデータがありません"
with open(self.metrics_file, 'r') as f:
data = json.load(f)
metrics = data["metrics"]
if not metrics:
return "メトリクスデータがありません"
# 最新24時間のデータ分析
last_24h = datetime.now() - timedelta(hours=24)
recent_metrics = [
m for m in metrics
if datetime.fromisoformat(m["timestamp"]) > last_24h
]
if not recent_metrics:
return "最新のメトリクスデータがありません"
# 統計計算
avg_cpu = sum(m["system"]["cpu_percent"] for m in recent_metrics) / len(recent_metrics)
avg_memory = sum(m["system"]["memory_percent"] for m in recent_metrics) / len(recent_metrics)
claude_metrics = [m["claude_code"] for m in recent_metrics if m["claude_code"]["process_count"] > 0]
avg_claude_processes = sum(m["process_count"] for m in claude_metrics) / len(claude_metrics) if claude_metrics else 0
github_healthy = sum(1 for m in recent_metrics if m["github_api"]["status"] == "healthy")
github_uptime = (github_healthy / len(recent_metrics)) * 100
return f"""
📊 パフォーマンスレポート(過去24時間)
🖥️ システムリソース:
CPU使用率平均: {avg_cpu:.1f}%
メモリ使用率平均: {avg_memory:.1f}%
🤖 Claude Code:
平均プロセス数: {avg_claude_processes:.1f}
🐙 GitHub API:
稼働率: {github_uptime:.1f}%
📈 データポイント数: {len(recent_metrics)}
最終更新: {recent_metrics[-1]["timestamp"]}
"""
if __name__ == "__main__":
import sys
monitor = PerformanceMonitor()
if len(sys.argv) > 1 and sys.argv[1] == "report":
print(monitor.generate_report())
else:
metrics = monitor.collect_metrics()
print(f"メトリクス収集完了: {metrics['timestamp']}")
運用ベストプラクティス¶
セキュリティ設定¶
# .github/workflows/security-scan.yml
name: Security Scan for AI Development Environment
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
schedule:
- cron: '0 2 * * 0' # 毎週日曜日午前2時
jobs:
security-audit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Secret Scan
run: |
# API キーやトークンの漏洩チェック
if grep -r "claude.*api.*key" . --exclude-dir=.git --include="*.py" --include="*.js" --include="*.yml"; then
echo "❌ Potential API key leak detected"
exit 1
fi
if grep -r "github.*token" . --exclude-dir=.git --include="*.py" --include="*.js" --include="*.yml"; then
echo "❌ Potential GitHub token leak detected"
exit 1
fi
- name: Dependency Audit
run: |
# Python依存関係脆弱性チェック
if [ -f "requirements.txt" ]; then
pip install safety
safety check -r requirements.txt
fi
# Node.js依存関係脆弱性チェック
if [ -f "package.json" ]; then
npm audit --audit-level high
fi
- name: Claude Code Configuration Audit
run: |
# Claude Code設定の安全性チェック
config_file="$HOME/.claude/config.json"
if [ -f "$config_file" ]; then
# デバッグモード無効化確認
if grep -q '"debug": true' "$config_file"; then
echo "⚠️ Debug mode is enabled in production"
fi
# 適切な権限設定確認
permissions=$(stat -c %a "$config_file")
if [ "$permissions" != "600" ]; then
echo "⚠️ Configuration file permissions are too permissive: $permissions"
fi
fi
まとめ¶
Claude Sonnet 4とGitHub Copilot Agentの実装では、以下の点が重要です:
- 段階的導入: 小規模プロジェクトから開始し、徐々に機能を拡張
- 監視体制: パフォーマンスメトリクスとエラーログの継続的監視
- セキュリティ: API キーの適切な管理と権限設定の最小化
- 最適化: バッチ処理とキャッシュ活用による効率化
この実装ガイドにより、理論だけでなく実際に動作する環境を構築できるはずです。
関連記事¶
- Claude Sonnet 4 × GitHub Copilot Agent基礎ガイド - 概要と基本概念
- MCP統合開発環境完全ガイド - MCPプロトコル詳細実装
- AI開発環境セキュリティベストプラクティス - セキュリティ対策