# バッチ設計書 9-bisect.sh

## 概要

本ドキュメントは、TensorFlowのCI/CDパイプラインにおけるgit bisectデバッグバッチ `bisect.sh` の設計仕様を記述する。

### 本バッチの処理概要

本バッチは、git bisect機能を使用して、CIテスト失敗の原因となったコミットを自動的に特定するバッチである。

**業務上の目的・背景**：大規模プロジェクトであるTensorFlowでは、多数のコミットが頻繁にマージされるため、テスト失敗の原因コミットの特定が困難になることがある。本バッチはgit bisectを自動化し、最後の正常コミットと最初の失敗コミットの間で二分探索を行い、原因コミットを効率的に特定する。これにより、デバッグ時間を大幅に短縮できる。

**バッチの実行タイミング**：CIテストの失敗が検出された後に、開発者が手動で実行する。

**主要な処理内容**：
1. TensorFlowルートディレクトリへの移動
2. `nightly_upload` 環境設定のローカルキャッシュへの置換（安全対策）
3. git bisect の開始（bad/good コミットの指定）
4. git bisect run による自動二分探索（指定スクリプトをテスト実行）

**前後の処理との関連**：`any.sh` と組み合わせて、特定のテストターゲットに対するbisectを実行可能。テスト実行には既存のCIスクリプト（wheel.sh等）を再利用する。

**影響範囲**：ローカルgitリポジトリの作業ツリー（bisect中に各コミットがチェックアウトされる）。

## バッチ種別

デバッグ / 原因特定

## 実行スケジュール

| 項目 | 内容 |
|-----|------|
| 実行頻度 | 随時（手動実行） |
| 実行時刻 | 該当なし |
| 実行曜日 | 該当なし |
| 実行日 | 該当なし |
| トリガー | 開発者による手動実行 |

## 実行条件

### 前提条件

| 条件 | 説明 |
|-----|------|
| TFCI環境変数の設定 | `$TFCI` 環境変数に適切な env ファイルパスが設定されていること |
| TF_BISECT_GOOD | 最後の正常コミットSHAが設定されていること |
| TF_BISECT_BAD | 最初の失敗コミットSHAが設定されていること |
| TF_BISECT_SCRIPT | テスト実行スクリプトのパスが設定されていること |
| Gitリポジトリ | TensorFlowのgitリポジトリ内で実行されること |

### 実行可否判定

`TF_BISECT_GOOD`、`TF_BISECT_BAD`、`TF_BISECT_SCRIPT`、`TFCI` がすべて設定されていること。

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | デフォルト値 | 説明 |
|-------------|-----|-----|-------------|------|
| TFCI | string | Yes | なし | 環境設定ファイルのカンマ区切りパス |
| TF_BISECT_GOOD | string | Yes | なし | 最後の正常コミットSHA |
| TF_BISECT_BAD | string | Yes | なし | 最初の失敗コミットSHA |
| TF_BISECT_SCRIPT | string | Yes | なし | テスト実行スクリプトのパス（TFルートからの相対パス） |
| TF_ANY_TARGETS | string | No | なし | any.shと組み合わせ時のBazelターゲット |
| TF_ANY_MODE | string | No | test | any.shと組み合わせ時のBazelモード |

### 入力データソース

| データソース | 形式 | 説明 |
|-------------|------|------|
| Gitリポジトリ | git | コミット履歴と各コミットのソースコード |
| テスト実行スクリプト | シェルスクリプト | TF_BISECT_SCRIPTで指定されたスクリプト |

## 出力仕様

### 出力データ

| 出力先 | 形式 | 説明 |
|-------|------|------|
| 標準出力 | テキスト | git bisect の結果（原因コミットの特定） |

### 出力ファイル仕様

| 項目 | 内容 |
|-----|------|
| ファイル名 | 該当なし（標準出力のみ） |
| 出力先 | 標準出力 |
| 文字コード | UTF-8 |
| 区切り文字 | 該当なし |

## 処理フロー

### 処理シーケンス

```
1. TensorFlowルートディレクトリへ移動
   └─ $(dirname "$0")/../../ に cd
2. TFCI環境変数の前処理
   └─ nightly_upload を public_cache,disk_cache に置換
3. git bisect 開始
   └─ git bisect start "$TF_BISECT_BAD" "$TF_BISECT_GOOD"
4. git bisect run 実行
   └─ git bisect run $TF_BISECT_SCRIPT
   └─ 各コミットで指定スクリプトを実行し、終了コードで good/bad を判定
   └─ 二分探索により原因コミットを特定
```

### フローチャート

```mermaid
flowchart TD
    A[バッチ開始] --> B[TFルートディレクトリへ移動]
    B --> C[nightly_uploadをローカルキャッシュに置換]
    C --> D[git bisect start BAD GOOD]
    D --> E[git bisect run SCRIPT]
    E --> F{テスト成功?}
    F -->|Yes: good| G[次のコミットをチェックアウト]
    F -->|No: bad| G
    G --> H{探索完了?}
    H -->|No| E
    H -->|Yes| I[原因コミットを出力]
    I --> J[バッチ終了]
```

## データベース操作仕様

### 操作別データベース影響一覧

本バッチはデータベース操作を行わない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 非ゼロ終了 | git bisectエラー | good/badコミットの範囲が不正 | コミットSHAを確認 |
| 非ゼロ終了 | スクリプト実行エラー | テストスクリプトの実行失敗（設定エラー等） | TF_BISECT_SCRIPTとTFCI設定を確認 |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | スクリプト自体にリトライ機能なし |
| リトライ間隔 | 該当なし |
| リトライ対象エラー | 該当なし |

### 障害時対応

`set -exo pipefail` により障害発生時にスクリプトが終了する。bisect中にエラーが発生した場合は `git bisect reset` でリポジトリの状態を復元する必要がある。

## トランザクション仕様

| 項目 | 内容 |
|-----|------|
| トランザクション範囲 | 該当なし |
| コミットタイミング | 該当なし |
| ロールバック条件 | `git bisect reset` によりリポジトリの元の状態に復帰 |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定処理件数 | O(log N) 回のテスト実行（Nはgood-bad間のコミット数） |
| 目標処理時間 | テスト実行時間 x log2(コミット数) |
| メモリ使用量上限 | テスト実行内容に依存 |

## 排他制御

git bisect中はリポジトリの作業ツリーが変更されるため、同一リポジトリでの並行実行は不可。

## ログ出力

| ログ種別 | 出力タイミング | 出力内容 |
|---------|--------------|---------|
| 進捗ログ | 各コミット実行時 | `set -x` による全コマンドのトレースログ |
| 進捗ログ | git bisect各ステップ | bisectの進捗状況（残りステップ数等） |
| 終了ログ | bisect完了時 | 原因コミットのSHAとコミットメッセージ |

## 監視・アラート

| 監視項目 | 閾値 | アラート先 |
|---------|-----|----------|
| ジョブ実行結果 | 非ゼロ終了コード | 手動実行のため開発者が直接確認 |

## 備考

- `any.sh` と組み合わせることで、特定のBazelテストターゲットに対するbisectが可能（例: `TF_BISECT_SCRIPT=ci/official/any.sh` + `TF_ANY_TARGETS="//path/to:test"` + `TF_ANY_MODE=test`）
- `nightly_upload` は安全のため自動的にローカルキャッシュに置換される
- bisect完了後は `git bisect reset` で元のブランチに戻す必要がある（スクリプト内には含まれていない）
- 二分探索のため、N個のコミット間で最大 log2(N) 回のテスト実行で原因を特定できる
