GitHub Webhook のローカルテストを使えば、staging にデプロイせずに push、pull request、issue、workflow のイベントを自分のマシンで受け取れます。localhost トンネルを起動し、HTTPS URL を GitHub App かリポジトリの設定に登録し、完全な署名検証つきでハンドラーをデバッグします。
なぜ GitHub Webhook には公開エンドポイントが要るのか
GitHub は Webhook イベントを設定済み URL への HTTP POST として配信します。127.0.0.1 のローカルマシンは GitHub のサーバーから到達できません。localhost トンネルが、GitHub の求める公開 HTTPS エンドポイントを提供します。
GitHub Apps とリポジトリ Webhook
リポジトリ Webhook
Settings → Webhooks でリポジトリごとに設定。機能開発中に単一リポジトリのイベントハンドラーをテストするのに向いています。
GitHub App Webhook
GitHub App 設定でアプリレベルに設定。複数のリポジトリや組織を扱う連携を作るときに必要です。
どちらの配信も X-Hub-Signature-256 ヘッダーによる HMAC-SHA256 署名検証を使います。
手順:GitHub Webhook のローカルテスト
- Webhook エンドポイント(例:
/api/webhooks/github)付きでローカルアプリを起動。 npx portpreview 3000を実行して公開 HTTPS URL を取得。- GitHub で、トンネル URL に Webhook パスを付けたものを payload URL として追加。
- content type を
application/jsonにし、受け取るイベントを選択。 - Webhook secret を生成し、ローカルの環境変数に保存。
- イベントを発火(コミット push、PR を開く、issue 作成)し、配信を確認。
- ハンドラーが署名を検証し、10 秒以内に 2xx を返すことを確認。
GitHub Webhook 署名をローカルで検証
GitHub は各ペイロードを Webhook secret で署名します。ハンドラーは:
- JSON パース前に生のリクエストボディを読む。
- secret を使って HMAC-SHA256 を計算。
X-Hub-Signature-256ヘッダーと定数時間比較で照合。
元のヘッダーを保つトンネルツールなら、本物の検証経路をテストできます。ローカル開発でも署名チェックを飛ばさないでください。
ローカルでテストすべきイベント
push— CI トリガーロジック、ブランチ保護フック、デプロイパイプライン。pull_request— レビュー自動化、ラベルボット、マージチェック。issues— issue トラッカー同期、アサインワークフロー。installation— GitHub App のインストール/アンインストール ライフサイクル。workflow_run— CI 後の自動化とアーティファクト処理。
失敗した GitHub Webhook 配信のデバッグ
GitHub は失敗した配信を指数バックオフで再試行します。ローカルテストでよくある失敗:
- ハンドラーのタイムアウト(GitHub は 10 秒以内の応答を期待)。
- 検証前にボディをパースしたことによる署名不一致。
- GitHub が再試行する間にトンネルセッションが失効。
- イベントフィルター誤り — ハンドラーが処理しないイベントを受け取る。
Webhook リプレイを使えば、新しいコミットを push せずに失敗した配信を再テストできます。
GitHub Webhook テスト vs smee.io
smee.io はローカル開発向けの人気の GitHub Webhook プロキシです。基本的な転送には便利ですが、組み込みのリクエスト確認やリプレイはありません。PortPreview はトンネリングとキャプチャ・リプレイを 1 つのツールにまとめます。より広い Webhook デバッグガイドは Webhook をローカルでデバッグする方法を参照。
組み込みのリクエスト可視性つきの GitHub Webhook テストは PortPreview のウェイトリストへ。
