# バッチ設計書 91-evaluate-changed-paths.sh

## 概要

本ドキュメントは、.NET Runtimeプロジェクトにおける変更パス評価スクリプト（evaluate-changed-paths.sh）の設計仕様を定義するものである。このスクリプトはCI/CDパイプラインで使用され、コード変更の影響範囲を評価してビルドの実行可否を判定する。

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

このバッチは、Gitリポジトリにおけるコード変更を検出し、指定されたパスフィルター条件に基づいてビルドをスキップするかどうかを判定する処理を行う。Azure DevOpsパイプラインと連携し、変更検出結果を出力変数として設定することで、後続のビルドジョブの実行制御を可能にする。

**業務上の目的・背景**：大規模なMonorepoである.NET Runtimeでは、すべてのコード変更に対して全コンポーネントのビルドを実行すると膨大な時間とリソースが消費される。特定のサブセット（CoreCLR、Mono、Libraries等）に関係しない変更に対しては、該当サブセットのビルドをスキップすることでCI/CDの効率を大幅に向上させる必要がある。

**バッチの実行タイミング**：CIパイプラインの初期段階で実行される。PRの作成・更新時、またはmainブランチへのプッシュ時にトリガーされ、後続のビルドジョブより前に実行される。

**主要な処理内容**：
1. コマンドライン引数の解析（difftarget、includepaths、excludepaths、subset、azurevariable等）
2. 指定されたdifftargetとHEAD間のgit diffを実行
3. 除外パス（excludepaths）と包含パス（includepaths）に基づくフィルタリング
4. combinedモードでの複合条件評価（包含パスから除外パスを除く）
5. 変更が検出された場合、Azure DevOps出力変数を設定

**前後の処理との関連**：パイプラインの最初期に実行され、出力変数を通じて後続のビルドジョブ（CoreCLR、Mono、Libraries等）の実行可否を制御する。変更が検出されない場合、該当サブセットのビルドジョブ全体がスキップされる。

**影響範囲**：Azure DevOpsパイプラインの実行制御に影響。誤った判定は不要なビルドの実行、または必要なビルドのスキップを引き起こす可能性がある。

## バッチ種別

CI最適化 / 変更検出 / パイプライン制御

## 実行スケジュール

| 項目 | 内容 |
|-----|------|
| 実行頻度 | イベント駆動 |
| 実行時刻 | N/A |
| 実行曜日 | N/A |
| 実行日 | N/A |
| トリガー | PRの作成・更新、mainブランチへのプッシュ（Azure DevOpsパイプライン） |

## 実行条件

### 前提条件

| 条件 | 説明 |
|-----|------|
| Gitリポジトリ | スクリプトはGitリポジトリ内で実行される必要がある |
| difftarget | 比較対象のコミットまたはブランチが指定されている |
| pipeline-logging-functions.sh | eng/common/pipeline-logging-functions.shが存在する |

### 実行可否判定

スクリプトは常に実行される。変更が検出されるかどうかは、指定されたパスフィルターとdifftargetに依存する。

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | デフォルト値 | 説明 |
|-------------|-----|-----|-------------|------|
| --difftarget | string | Yes | なし | 比較対象のSHAまたはブランチ名（例: HEAD^1, origin/main） |
| --excludepaths | string | No | 空配列 | 除外するパスのリスト（+区切り） |
| --includepaths | string | No | 空配列 | 包含するパスのリスト（+区切り） |
| --combined | flag | No | false | excludeとincludeを組み合わせて評価 |
| --subset | string | No | 空文字 | 評価対象のサブセット名（ログ出力用） |
| --azurevariable | string | No | 空文字 | 変更検出時に設定するAzure DevOps変数名 |

### 入力データソース

| データソース | 形式 | 説明 |
|-------------|------|------|
| Gitリポジトリ | Git | 変更検出対象のソースコードリポジトリ |
| eng/common/pipeline-logging-functions.sh | Shell Script | Azure Pipelines用のログ関数 |

## 出力仕様

### 出力データ

| 出力先 | 形式 | 説明 |
|-------|------|------|
| Azure DevOps変数 | 出力変数 | 変更検出時に指定変数名をtrueに設定 |
| 標準出力 | テキスト | 処理状況のログ、マッチしたファイルのリスト |

### 出力ファイル仕様

ファイル出力なし（Azure DevOps出力変数とコンソール出力のみ）

## 処理フロー

### 処理シーケンス

```
1. 初期設定
   └─ set -f（globbing無効化）、set -u（未定義変数エラー）、set -e（エラー時停止）
2. コマンドライン引数の解析
   └─ difftarget、excludepaths、includepaths、combined、subset、azurevariable
3. pipeline-logging-functions.shの読み込み
   └─ Write-PipelineSetVariable関数を利用可能にする
4. パス文字列の構築
   └─ 除外パスは ":!path" 形式、包含パスは ":path" 形式で構築
5. 変更検出の実行
   └─ combinedモード: 包含パス + 除外パスで評価
   └─ 通常モード: 除外パス評価 → 包含パス評価（順次）
6. git diff実行
   └─ -M -C -b --ignore-cr-at-eol --ignore-space-at-eol オプション付き
7. 結果の出力
   └─ 変更検出時: Azure DevOps変数を設定、マッチファイルをログ出力
   └─ 変更なし: ログ出力のみ
```

### フローチャート

```mermaid
flowchart TD
    A[バッチ開始] --> B[引数解析]
    B --> C[pipeline-logging-functions.sh読込]
    C --> D{combinedモード?}
    D -->|Yes| E[包含+除外パスで評価]
    D -->|No| F{除外パスあり?}
    F -->|Yes| G[除外パスで評価]
    F -->|No| H{包含パスあり?}
    G --> I{変更検出?}
    I -->|No| H
    I -->|Yes| J[変更フラグON]
    H -->|Yes| K[包含パスで評価]
    H -->|No| L[変更なし]
    K --> M{変更検出?}
    M -->|Yes| J
    M -->|No| L
    E --> N{変更検出?}
    N -->|Yes| J
    N -->|No| L
    J --> O[Azure変数設定]
    O --> P[マッチファイルログ出力]
    P --> Q[バッチ終了]
    L --> Q
```

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

データベース操作なし

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 1 | スクリプトエラー | 未定義変数の参照 | set -uにより即座に終了 |
| 1 | Gitエラー | git diffコマンド失敗 | set -eにより即座に終了 |
| 1 | ファイルエラー | pipeline-logging-functions.shが見つからない | スクリプト終了 |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | なし |
| リトライ間隔 | N/A |
| リトライ対象エラー | N/A |

### 障害時対応

スクリプトが失敗した場合、パイプラインの後続ジョブは変更検出なしとして扱われ、フルビルドが実行される可能性がある。エラーログを確認し、Gitリポジトリの状態およびパラメータの正当性を確認する。

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

| 項目 | 内容 |
|-----|------|
| トランザクション範囲 | N/A（トランザクション処理なし） |
| コミットタイミング | N/A |
| ロールバック条件 | N/A |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定処理件数 | 1回のgit diff実行 |
| 目標処理時間 | 数秒以内 |
| メモリ使用量上限 | 通常のシェルスクリプト実行範囲 |

## 排他制御

同時実行の制限なし。ただし、同一リポジトリに対する並行実行時はGitロックに注意。

## ログ出力

| ログ種別 | 出力タイミング | 出力内容 |
|---------|--------------|---------|
| パス収集ログ | パス文字列構築時 | 収集した除外/包含パス |
| プローブログ | git diff実行時 | 実行中のgit diffコマンド |
| 結果ログ | 評価完了時 | マッチしたファイルリストまたは「変更なし」 |
| 変数設定ログ | 変更検出時 | 設定するAzure DevOps変数名と値 |

## 監視・アラート

| 監視項目 | 閾値 | アラート先 |
|---------|-----|----------|
| スクリプト失敗 | 終了コード != 0 | Azure DevOpsパイプライン |
| 実行時間 | 60秒超過 | パイプライン監視 |

## 備考

- `set -f`によりglobbingが無効化されているため、パスパターンのワイルドカードはgit diff側で解釈される
- `--exit-code`オプションにより、git diffは変更なしの場合に終了コード0、変更ありの場合に終了コード1を返す
- 3つのシナリオ（excludeのみ、includeのみ、combined）に対応した柔軟な変更検出が可能
