# バッチ設計書 34-change-scala-version.sh

## 概要

本ドキュメントは、SparkプロジェクトのScalaバージョンを切り替えるスクリプト `dev/change-scala-version.sh` のバッチ設計書である。本スクリプトは全pom.xmlファイルおよび関連設定ファイル内のScalaバージョン参照を一括変更し、プロジェクト全体を指定したScalaバージョンでビルド可能な状態に切り替える。

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

本スクリプトは、Sparkプロジェクト全体のScalaバージョンを一括で切り替えるユーティリティである。

**業務上の目的・背景**：Apache SparkはScala 2.13をサポートしており、異なるScalaバージョン向けのビルドを行う必要がある。ScalaバージョンはMaven/SBTのartifactId（サフィックス _2.12 / _2.13）やプロファイル設定、親POMのscala.version/scala.binary.versionプロパティ、さらにドキュメントビルドやMiMa（バイナリ互換性チェック）のスクリプトにも影響する。これらすべてのファイルを一貫して更新するために本スクリプトが提供されている。手動での変更はファイル数が多く漏れが発生しやすいため、自動化が必須である。

**バッチの実行タイミング**：Scalaバージョンを切り替えてビルド・テストを行う際に手動で実行する。CI/CDパイプラインにおいてマルチバージョンテストを行う際にも使用される。run-tests.pyからも内部的に呼び出される。

**主要な処理内容**：
1. 指定されたScalaバージョンの有効性検証（現在は2.13のみ有効）
2. 切り替え元バージョンの自動判定（2.13指定時は2.12から切り替え）
3. 全pom.xmlファイル内のartifactIdサフィックスの置換（_FROM → _TO）
4. pom.xml内のScalaバージョン条件付きセクションのコメント切り替え
5. commons-cliの依存関係事前取得（SBTビルド時の問題回避、SPARK-34762対応）
6. 親POMのscala.versionプロパティの更新（完全バージョン番号）
7. 親POMのscala.binary.versionプロパティの更新
8. ドキュメントビルドスクリプト（build_api_docs.rb）のScalaプロファイル更新
9. MiMaスクリプト（dev/mima）のScalaプロファイル更新

**前後の処理との関連**：本スクリプトはビルド前の準備ステップとして実行される。run-tests.pyのswitch_scala_version関数から呼び出されることがある。本スクリプト実行後、Maven/SBTによるビルドが可能になる。make-distribution.shやその他のビルドスクリプトは変更後のScalaバージョンでビルドを行う。

**影響範囲**：プロジェクト全体のpom.xmlファイル（target/ディレクトリ配下を除く）、親POMのscala.version/scala.binary.version、docs/_plugins/build_api_docs.rb、dev/mimaファイルが変更される。Mavenローカルリポジトリにcommons-cliの依存関係が追加される。

## バッチ種別

ビルド・リリース（Scalaバージョン切り替えユーティリティ）

## 実行スケジュール

| 項目 | 内容 |
|-----|------|
| 実行頻度 | 随時（Scalaバージョン切り替え時） |
| 実行時刻 | N/A |
| 実行曜日 | N/A |
| 実行日 | N/A |
| トリガー | 手動実行 / run-tests.pyからの呼び出し / CI/CDパイプライン |

## 実行条件

### 前提条件

| 条件 | 説明 |
|-----|------|
| Bashシェル | `/usr/bin/env bash`で実行可能であること |
| sed | sedコマンドが利用可能であること |
| find | findコマンドが利用可能であること |
| Maven | `build/mvn`経由でMavenが利用可能であること（バージョン情報取得・依存関係ダウンロードに使用） |
| pom.xml | SparkプロジェクトのMaven POMファイルが存在すること |

### 実行可否判定

引数が1つでない場合、または指定されたバージョンが有効バージョン（2.13）でない場合はusageを表示して終了する。

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | デフォルト値 | 説明 |
|-------------|-----|-----|-------------|------|
| version | string | Yes | N/A | 切り替え先のScalaバイナリバージョン（有効値: 2.13） |

### 入力データソース

| データソース | 形式 | 説明 |
|-------------|------|------|
| **/pom.xml | XML | Maven POMファイル群（target/ディレクトリ配下を除く） |
| pom.xml（ルート） | XML | 親POM（scala.version, scala.binary.version更新対象） |
| docs/_plugins/build_api_docs.rb | Ruby | ドキュメントビルドスクリプト |
| dev/mima | スクリプト | MiMa（バイナリ互換性チェック）スクリプト |

## 出力仕様

### 出力データ

| 出力先 | 形式 | 説明 |
|-------|------|------|
| **/pom.xml | XML | artifactIdサフィックス・条件付きセクションが更新されたPOMファイル |
| pom.xml（ルート） | XML | scala.version・scala.binary.versionが更新された親POM |
| docs/_plugins/build_api_docs.rb | Ruby | Scalaプロファイルが更新されたビルドスクリプト |
| dev/mima | スクリプト | Scalaプロファイルが更新されたMiMaスクリプト |

### 出力ファイル仕様

更新は既存ファイルのインプレース変更として行われる。一時ファイル（*.tmp）が作成され、処理完了後に元ファイルに置換される（sed_i関数によるatomicな更新）。

## 処理フロー

### 処理シーケンス

```
1. 引数検証
   └─ 引数が1つであること、有効バージョン(2.13)であることを確認
2. 切り替え元バージョン決定
   └─ TO_VERSION=2.13の場合、FROM_VERSION=2.12
3. 全pom.xmlの検索と更新
   └─ find でtarget/以外の全pom.xmlを検出
   └─ artifactIdサフィックスの置換（_FROM → _TO）
   └─ scala-TOバージョンの条件付きセクションを有効化（コメント解除）
   └─ scala-FROMバージョンの条件付きセクションを無効化（コメント化）
4. commons-cli依存関係の事前取得
   └─ SPARK-34762対応: commons-cliのJARをMavenローカルリポジトリにダウンロード
5. 親POMのscala.version更新
   └─ Mavenプロファイル経由で完全バージョン番号を取得
   └─ pom.xml内の<scala.version>を更新
6. 親POMのscala.binary.version更新
   └─ pom.xml内の<scala.binary.version>を更新
7. ドキュメントビルドスクリプト更新
   └─ docs/_plugins/build_api_docs.rb内のScalaプロファイル参照を更新
8. MiMaスクリプト更新
   └─ dev/mima内のScalaプロファイル参照を更新
   └─ パーミッション775を設定
```

### フローチャート

```mermaid
flowchart TD
    A[バッチ開始] --> B{引数検証OK?}
    B -->|いいえ| C[usage表示・終了]
    B -->|はい| D[FROM/TOバージョン決定]
    D --> E[全pom.xml検索・更新]
    E --> F[artifactIdサフィックス置換]
    F --> G[条件付きセクション切り替え]
    G --> H[commons-cli依存関係取得]
    H --> I[親POM scala.version更新]
    I --> J[親POM scala.binary.version更新]
    J --> K[build_api_docs.rb更新]
    K --> L[dev/mima更新]
    L --> M[バッチ終了]
```

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

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

データベース操作なし。本スクリプトはファイルの検索・置換操作とMaven依存関係取得のみを行う。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 1 | 引数エラー | 引数が0または2以上、もしくは--help/-hが指定された | 有効バージョン（2.13）を1つだけ指定する |
| 1 | 無効バージョン | 有効バージョン以外が指定された | 有効バージョン（2.13）を指定する |
| 非0 | sed置換失敗 | pom.xmlの構文が想定外 | POMファイルの構文を確認する |
| 非0 | Maven実行失敗 | build/mvnが実行できない、または依存関係取得失敗 | Maven環境を確認する |

### リトライ仕様

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

### 障害時対応

`set -e`が有効なため、いずれかのコマンド失敗で即座にスクリプトが終了する。中途半端な状態からの復旧には`git checkout -- .`でファイルを元に戻すか、再度スクリプトを正しいバージョンで実行する。

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

| 項目 | 内容 |
|-----|------|
| トランザクション範囲 | N/A（ファイルシステム操作のみ） |
| コミットタイミング | N/A |
| ロールバック条件 | N/A（git checkoutで手動復旧可能） |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定処理件数 | プロジェクト内の全pom.xmlファイル + 3追加ファイル |
| 目標処理時間 | 数分以内（Maven依存関係取得を含む） |
| メモリ使用量上限 | 最小限（sed/find/Mavenプロセス） |

## 排他制御

同一プロジェクトディレクトリ上での同時実行は非対応。pom.xmlファイルへの同時書き込みが発生するため、排他制御が必要な場合は呼び出し側で制御する。

## ログ出力

| ログ種別 | 出力タイミング | 出力内容 |
|---------|--------------|---------|
| 進捗ログ | 各pom.xml処理時 | 処理対象のpom.xmlファイルパス |
| 進捗ログ | build_api_docs.rb更新時 | ファイルパス |
| 進捗ログ | dev/mima更新時 | ファイルパス |

## 監視・アラート

| 監視項目 | 閾値 | アラート先 |
|---------|-----|----------|
| 終了コード | 0以外 | CI/CDシステム |

## 備考

- 有効バージョンは現在2.13のみであり、VALID_VERSIONS配列で定義されている
- sed_i関数は、sedコマンドの-iオプションのポータビリティ問題を回避するため、一時ファイル経由で更新を行う（`sed -e "$1" "$2" > "$2.tmp" && mv "$2.tmp" "$2"`）
- pom.xml内の条件付きセクション（`<!-- #if scala-X.XX -->`/`<!-- #endif scala-X.XX -->`）のコメント操作により、バージョン固有の依存関係を有効化/無効化する
- SPARK-34762対応として、commons-cliのJARファイルをMaven dependency:getで事前ダウンロードしている。これはSBTビルド時にhelpプラグインがPOMのみをダウンロードしJARをダウンロードしない問題への対応である
- Mavenのhelp:evaluateプラグインを使用してScalaの完全バージョン番号（例: 2.13.x）を動的に取得する
