# 通知設計書 126-notify (RepositoryCheckMailer)

## 概要

本ドキュメントは、GitLabにおける「リポジトリチェック失敗通知」メールの設計を記載します。定期的なリポジトリ整合性チェックで失敗したプロジェクトがある場合に、管理者に通知されるメールです。

### 本通知の処理概要

本通知は、GitLabのリポジトリ整合性チェック（Repository Check）機能が定期的に実行され、1つ以上のプロジェクトでチェックが失敗した場合に、すべてのアクティブな管理者に通知を送信する機能です。

**業務上の目的・背景**：GitLabは大量のGitリポジトリを管理しており、ディスク障害やデータ破損によりリポジトリが破損する可能性があります。リポジトリチェック機能は、`git fsck`などを使用してリポジトリの整合性を定期的に検証します。本通知は、問題が検出された場合に管理者に即座に知らせ、データ損失を防ぐための早期対応を可能にします。

**通知の送信タイミング**：`AdminEmailWorker`（Cronjob）が定期的に実行され、`repository_checks_enabled`設定が有効で、かつリポジトリチェックに失敗したプロジェクトが1つ以上存在する場合に同期送信されます。

**通知の受信者**：すべてのアクティブな管理者（`User.admins.active`）のメールアドレスに送信されます。

**通知内容の概要**：失敗したプロジェクトの数と、管理画面で詳細を確認するためのリンクが含まれます。

**期待されるアクション**：管理者は、管理画面でリポジトリチェックに失敗したプロジェクトを確認し、必要に応じてバックアップからの復元、リポジトリの修復、または問題のあるプロジェクトのオーナーへの連絡を行います。

## 通知種別

メール（Email）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期（`deliver_now`） |
| 優先度 | 高（インフラ関連アラート） |
| リトライ | なし（同期送信のため） |

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

`User.admins.active.pluck(:email)`により、すべてのアクティブな管理者のメールアドレスを取得して送信します。ブロックされた管理者は除外されます。

## 通知テンプレート

### メール通知の場合

| 項目 | 内容 |
|-----|------|
| 送信元アドレス | `Gitlab.config.gitlab.email_from` |
| 送信元名称 | `Gitlab.config.gitlab.email_display_name` |
| 件名 | `GitLab Admin \| {失敗メッセージ}` |
| 形式 | HTML/テキスト（マルチパート） |

### 件名パターン

- 単数形: `GitLab Admin | One project failed its last repository check`
- 複数形: `GitLab Admin | {N} projects failed their last repository check`

### 本文テンプレート

**HTML版:**
```html
<p>{失敗メッセージ}.</p>
<p>
  <a href="{管理画面URL}">See the affected projects in the GitLab admin panel</a>
</p>
<p>You are receiving this message because you are a GitLab administrator for {GitLab URL}.</p>
```

**テキスト版:**
```
{失敗メッセージ}.

View details: {管理画面URL}

You are receiving this message because you are a GitLab administrator for {GitLab URL}.
```

### 添付ファイル

| ファイル名 | 形式 | 条件 | 説明 |
|----------|------|------|------|
| なし | - | - | 本通知には添付ファイルはありません |

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| @message | 失敗メッセージ | failed_countから生成 | Yes |
| failed_count | 失敗したプロジェクト数 | Project.last_repository_check_failed.count | Yes |
| Gitlab.config.gitlab.url | GitLabインスタンスURL | 設定ファイル | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| Cronjob | AdminEmailWorker#perform | repository_checks_enabledかつfailed_count > 0 | 定期的なバックグラウンドジョブ |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| `repository_checks_enabled`が無効 | インスタンス設定でリポジトリチェックが無効化されている場合 |
| 失敗プロジェクト数が0 | すべてのプロジェクトが正常にチェックをパスした場合 |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[AdminEmailWorker Cronjob実行] --> B{repository_checks_enabled?}
    B -->|No| C[処理終了]
    B -->|Yes| D[Project.last_repository_check_failed.count取得]
    D --> E{failed_count > 0?}
    E -->|No| F[処理終了]
    E -->|Yes| G[RepositoryCheckMailer.notify.deliver_now]
    G --> H[メール送信（全アクティブ管理者）]
    H --> I[終了]
```

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

### 参照テーブル一覧

| テーブル名 | 用途 | 備考 |
|-----------|------|------|
| projects | 失敗プロジェクト数のカウント | last_repository_check_failed |
| users | 管理者メールアドレス取得 | admin, state, email |
| application_settings | リポジトリチェック設定 | repository_checks_enabled |

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

#### projects

| 参照項目（カラム名） | 用途 | 取得条件 |
|-------------------|------|---------|
| last_repository_check_failed | 失敗フラグ | スコープで条件抽出 |

#### users

| 参照項目（カラム名） | 用途 | 取得条件 |
|-------------------|------|---------|
| email | 送信先メールアドレス | admin=true AND state=active |

### 更新テーブル一覧

| テーブル名 | 操作 | 概要 |
|-----------|------|------|
| なし | - | メール送信のみで、DB更新は行わない |

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| 送信失敗 | SMTPサーバー接続エラー | Workerがリトライ（Sidekiqリトライ設定に依存） |
| 管理者不在 | アクティブな管理者がいない | メールは空の宛先リストで送信されるが、通常はエラーにならない |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | AdminEmailWorkerのSidekiq設定に依存 |
| リトライ間隔 | Sidekiqデフォルト |
| リトライ対象エラー | Worker実行時のエラー |

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 1分あたり上限 | 制限なし |
| 1日あたり上限 | Cronjobの実行頻度に依存 |

### 配信時間帯

Cronjobのスケジュールに従う

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

- 管理者のみに送信されるため、機密性の高いインフラ情報の漏洩リスクは低い
- 管理画面へのリンクは認証が必要
- 失敗したプロジェクトの詳細情報（名前など）はメールに含まれない

## 備考

- 失敗メッセージは単数形（"One project"）と複数形（"{N} projects"）で切り替わる
- メールの言語はI18n.default_localeに従う（各管理者の言語設定は使用されない）
- EE版では`render_if_exists 'shared/additional_email_text'`で追加テキストが表示される可能性がある

---

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

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

### 推奨読解順序

#### Step 1: Workerの実装を理解する

通知のトリガーとなるAdminEmailWorkerを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | admin_email_worker.rb | `app/workers/admin_email_worker.rb` | `perform`メソッド、送信条件 |

**主要処理フロー**:
1. **行16-18**: `perform`メソッドで`repository_checks_enabled`をチェック
2. **行22-27**: `send_repository_check_mail`で失敗数を取得しメール送信

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | repository_check_mailer.rb | `app/mailers/repository_check_mailer.rb` | `notify`メソッド、メッセージ生成 |

**主要処理フロー**:
1. **行9-21**: `notify`メソッドの定義
2. **行10-15**: `failed_count`に応じたメッセージ生成（単数/複数形）
3. **行17-19**: 管理者メールアドレス取得と件名設定

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | notify.html.haml | `app/views/repository_check_mailer/notify.html.haml` | HTML版メールテンプレート |
| 3-2 | notify.text.haml | `app/views/repository_check_mailer/notify.text.haml` | テキスト版メールテンプレート |

**主要処理フロー（HTML版）**:
- **行1-2**: 失敗メッセージの表示
- **行4-5**: 管理画面へのリンク
- **行7-8**: 受信理由の説明

#### Step 4: テストから仕様を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | repository_check_mailer_spec.rb | `spec/mailers/repository_check_mailer_spec.rb` | テストケース |

**主要処理フロー**:
- **行9-14**: 全管理者への送信検証
- **行16-24**: I18n.default_localeでの送信検証
- **行26-34**: ブロック管理者除外の検証
- **行36-40**: 失敗数に応じた件名検証

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

```
Sidekiq (Cronjob)
    │
    └─ AdminEmailWorker#perform
           │
           ├─ repository_checks_enabled? チェック
           │
           └─ send_repository_check_mail
                  │
                  ├─ Project.last_repository_check_failed.count
                  │
                  └─ RepositoryCheckMailer.notify(failed_count).deliver_now
                         │
                         ├─ メッセージ生成（単数/複数形）
                         │
                         ├─ User.admins.active.pluck(:email)
                         │
                         └─ mail_with_locale
                                └─ テンプレートレンダリング
                                       ├─ notify.html.haml
                                       └─ notify.text.haml
```

### データフロー図

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

Cronjobスケジュール
          ───▶  AdminEmailWorker
                              │
                              ▼
                        repository_checks_enabled?
                              │
                              ▼
                        Project.last_repository_check_failed.count
                              │
                              ▼
                        RepositoryCheckMailer
                        .notify(failed_count)
                        .deliver_now    ───▶  メール送信
                              │               (全アクティブ管理者)
                              ▼
                        User.admins.active
                        .pluck(:email)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| admin_email_worker.rb | `app/workers/admin_email_worker.rb` | ソース | Cronjobワーカー |
| repository_check_mailer.rb | `app/mailers/repository_check_mailer.rb` | ソース | RepositoryCheckメーラー |
| notify.html.haml | `app/views/repository_check_mailer/notify.html.haml` | テンプレート | HTML版メールテンプレート |
| notify.text.haml | `app/views/repository_check_mailer/notify.text.haml` | テンプレート | テキスト版メールテンプレート |
| repository_check_mailer_spec.rb | `spec/mailers/repository_check_mailer_spec.rb` | テスト | メーラーのテスト |
| admin_email_worker_spec.rb | `spec/workers/admin_email_worker_spec.rb` | テスト | ワーカーのテスト |
