# 機能設計書 62-環境変数

## 概要

本ドキュメントは、Jenkins におけるビルド環境変数の管理機能（EnvVars）の設計について記述する。

### 本機能の処理概要

環境変数機能は、Jenkins のビルド処理において環境変数を管理・操作するための基盤機能である。クロスプラットフォームでの一貫した動作と、ビルドパイプラインでの変数展開を提供する。

**業務上の目的・背景**：CI/CD パイプラインでは、ビルドパラメータ、システム設定、認証情報などを環境変数として扱う必要がある。環境変数機能は、Windows と Unix/Linux の環境変数の違い（特に大文字小文字の扱い）を抽象化し、一貫した操作を提供する。また、PATH 変数の安全な拡張や変数の展開（${VAR}）を自動的に処理することで、ビルドスクリプトの移植性を向上させる。

**機能の利用シーン**：
- ビルド開始時の環境変数初期化
- ビルドステップへの環境変数の受け渡し
- エージェントノードへの環境変数の転送
- PATH 変数への追加パス設定
- ビルドパラメータの環境変数としての展開
- 変数値内の他の変数参照の展開

**主要な処理内容**：
1. 環境変数の大文字小文字非依存マップ管理（Windows 互換）
2. 環境変数のオーバーライドと継承処理
3. PATH+XXX 記法による PATH 変数への追加
4. 変数展開（${VAR} 形式の置換）
5. 変数間の循環参照検出と解決
6. リモートエージェントからの環境変数取得
7. プロセス終了用クッキー変数の生成

**関連システム・外部連携**：
- Launcher: プロセス起動時の環境変数設定
- VirtualChannel: リモート環境変数取得
- Platform: プラットフォーム依存の処理（パス区切り文字など）
- Util: 変数展開処理

**権限による制御**：環境変数機能自体には権限制御はないが、機密情報を含む環境変数の取り扱いはビルドログのマスク機能と連携する。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 31 | システム情報 | 主画面 | 環境変数情報の表示 |
| 12 | ジョブ設定 | 参照画面 | ビルドパラメータとしての環境変数設定 |

## 機能種別

データ管理 / ユーティリティ

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| key | String | Yes | 環境変数名 | 空でないこと |
| value | String | Yes | 環境変数値 | null でないこと |
| overrides | Map<String, String> | No | オーバーライドする環境変数群 | - |

### 入力データソース

- システム環境変数（System.getenv()）
- ビルドパラメータ
- プラグインからの追加変数
- ジョブ設定で定義された変数

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| EnvVars | EnvVars | 環境変数マップ（TreeMap<String, String> の拡張） |
| expandedValue | String | 変数展開後の文字列 |

### 出力先

- Launcher: プロセス起動時に渡される
- ビルドログ: 展開された変数値の表示

## 処理フロー

### 処理シーケンス

```
1. EnvVars インスタンスの生成
   └─ 大文字小文字非依存の TreeMap を基底クラスとして使用

2. 初期環境変数の取得
   └─ masterEnvVars から現在の JVM 環境変数を取得

3. オーバーライドの適用
   └─ override() メソッドで個別に適用
   └─ overrideAll() メソッドで一括適用

4. PATH+ 記法の処理
   └─ PATH+XXX 形式の変数を検出
   └─ 既存の PATH 変数に値を追加（プラットフォーム依存の区切り文字使用）

5. 変数展開
   └─ expand() メソッドで ${VAR} を実際の値に置換
   └─ 循環参照を検出して処理

6. リモート転送（必要に応じて）
   └─ getRemote() でエージェントの環境変数を取得
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B[EnvVars 生成]
    B --> C[masterEnvVars から初期化]
    C --> D{オーバーライドあり?}
    D -->|Yes| E[override/overrideAll 適用]
    D -->|No| F{PATH+ 変数あり?}
    E --> F
    F -->|Yes| G[PATH 変数に追加]
    F -->|No| H{変数展開必要?}
    G --> H
    H -->|Yes| I[expand() で ${VAR} を展開]
    H -->|No| J[EnvVars 返却]
    I --> K{循環参照あり?}
    K -->|Yes| L[循環を検出して切断]
    K -->|No| J
    L --> J
    J --> M[終了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-62-01 | 大文字小文字非依存 | 環境変数名は大文字小文字を区別しない（値は保持） | 常時 |
| BR-62-02 | PATH+ 記法 | PATH+XXX 形式の変数は PATH の先頭に追加される | 変数名が PATH+ で始まる場合 |
| BR-62-03 | Null 値禁止 | 環境変数の値に null は設定できない | put() 呼び出し時 |
| BR-62-04 | 循環参照解決 | 変数間の循環参照は自動的に検出・切断される | overrideExpandingAll() 時 |
| BR-62-05 | プラットフォーム区切り | PATH 区切り文字はプラットフォームに依存（Unix: ":"、Windows: ";"） | PATH+ 処理時 |

### 計算ロジック

**変数展開順序の計算**:
- トポロジカルソートを使用して変数の依存関係を解決
- 循環参照が検出された場合、適切な位置で参照を切断
- OverrideOrderCalculator クラスで実装

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

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

該当なし（環境変数機能はデータベース操作を行わない）

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| IllegalArgumentException | 引数エラー | null 値の設定、不正な形式 | 例外をスロー |
| CycleDetectedException | 循環参照 | 変数間の循環参照を検出 | 警告ログ出力後、参照を切断して続行 |

### リトライ仕様

該当なし

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

該当なし（データベーストランザクションは使用しない）

## パフォーマンス要件

- 環境変数アクセスは O(log n) の計算量（TreeMap 使用）
- 変数展開時の循環参照検出は効率的なグラフアルゴリズムを使用

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

- パスワードなどの機密情報は Secret クラスと連携して管理すべき
- MAVEN_OPTS など開発モード用の変数は自動的に除外される
- 環境変数のログ出力時はマスク機能との連携が推奨される

## 備考

- EnvVars は TreeMap<String, String> を継承し、大文字小文字非依存の比較を実装
- masterEnvVars はコントローラー/エージェントそれぞれの JVM 環境変数を保持
- platform プロパティでターゲットプラットフォームを指定可能

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | EnvVars.java | `core/src/main/java/hudson/EnvVars.java` | TreeMap を継承した大文字小文字非依存マップの実装（75-109行目） |

**読解のコツ**: コンストラクタ（107-137行目）で `String.CASE_INSENSITIVE_ORDER` を使用している点に注目。これにより Windows 互換の大文字小文字非依存動作を実現している。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | EnvVars.java | `core/src/main/java/hudson/EnvVars.java` | override() メソッド（145-168行目）と put() メソッド（377-381行目） |

**主要処理フロー**:
1. **145-168行目**: override() - PATH+ 記法を処理する中核メソッド
2. **151-164行目**: PATH+ 記法の検出と PATH への追加処理
3. **160-161行目**: プラットフォーム依存のパス区切り文字選択

#### Step 3: 変数展開を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | EnvVars.java | `core/src/main/java/hudson/EnvVars.java` | expand() メソッド（414-416行目）と OverrideOrderCalculator（189-343行目） |

**主要処理フロー**:
- **414-416行目**: expand() - Util.replaceMacro() を使用した変数展開
- **351-356行目**: overrideExpandingAll() - 順序を考慮した展開付きオーバーライド
- **189-343行目**: OverrideOrderCalculator - トポロジカルソートによる依存関係解決

#### Step 4: リモート環境変数取得を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | EnvVars.java | `core/src/main/java/hudson/EnvVars.java` | getRemote() メソッド（434-438行目）と GetEnvVars クラス（440-447行目） |

**主要処理フロー**:
- **434-438行目**: getRemote() - VirtualChannel 経由でリモート環境変数取得
- **440-447行目**: GetEnvVars - MasterToSlaveCallable の実装

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

```
EnvVars 操作
    │
    ├─ put(key, value)
    │      └─ null チェック (377-381行目)
    │
    ├─ override(key, value)
    │      ├─ PATH+ 記法検出 (151行目)
    │      ├─ プラットフォーム判定 (160行目)
    │      └─ put() 呼び出し (163, 167行目)
    │
    ├─ overrideExpandingAll(map)
    │      ├─ OverrideOrderCalculator 生成 (352行目)
    │      │      ├─ scan() - 依存関係解析 (291-342行目)
    │      │      └─ getOrderedVariableNames() (249-251行目)
    │      └─ expand() & override() (353-354行目)
    │
    └─ getRemote(channel)
           └─ channel.call(GetEnvVars) (437行目)
```

### データフロー図

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

System.getenv() ─────▶ masterEnvVars 初期化 (463-472行目)
                              │
                              ▼
オーバーライド値 ────▶ override() / overrideAll()
                              │
                              ▼
                       PATH+ 記法処理 ─────────▶ PATH 変数更新
                              │
                              ▼
変数参照 ${VAR} ─────▶ expand() ───────────────▶ 展開済み文字列
                              │
                              ▼
                       OverrideOrderCalculator
                              │
                              ▼
                       循環参照検出・切断 ────▶ 警告ログ
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| EnvVars.java | `core/src/main/java/hudson/EnvVars.java` | ソース | 環境変数管理の主要クラス |
| Platform.java | `core/src/main/java/hudson/Platform.java` | ソース | プラットフォーム判定 |
| Util.java | `core/src/main/java/hudson/Util.java` | ソース | replaceMacro() による変数展開 |
| Launcher.java | `core/src/main/java/hudson/Launcher.java` | ソース | 環境変数を使用するプロセス起動 |
| VirtualChannel.java | `remoting/.../VirtualChannel.java` | ソース | リモート通信チャネル |
| CyclicGraphDetector.java | `core/src/main/java/hudson/util/CyclicGraphDetector.java` | ソース | 循環参照検出 |
| VariableResolver.java | `core/src/main/java/hudson/util/VariableResolver.java` | ソース | 変数解決インターフェース |
