※以下はClaude 3.7 Sonnetで聞いてみただけの記事なので未検証です。
これから検証するためのメモです。これを見て試して失敗しても責任は負いかねますので
ご了承ください。
このガイドでは、GitHubで何らかの操作(例:イシューの作成)が行われたときに自動的にそれを検知し、その操作を取り消す(ロールバック)するシステムをAWS Lambda、API Gateway、GitHub Webhookを使って構築する方法を詳しく説明します。
目次
1. GitHub個人アクセストークンの作成
GitHub APIを呼び出すには、アクセストークンが必要です。
- GitHubにログイン: あなたのGitHubアカウントにログインします
- 設定ページに移動: 右上のプロフィールアイコンをクリックし、「Settings」を選択
- 開発者設定に移動: 左側のメニューの下部にある「Developer settings」をクリック
- 個人アクセストークンを選択: 「Personal access tokens」→「Tokens (classic)」をクリック
- 新しいトークンを生成: 「Generate new token」→「Generate new token (classic)」をクリック
-
トークンの設定:
- Token name:
GitHubWebhookRollback
など分かりやすい名前 - Expiration: 有効期限(まずは30日程度に設定)
- Select scopes: 最低限以下の権限が必要
-
repo
(リポジトリへのフルアクセス権)
-
- 「Generate token」ボタンをクリック
- Token name:
- トークンをコピー: 生成されたトークンをコピーして安全な場所に保存(この画面を閉じると二度とトークン全体を見ることができません)
2. Lambda関数の作成
-
AWSコンソールにログイン: AWSマネジメントコンソールにログインします
-
Lambda画面に移動: サービス一覧から「Lambda」を選択
-
関数の作成:
- 「関数の作成」ボタンをクリック
- 「一から作成」を選択
- 関数名:
GitHubWebhookHandler
- ランタイム:
Node.js 20.x
- アーキテクチャ:
x86_64
- 「関数の作成」ボタンをクリック
-
Lambda関数のコードを記述:
- 表示されるコードエディタに以下のコードを入力:
const https = require('https');
// 環境変数からGitHubのアクセストークンを取得
const GITHUB_TOKEN = process.env.GITHUB_TOKEN;
exports.handler = async (event) => {
try {
// リクエストボディをパース
const webhookPayload = JSON.parse(event.body);
console.log('Received webhook payload:', JSON.stringify(webhookPayload));
// イベントタイプを確認
const githubEvent = event.headers['X-GitHub-Event'] || event.headers['x-github-event'];
console.log('GitHub Event:', githubEvent);
// リポジトリ情報とアクション情報を取得
const repo = webhookPayload.repository.full_name;
const action = webhookPayload.action;
console.log(`Repository: ${repo}, Action: ${action}`);
// 適切なロールバックアクションを実行
let result;
if (githubEvent === 'issues' && action === 'opened') {
// イシューが作成された場合、そのイシューを閉じる
const issueNumber = webhookPayload.issue.number;
result = await closeIssue(repo, issueNumber);
console.log(`Closed issue #${issueNumber}`);
} else {
console.log(`No rollback action defined for event '${githubEvent}' with action '${action}'`);
result = { message: 'No rollback action performed' };
}
// 成功レスポンスを返す
return {
statusCode: 200,
body: JSON.stringify({
message: 'Webhook processed successfully',
result: result
})
};
} catch (error) {
// エラーログ
console.error('Error processing webhook:', error);
// エラーレスポンスを返す
return {
statusCode: 500,
body: JSON.stringify({
message: 'Error processing webhook',
error: error.message
})
};
}
};
// GitHubのイシューを閉じる関数
async function closeIssue(repo, issueNumber) {
const options = {
hostname: 'api.github.com',
path: `/repos/${repo}/issues/${issueNumber}`,
method: 'PATCH',
headers: {
'User-Agent': 'AWS-Lambda',
'Content-Type': 'application/json',
'Authorization': `token ${GITHUB_TOKEN}`,
'Accept': 'application/vnd.github.v3+json'
}
};
const data = JSON.stringify({
state: 'closed'
});
return new Promise((resolve, reject) => {
const req = https.request(options, (res) => {
let responseBody = '';
res.on('data', (chunk) => {
responseBody += chunk;
});
res.on('end', () => {
if (res.statusCode >= 200 && res.statusCode < 300) {
resolve(JSON.parse(responseBody));
} else {
reject(new Error(`GitHub API responded with status code ${res.statusCode}: ${responseBody}`));
}
});
});
req.on('error', (error) => {
reject(error);
});
req.write(data);
req.end();
});
}
-
環境変数の設定:
- Lambda関数の「設定」タブをクリック
- 「環境変数」セクションを選択し、「編集」ボタンをクリック
- 新しい環境変数を追加:
- キー:
GITHUB_TOKEN
- 値: 先ほど生成したGitHubアクセストークン
- キー:
- 「保存」ボタンをクリック
-
タイムアウトの設定:
- Lambda関数の「設定」タブで、「一般設定」セクションの「編集」ボタンをクリック
- タイムアウトを10秒に設定(デフォルトの3秒だと足りない場合があります)
- 「保存」ボタンをクリック
-
コードのデプロイ
- 「コード」タブから「Deploy」ボタンをクリック
3. API Gatewayの設定
-
API Gatewayコンソールに移動: AWSコンソールのサービス一覧から「API Gateway」を選択
-
APIの作成:
- 「APIを作成」ボタンをクリック
- 「REST API」を選択し、「構築」ボタンをクリック
- 「REST API」が選択されていることを確認
- API名:
GitHubWebhookAPI
- 「APIの作成」ボタンをクリック
-
リソースの作成:
- 「リソースの作成」ボタンをクリック
- リソース名:
webhook
- リソースパス:
/webhook
- 「CORS(Cross-Origin Resource Sharing)の有効化」はチェックしない
- 「リソースの作成」ボタンをクリック
-
メソッドの作成:
- 新しく作成した
/webhook
リソースを選択 - 「メソッドの作成」ボタンをクリック
- ドロップダウンから「POST」を選択し、チェックマークをクリック
- 統合タイプ: 「Lambda関数」
- Lambda関数: 先ほど作成した
GitHubWebhookHandler
を入力(入力中に候補が表示されます) - 「メソッドを作成」ボタンをクリック
- 「Lambda関数に権限を追加することを確認します」というポップアップが表示されたら「OK」をクリック
- 新しく作成した
-
メソッドレスポンスの設定:
- 「メソッドレスポンス」をクリック
- 「レスポンス 200」を編集
- 「ヘッダーの追加」をクリック
- 「Access-Control-Allow-Origin」と入力し、「保存」ボタンをクリック
-
統合レスポンスの設定:
- 「統合レスポンス」をクリック
- 「デフォルト-レスポンス」を編集
- 「ヘッダーマッピング」セクションで「Access-Control-Allow-Origin」の値に「'*'」と入力(シングルクォートを含む)
- 「保存」ボタンをクリック
-
APIのデプロイ:
- 「APIをデプロイ」を選択
- デプロイされるステージ: 「新しいステージ」
- ステージ名:
prod
- 「デプロイ」ボタンをクリック
-
エンドポイントURLの取得:
- デプロイされたAPIの情報が表示される画面で、「URLを呼び出す」に記載されたURLをメモ
- このURLは次のステップのGitHub Webhook設定で使用します
- 例:
https://abcd1234.execute-api.us-east-1.amazonaws.com/prod/webhook
※webhookを末尾に足す
4. GitHub Webhookの設定
- 対象GitHubリポジトリに移動: WebhookでイベントをキャッチしたいGitHubリポジトリのページに移動
- 設定ページに移動: リポジトリページの上部メニューから「Settings」タブをクリック
- Webhookセクションに移動: 左側のメニューから「Webhooks」を選択
-
新しいWebhookを追加:
- 「Add webhook」ボタンをクリック
- Payload URL: API GatewayのエンドポイントURL(
/webhook
まで含む)を入力 - Content type:
application/json
を選択 - Secret: 空のままでも良いですが、セキュリティを強化したい場合は秘密のトークンを入力し、Lambda関数でも対応する必要があります
- どのイベントでWebhookを起動するか:
Let me select individual events
を選択 - 「Issues」にチェックを入れる(イシュー作成イベントをキャッチする場合)
- 「Active」にチェックが入っていることを確認
- 「Add webhook」ボタンをクリック
5. テスト方法
-
イシューを作成:
- GitHubリポジトリページに移動
- 「Issues」タブをクリック
- 「New issue」ボタンをクリック
- タイトルと説明を入力して「Create」ボタンをクリック
-
結果の確認:
- イシューが作成された後、すぐに閉じられる(ロールバックされる)はずです
- イシューリストに戻ると、作成したイシューが「Closed」状態になっていることが確認できます
-
Lambdaログの確認:
- AWSコンソールのLambda関数ページに移動
- 「モニタリング」タブをクリック
- 「ログ」をクリック(CloudWatchログに移動します)
- 最新のログストリームをクリックして、処理の詳細を確認
-
GitHub Webhookの配信履歴確認:
- リポジトリの「Settings」→「Webhooks」に移動
- 設定したWebhookをクリック
- 「Recent Deliveries」セクションでWebhookの配信履歴と結果を確認できます
6. トラブルシューティング
Webhook呼び出しが成功しない場合:
- API GatewayのCORSを確認: 統合レスポンスで正しくCORSヘッダーが設定されているか確認
- Lambda関数の権限を確認: API GatewayからLambda関数を呼び出す権限が付与されているか確認
- GitHubのWebhook設定を確認: ペイロードURLやコンテンツタイプが正しく設定されているか確認
- Lambdaのログを確認: CloudWatchログでエラーメッセージを確認
- GitHub APIの権限を確認: 個人アクセストークンに十分な権限が付与されているか確認
イシューが閉じられない場合:
- GitHubトークンの有効性を確認: トークンが有効であることを確認(期限切れでないか)
- Lambda関数のタイムアウトを確認: 処理が完了する前にタイムアウトしていないか確認
- Webhookペイロードの構造を確認: Lambda関数内でWebhookペイロードが正しくパースされているか確認
拡張方法
このシステムは、イシューのクローズ(取り消し)だけでなく、さまざまなGitHubイベントに対応できるよう拡張できます:
- プルリクエストの自動クローズ: 特定の条件下でプルリクエストを自動的に閉じる
- コメントの自動追加: イシューやプルリクエストに自動的にコメントを追加
- 特定のラベルの追加/削除: 条件に基づいてラベルを追加または削除
- 承認者の自動割り当て: プルリクエストに特定の承認者を自動的に割り当て
Lambda関数のコードを修正することで、これらの機能を実装できます。