# 通知設計書 26-GitHub Webhook

## 概要

本ドキュメントは、GitHubリポジトリからのイベント（Issue、PR、Discussion等）を受信し、Giselleのワークフローをトリガーする「GitHub Webhook」の設計仕様を定義する。外部サービスからの通知を受け取り、自動化されたAIワークフローを起動するための連携機能である。

### 本通知の処理概要

GitHub Webhookは、GitHubリポジトリで発生したイベント（Issue作成、PR作成、コメント追加等）をHTTPリクエストとして受信し、Giselleのワークフローを自動的にトリガーする機能である。GitHub Appとして連携し、指定されたイベントに応じてAIワークフローを実行する。

**業務上の目的・背景**：ソフトウェア開発において、GitHubは中心的なコラボレーションプラットフォームである。Issue、Pull Request、Discussionなどで発生するイベントに対して、AIを活用した自動対応を行うことで、開発者の生産性向上と迅速な対応が可能となる。例えば、新しいIssueが作成された際にAIが自動的に分類・対応する、PRが作成された際にコードレビューを支援する、特定のコメントに対してAIが応答するなどのユースケースが実現できる。GitHub Webhookは、これらの自動化を実現するための入口となる重要なコンポーネントである。

**通知の送信タイミング**：GitHubリポジトリで対象イベントが発生した際に、GitHubからGiselleのWebhookエンドポイントへHTTP POSTリクエストが送信される。対応するイベントは、issues.opened、issues.closed、issues.labeled、issue_comment.created、pull_request.opened、pull_request.ready_for_review、pull_request.closed、pull_request.labeled、pull_request_review_comment.created、discussion.created、discussion_comment.createdの11種類である。

**通知の受信者**：Giselleのサーバーサイドで受信し、対応するワークフローをトリガーする。ワークフローの実行結果は、GitHubのIssue、PR、Discussionにコメントとして投稿される。結果としてGitHubユーザーがその通知を受け取ることになる。

**通知内容の概要**：Webhookペイロードには、イベント種別、リポジトリ情報、Issue/PR/Discussion本体の情報、コメント内容、ユーザー情報などが含まれる。これらの情報はGiselleワークフローへの入力として使用される。

**期待されるアクション**：Giselleはイベントを受信すると、設定されたトリガー条件と照合し、条件に合致する場合はワークフローを実行する。実行中は対象のIssue/PR/Discussionに進捗コメントを投稿し、完了後に結果をコメントとして返信する。

## 通知種別

Webhook（HTTP POST）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期（HTTPリクエスト受信後、非同期でワークフロー実行） |
| 優先度 | 高 |
| リトライ | GitHubによる自動リトライ（失敗時） |

### 送信先決定ロジック

- GitHubリポジトリに設定されたWebhook URLへGitHubが送信
- Giselleは受信後、repositoryNodeIdに基づいて関連するワークフローを検索
- トリガー設定（イベントタイプ、callsign、labels等）に合致するワークフローを実行

## 通知テンプレート

### Webhook受信の場合

| 項目 | 内容 |
|-----|------|
| HTTPメソッド | POST |
| Content-Type | application/json |
| 認証 | Webhook Secret（HMAC-SHA256署名） |
| ヘッダー | X-GitHub-Event, X-GitHub-Delivery, X-Hub-Signature-256 |

### Webhookペイロード構造

```json
{
  "action": "opened | created | closed | labeled | ready_for_review",
  "repository": {
    "node_id": "R_xxxx",
    "owner": { "login": "owner-name" },
    "name": "repo-name"
  },
  "installation": {
    "id": 12345
  },
  "issue": { ... },
  "pull_request": { ... },
  "discussion": { ... },
  "comment": { ... },
  "label": { ... }
}
```

### 添付ファイル

| ファイル名 | 形式 | 条件 | 説明 |
|----------|------|------|------|
| なし | - | - | Webhookのため添付ファイルなし |

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| repository.node_id | リポジトリの一意識別子 | Webhookペイロード | Yes |
| installation.id | GitHub App InstallationのID | Webhookペイロード | Yes |
| event.name | イベント名（issues.opened等） | HTTPヘッダー | Yes |
| event.payload | イベントの詳細情報 | リクエストボディ | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| GitHub | issues.opened | github.issue.created | Issueが新規作成された |
| GitHub | issues.closed | github.issue.closed | Issueがクローズされた |
| GitHub | issues.labeled | github.issue.labeled | Issueにラベルが追加された |
| GitHub | issue_comment.created | github.issue_comment.created | Issueにコメントが追加された |
| GitHub | issue_comment.created | github.pull_request_comment.created | PRにコメントが追加された |
| GitHub | pull_request.opened | github.pull_request.opened | PRが新規作成された |
| GitHub | pull_request.ready_for_review | github.pull_request.ready_for_review | PRがレビュー準備完了になった |
| GitHub | pull_request.closed | github.pull_request.closed | PRがクローズされた |
| GitHub | pull_request.labeled | github.pull_request.labeled | PRにラベルが追加された |
| GitHub | pull_request_review_comment.created | github.pull_request_review_comment.created | PRレビューコメントが追加された |
| GitHub | discussion.created | github.discussion.created | Discussionが新規作成された |
| GitHub | discussion_comment.created | github.discussion_comment.created | Discussionにコメントが追加された |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| 署名検証失敗 | X-Hub-Signature-256の検証に失敗した場合 |
| リポジトリ未登録 | repositoryNodeIdに対応する統合設定が存在しない場合 |
| トリガー無効 | trigger.enable = false の場合 |
| Callsign不一致 | コメントイベントでcallsignが設定と一致しない場合 |
| Label不一致 | labeledイベントで対象ラベルが設定と一致しない場合 |

## 処理フロー

### 受信フロー

```mermaid
flowchart TD
    A[GitHub Webhookリクエスト受信] --> B[署名検証]
    B -->|失敗| C[401 Unauthorized]
    B -->|成功| D[ペイロード解析]
    D --> E[repositoryNodeIdでIntegration検索]
    E -->|見つからない| F[処理スキップ]
    E -->|見つかった| G[関連トリガーを取得]
    G --> H[各トリガーに対してイベント処理]
    H --> I{イベントタイプ判定}
    I -->|issues| J[handleIssue系]
    I -->|pull_request| K[handlePullRequest系]
    I -->|discussion| L[handleDiscussion系]
    J --> M{トリガー条件合致?}
    K --> M
    L --> M
    M -->|No| N[スキップ]
    M -->|Yes| O[リアクション追加]
    O --> P[進捗コメント投稿]
    P --> Q[ワークフロー実行]
    Q --> R[結果コメント更新]
    R --> S[終了]
    N --> S
    F --> S
    C --> S
```

## データベース参照・更新仕様

### 参照テーブル一覧

| テーブル名 | 用途 | 備考 |
|-----------|------|------|
| github_repository_integration_index | リポジトリとワークフローの紐付け | repositoryNodeIdで検索 |
| triggers | トリガー設定 | flowTriggerIdで検索 |
| workspaces | ワークスペース情報 | workspaceIdで検索 |

### テーブル別参照項目詳細

#### github_repository_integration_index

| 参照項目（カラム名） | 用途 | 取得条件 |
|-------------------|------|---------|
| repositoryNodeId | リポジトリ識別 | WHERE repositoryNodeId = {payload.repository.node_id} |
| flowTriggerIds | 関連トリガー一覧 | - |

#### triggers

| 参照項目（カラム名） | 用途 | 取得条件 |
|-------------------|------|---------|
| enable | トリガー有効/無効 | - |
| configuration | イベント設定、条件設定 | - |
| workspaceId | ワークスペース参照 | - |
| nodeId | トリガーノード参照 | - |

### 更新テーブル一覧

| テーブル名 | 操作 | 概要 |
|-----------|------|------|
| tasks | INSERT | タスク作成 |
| generations | INSERT/UPDATE | 生成処理の記録 |

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| 署名検証エラー | Webhook SecretのHMAC検証失敗 | 401レスポンス、ログ記録 |
| 認証情報不足 | GitHub authV2設定が存在しない | エラースロー、処理中断 |
| リポジトリ未登録 | Integration設定が見つからない | 処理スキップ（正常終了） |
| ワークフロー実行エラー | タスク実行中のエラー | エラーログ記録、次のトリガーは継続 |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | GitHub側のリトライポリシーに依存 |
| リトライ間隔 | GitHub側で管理 |
| リトライ対象エラー | 5xxエラー、タイムアウト |

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 1分あたり上限 | GitHubのWebhook配信レートに依存 |
| 1日あたり上限 | なし |

### 配信時間帯

制限なし（24時間、GitHubイベント発生時に即時配信）

## セキュリティ考慮事項

- Webhook Secretを使用したHMAC-SHA256署名検証を必須とする
- 署名検証に失敗した場合は401 Unauthorizedを返し、処理を中断する
- GitHub App認証情報（appId、privateKey、installationId）は環境変数で安全に管理する
- Webhookエンドポイントは公開されるが、署名検証により不正リクエストを排除する
- ワークフロー実行ログには機密情報を含めない

## 備考

- 実装ファイル: `packages/giselle/src/github/handle-webhook-v2.ts`
- イベントハンドラー: `packages/giselle/src/github/event-handlers.ts`
- Webhook共通処理: `packages/github-tool/src/webhooks.ts`
- コマンドパース: `packages/giselle/src/github/utils.ts`
- GitHub Appインストレーションベースの認証を使用
- 進捗表示にテーブル形式のコメントを使用

---

## コードリーディングガイド

本通知を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

まず、Webhookイベントの型定義を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | webhooks.ts | `packages/github-tool/src/webhooks.ts` | WebhookEvent型（15-18行目）でイベント構造を確認 |
| 1-2 | webhooks.ts | `packages/github-tool/src/webhooks.ts` | ensureWebhookEvent関数（20-25行目）で型ガードを確認 |

**読解のコツ**: @octokit/webhooksのEmitterWebhookEventを基にした型定義を理解する。

#### Step 2: エントリーポイントを理解する

Webhook受信のエントリーポイントを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | handle-webhook-v2.ts | `packages/giselle/src/github/handle-webhook-v2.ts` | handleGitHubWebhookV2関数（39-93行目）がエントリーポイント |

**主要処理フロー**:
1. **46-49行目**: GitHub認証情報の取得、存在確認
2. **50-75行目**: dispatch関数の定義（イベントをprocess関数に委譲）
3. **77-86行目**: 各イベント名に対してdispatch関数をハンドラーとして登録
4. **88-92行目**: handleWebhook関数で署名検証とイベント受信

#### Step 3: イベント処理を理解する

process関数とイベントハンドラーの処理を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | handle-webhook-v2.ts | `packages/giselle/src/github/handle-webhook-v2.ts` | process関数（125-192行目）でイベント処理の流れを確認 |
| 3-2 | event-handlers.ts | `packages/giselle/src/github/event-handlers.ts` | 各イベントハンドラー（handleIssueOpened等）で条件判定を確認 |

**主要処理フロー**:
- **133-135行目**: ペイロードの必須プロパティチェック
- **137-149行目**: repositoryNodeIdでIntegration設定を検索
- **151-191行目**: 各flowTriggerIdに対してprocessEventを実行

#### Step 4: イベントハンドラー詳細を理解する

個別イベントの処理ロジックを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | event-handlers.ts | `packages/giselle/src/github/event-handlers.ts` | handleIssueOpened（165-181行目）でIssue作成イベントを確認 |
| 4-2 | event-handlers.ts | `packages/giselle/src/github/event-handlers.ts` | handleIssueCommentCreated（201-227行目）でcallsign判定を確認 |
| 4-3 | event-handlers.ts | `packages/giselle/src/github/event-handlers.ts` | processEvent（478-814行目）でタスク実行と進捗更新を確認 |

**主要処理フロー**:
- **507-523行目**: イベントハンドラー配列をループし条件合致を判定
- **517-523行目**: リアクション追加（EYES絵文字）
- **562-689行目**: 進捗コメント投稿とタスク実行
- **807-812行目**: 完了コメント更新

#### Step 5: コマンドパースを理解する

コメント内のコマンド（/callsign）のパース処理を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | utils.ts | `packages/giselle/src/github/utils.ts` | parseCommand関数（162-185行目）でコマンドパースを確認 |

**主要処理フロー**:
- **164-165行目**: 改行を正規化し行分割
- **167-171行目**: 1行目から/で始まるコマンドを抽出
- **174-179行目**: callsignと残りのcontentを分離

### プログラム呼び出し階層図

```
handleGitHubWebhookV2 (handle-webhook-v2.ts)
    |
    +-- handleWebhook (github-tool/webhooks.ts)
    |     +-- verifyRequest (署名検証)
    |     +-- createEventHandler
    |     +-- eventHandler.receive
    |
    +-- dispatch (内部関数)
          |
          +-- process (handle-webhook-v2.ts)
                |
                +-- hasRequiredPayloadProps (型ガード)
                +-- getGitHubRepositoryIntegrationIndex
                +-- getTrigger
                |
                +-- processEvent (event-handlers.ts)
                      |
                      +-- eventHandlers[] (ハンドラー配列)
                      |     +-- handleIssueOpened
                      |     +-- handleIssueClosed
                      |     +-- handleIssueCommentCreated
                      |     +-- handlePullRequestOpened
                      |     +-- handleDiscussionCreated
                      |     +-- ...
                      |
                      +-- addReaction (リアクション追加)
                      +-- createIssueComment / createPullRequestComment
                      +-- createAndStartTask (タスク実行)
                      |     +-- sequenceStart callback
                      |     +-- sequenceComplete callback
                      |     +-- sequenceFail callback
                      |
                      +-- updateIssueComment / updatePullRequestReviewComment
```

### データフロー図

```
[入力]                           [処理]                              [出力]

GitHub Webhook ───────────> handleGitHubWebhookV2
(HTTP POST)                        |
                                   v
                            署名検証 (HMAC-SHA256)
                                   |
                                   v
                            ペイロード解析
                                   |
                                   v
                            Integration検索 ──────> DB参照
                            (repositoryNodeId)
                                   |
                                   v
                            トリガー取得 ──────────> DB参照
                                   |
                                   v
                            イベントハンドラー選択
                                   |
                                   v
                            条件判定 (callsign, labels)
                                   |
                                   v
                +------------------+------------------+
                |                  |                  |
                v                  v                  v
         Issue系          PullRequest系        Discussion系
                |                  |                  |
                +------------------+------------------+
                                   |
                                   v
                            リアクション追加 ────> GitHub API
                                   |
                                   v
                            進捗コメント投稿 ────> GitHub API
                                   |
                                   v
                            タスク実行
                            (Giselleワークフロー)
                                   |
                                   v
                            結果コメント更新 ────> GitHub API
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| handle-webhook-v2.ts | `packages/giselle/src/github/handle-webhook-v2.ts` | ソース | Webhookエントリーポイント |
| event-handlers.ts | `packages/giselle/src/github/event-handlers.ts` | ソース | イベントハンドラー定義 |
| utils.ts | `packages/giselle/src/github/utils.ts` | ソース | URL解析、コマンドパース |
| webhooks.ts | `packages/github-tool/src/webhooks.ts` | ソース | Webhook署名検証、ハンドラー管理 |
| reactions.ts | `packages/github-tool/src/reactions.ts` | ソース | リアクション追加 |
| issues.ts | `packages/github-tool/src/issues.ts` | ソース | Issueコメント操作 |
| pull-requests.ts | `packages/github-tool/src/pull-requests.ts` | ソース | PRコメント操作 |
| discussions.ts | `packages/github-tool/src/discussions.ts` | ソース | Discussionコメント操作 |
| errors.ts | `packages/github-tool/src/errors.ts` | ソース | エラー定義 |
