# 通知設計書 76-repository_push_email

## 概要

本ドキュメントは、GitLabリポジトリへのプッシュがあった際に送信されるメール通知 `repository_push_email` の設計仕様を定義する。

### 本通知の処理概要

本通知は、プロジェクトのGitリポジトリへのプッシュ操作（新規ブランチ作成、コミットのプッシュ、ブランチ削除、タグ操作等）があった際に、設定されたメールアドレスに通知するメール機能を提供する。

**業務上の目的・背景**：リポジトリへのプッシュは、コードベースの変更を意味する重要なイベントである。チームメンバーやCI/CDシステムが変更を追跡するために、プッシュイベントをメールで通知することで、コードレビューの開始、デプロイの準備、変更内容の確認などのアクションを促すことができる。この機能は「Emails on Push」インテグレーションとして提供される。

**通知の送信タイミング**：リポジトリへのプッシュ操作が検出された際に、Emails on Pushインテグレーションが有効になっているプロジェクトで送信される。

**通知の受信者**：Emails on Pushインテグレーションで設定されたメールアドレス（複数指定可能）に送信される。プロジェクト単位で受信者を設定できる。

**通知内容の概要**：プッシュの作者、対象ブランチ/タグ、コミット情報、変更されたファイル一覧、差分（オプション）を含む詳細な通知メールである。

**期待されるアクション**：受信者はプッシュ内容を確認し、必要に応じてコードレビュー、テスト実行、デプロイ作業などのフォローアップアクションを実行する。

## 通知種別

メール通知

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 非同期（deliver_later） |
| 優先度 | 中 |
| リトライ | Sidekiqのデフォルトリトライ機構に従う |

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

Emails on Pushインテグレーションで設定されたメールアドレスに送信される。複数のアドレスをカンマ区切りで指定可能。送信元は、設定により実際のコミッターのメールアドレスを使用することも可能。

## 通知テンプレート

### メール通知の場合

| 項目 | 内容 |
|-----|------|
| 送信元アドレス | GitLabデフォルト または コミッターのメールアドレス |
| 送信元名称 | GitLab |
| 件名 | `[Git][{project_path}][{branch_name}] {commit_count} commits: {first_commit_title}` |
| 形式 | HTML/テキスト |

### 件名パターン

| アクション | 件名例 |
|-----------|--------|
| 通常プッシュ（複数コミット） | `[Git][mygroup/myproject][main] 3 commits: Fix bug in login` |
| 通常プッシュ（単一コミット） | `[Git][mygroup/myproject][main] Fix bug in login` |
| 新規ブランチ作成 | `[Git][mygroup/myproject] Pushed new branch feature-x` |
| ブランチ削除 | `[Git][mygroup/myproject] Deleted branch old-branch` |
| Force Push（コミット削除） | `[Git][mygroup/myproject][main] Deleted 3 commits: Old commit` |

### 本文テンプレート

```html
<h3>
  {author_name} {action_name} {ref_type} {ref_name} at {project_link}
</h3>

<!-- Force Pushの場合の警告 -->
<p>
  <strong>WARNING:</strong> The push did not contain any new commits, but force pushed to delete the commits and changes below.
</p>

<h4>Commits:</h4>
<ul>
  <!-- コミットごとにリスト表示 -->
  <li>
    <strong>{commit_short_id}</strong>
    <div>by {author_name} at {committed_date}</div>
    <pre>{commit_message}</pre>
  </li>
</ul>

<h4>{changed_files_count} changed files:</h4>
<ul>
  <!-- 変更ファイルごとにリスト表示 -->
  <li>
    <!-- 削除/追加/変更に応じたアイコン付き -->
    {file_path}
  </li>
</ul>

<!-- 差分表示（無効でない場合） -->
<h4>Changes:</h4>
<!-- ファイルごとの差分表示 -->
```

### 添付ファイル

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

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| @message | RepositoryPushメッセージオブジェクト | RepositoryPush.new | Yes |
| @message.author_name | プッシュ作者名 | User.name | Yes |
| @message.action_name | アクション名（pushed to/deleted等） | 計算 | Yes |
| @message.ref_type | 参照タイプ（branch/tag） | 計算 | Yes |
| @message.ref_name | ブランチ/タグ名 | Git.ref_name | Yes |
| @message.commits | コミット一覧 | compare.commits | No |
| @message.changed_files | 変更ファイル一覧 | compare.changed_paths | No |
| @message.diffs | 差分情報 | compare.diffs | No |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| Gitフック | post-receive | Emails on Push有効 | プッシュ時にインテグレーション経由で送信 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| インテグレーション無効 | Emails on Pushインテグレーションが無効の場合 |
| 差分表示無効 | disable_diffsオプションで差分を省略可能 |
| 差分サイズ超過 | 差分が大きすぎる場合は「The diff was not included because it is too large.」と表示 |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[リポジトリへのプッシュ] --> B[post-receiveフック実行]
    B --> C{Emails on Push有効?}
    C -->|No| D[終了]
    C -->|Yes| E[RepositoryPushメッセージ作成]
    E --> F[比較情報取得]
    F --> G{差分表示有効?}
    G -->|Yes| H[差分情報取得]
    G -->|No| I[差分スキップ]
    H --> J[メール生成]
    I --> J
    J --> K[設定された宛先に送信]
    K --> L[終了]
```

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

### 参照テーブル一覧

| テーブル名 | 用途 | 備考 |
|-----------|------|------|
| projects | プロジェクト情報取得 | パス、名前の表示 |
| users | ユーザー情報取得 | 作者名、メールアドレス |
| integrations | インテグレーション設定 | Emails on Push設定 |

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

#### projects

| 参照項目（カラム名） | 用途 | 取得条件 |
|-------------------|------|---------|
| id | プロジェクト識別 | パラメータで指定されたproject_id |
| name | プロジェクト名表示 | - |
| full_path | プロジェクトパス表示 | - |

#### integrations（Emails on Push）

| 参照項目（カラム名） | 用途 | 取得条件 |
|-------------------|------|---------|
| recipients | 送信先メールアドレス | - |
| disable_diffs | 差分表示無効フラグ | - |
| send_from_committer_email | コミッターメールから送信 | - |

### 更新テーブル一覧

| テーブル名 | 操作 | 概要 |
|-----------|------|------|
| なし | - | 参照のみ |

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| 送信失敗 | SMTPサーバー接続エラー | Sidekiqによるリトライ |
| 差分取得タイムアウト | 大きな差分の取得に時間がかかる | 「The diff was not included because it is too large.」と表示 |
| 宛先不正 | 無効なメールアドレス | エラーログ記録、該当アドレスはスキップ |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | Sidekiqデフォルト |
| リトライ間隔 | 指数バックオフ |
| リトライ対象エラー | 一時的なネットワークエラー等 |

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 1分あたり上限 | GitLabのデフォルト設定に従う |
| 1日あたり上限 | GitLabのデフォルト設定に従う |

### 配信時間帯

特に制限なし。プッシュ時に即時送信される。

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

- コミット内容が含まれるため、機密情報がコミットされている場合は注意が必要
- 送信先メールアドレスはプロジェクト管理者が設定
- send_from_committer_emailオプションを使用する場合、送信者詐称のリスクに注意

## 備考

- Emails on Pushインテグレーションとして設定される
- 差分表示は設定で無効化可能
- 大きな差分は自動的に省略される
- Force Pushの場合は削除されたコミットの情報が表示される

---

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

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

### 推奨読解順序

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

まず、通知に必要なメッセージオブジェクトを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | repository_push.rb | `lib/gitlab/email/message/repository_push.rb` | RepositoryPushメッセージクラスの全体構造 |

**読解のコツ**:
- コンストラクタで必須パラメータ（author_id, ref, action）を確認
- commits、diffs、changed_filesなどのデータ取得メソッドを確認
- action_name、ref_type、ref_nameなどの計算プロパティを確認

#### Step 2: メーラーを理解する

メール生成処理を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | projects.rb | `app/mailers/emails/projects.rb` | repository_push_emailメソッド（96-113行目） |

**主要処理フロー**:
- **96-113行目**: RepositoryPushオブジェクト作成、ヘッダー設定、メール送信

#### Step 3: ビューテンプレートを理解する

メール本文のテンプレートを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | repository_push_email.html.haml | `app/views/notify/repository_push_email.html.haml` | HTML本文の構造 |

**テンプレート内容**:
- **1-5行目**: ヘッダー（作者、アクション、プロジェクトリンク）
- **7-12行目**: Force Pushの警告表示
- **14-24行目**: コミット一覧の表示
- **26-47行目**: 変更ファイル一覧の表示
- **49-83行目**: 差分の表示（オプション）

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

```
Gitプッシュ操作
    │
    └─ Emails on Pushインテグレーション
           │
           └─ Notify#repository_push_email
                  │
                  ├─ Gitlab::Email::Message::RepositoryPush.new
                  │      ├─ project情報取得
                  │      ├─ author情報取得
                  │      ├─ commits取得
                  │      ├─ diffs取得
                  │      └─ changed_files取得
                  │
                  ├─ add_project_headers
                  │
                  └─ mail_with_locale
                         └─ repository_push_email.html.haml
```

### データフロー図

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

project_id ────────▶ RepositoryPush ──────────────────▶ メール送信
opts (author_id,          │
      ref, action,        ├─ Compare情報
      compare, ...)       │      ├─ commits
                          │      ├─ diffs
                          │      └─ changed_files
                          │
                          └─ Notify (Mailer)
                                 └─ 作者名
                                    アクション
                                    コミット一覧
                                    変更ファイル一覧
                                    差分（オプション）
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| repository_push.rb | `lib/gitlab/email/message/repository_push.rb` | ソース | プッシュメッセージモデル |
| projects.rb | `app/mailers/emails/projects.rb` | ソース | メール生成メーラー |
| repository_push_email.html.haml | `app/views/notify/repository_push_email.html.haml` | テンプレート | HTML本文テンプレート |
| highlighted_diff_email.scss | `app/assets/stylesheets/mailers/highlighted_diff_email.scss` | スタイル | 差分表示用スタイル |
| _email_line.html.haml | `app/views/projects/diffs/_email_line.html.haml` | テンプレート | 差分行表示用パーシャル |
