# バッチ設計書 5-upload.sh

## 概要

本ドキュメントは、TensorFlowのCI/CDパイプラインにおけるビルド成果物アップロードバッチ `upload.sh` の設計仕様を記述する。

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

本バッチは、同一ジョブチェーン内の前段ビルドでGCSステージング領域に配置されたすべてのビルド成果物を、最終的なGCSリリースディレクトリおよびPyPIにアップロードする処理を行う。

**業務上の目的・背景**：TensorFlowのリリースプロセスでは、複数のビルドジョブ（wheel、libtensorflow、installer_wheel等）がそれぞれの成果物をGCSステージング領域に配置する。本バッチはそれらを集約し、バージョン管理されたGCSディレクトリとPyPIへの一括アップロードを行う最終段階のバッチである。

**バッチの実行タイミング**：CI/CDパイプラインにおいて、すべてのビルドジョブが完了した後に実行される。リリースビルドおよびNightlyビルドの最終段階で実行される。

**主要な処理内容**：
1. TFCI環境の初期化（setup.sh の読み込み）
2. TensorFlowの完全バージョン番号の算出（nightly/releaseに応じた形式）
3. GCSステージング領域からローカルへの全成果物ダウンロード
4. GCS最終リリースディレクトリへの同期アップロード（バージョンディレクトリ + latestミラー）
5. PyPIへのwheelアップロード（twine使用）

**前後の処理との関連**：前段として `wheel.sh`、`libtensorflow.sh`、`installer_wheel.sh` 等のビルドバッチが完了し、成果物がGCSステージング領域に配置されていること。本バッチがCI/CDパイプラインの最終段階となる。

**影響範囲**：GCS最終リリースディレクトリ（`$TFCI_ARTIFACT_FINAL_GCS_URI/{version}`）、GCS latestディレクトリ、PyPIパッケージレジストリ。

## バッチ種別

成果物アップロード / リリース配布

## 実行スケジュール

| 項目 | 内容 |
|-----|------|
| 実行頻度 | 随時（CI/CDトリガーに依存） |
| 実行時刻 | CI/CDパイプラインによる（ビルドジョブ完了後） |
| 実行曜日 | 該当なし |
| 実行日 | 該当なし |
| トリガー | CI/CDパイプライン（Kokoro等）からの呼び出し |

## 実行条件

### 前提条件

| 条件 | 説明 |
|-----|------|
| TFCI環境変数の設定 | `$TFCI` 環境変数が適切に設定されていること |
| GCSステージング成果物 | 前段ビルドジョブにより成果物がGCSステージング領域に配置済みであること |
| GCS認証情報 | サービスアカウントキーが `$TFCI_ARTIFACT_FINAL_GCS_SA_PATH` に配置されていること |
| PyPI認証情報 | PyPIアップロード有効時、twine用の認証情報が設定されていること |

### 実行可否判定

GCSステージング領域に成果物が存在すること。`setup.sh` による環境初期化が正常に完了していること。

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | デフォルト値 | 説明 |
|-------------|-----|-----|-------------|------|
| TFCI | string | Yes | なし | 環境設定ファイルのカンマ区切りパス |
| TFCI_NIGHTLY_UPDATE_VERSION_ENABLE | string | No | 0 | Nightlyビルドの有無 |
| TFCI_ARTIFACT_STAGING_GCS_URI | string | Yes | なし | GCSステージングURI |
| TFCI_ARTIFACT_FINAL_GCS_ENABLE | string | No | 0 | GCS最終アップロードの有効/無効 |
| TFCI_ARTIFACT_FINAL_GCS_SA_PATH | string | No | なし | GCSサービスアカウントキーパス |
| TFCI_ARTIFACT_FINAL_GCS_URI | string | No | なし | GCS最終ディレクトリのベースURI |
| TFCI_ARTIFACT_LATEST_GCS_URI | string | No | なし | GCS latestディレクトリURI |
| TFCI_ARTIFACT_FINAL_PYPI_ENABLE | string | No | 0 | PyPIアップロードの有効/無効 |
| TFCI_ARTIFACT_FINAL_PYPI_ARGS | string | No | なし | twine uploadの追加引数 |

### 入力データソース

| データソース | 形式 | 説明 |
|-------------|------|------|
| GCSステージング領域 | GCS | 前段ビルドジョブの成果物（.whl、.tar.gz等） |

## 出力仕様

### 出力データ

| 出力先 | 形式 | 説明 |
|-------|------|------|
| $TFCI_ARTIFACT_FINAL_GCS_URI/$TF_VER_FULL | GCS | バージョンディレクトリへの全成果物 |
| $TFCI_ARTIFACT_LATEST_GCS_URI | GCS | latestミラーディレクトリ |
| PyPI | wheelパッケージ | PyPIへのwheelアップロード |

### 出力ファイル仕様

| 項目 | 内容 |
|-----|------|
| ファイル名 | ステージング領域と同一 |
| 出力先 | GCSバージョンディレクトリ / PyPI |
| 文字コード | バイナリ |
| 区切り文字 | 該当なし |

## 処理フロー

### 処理シーケンス

```
1. 環境初期化
   └─ setup.sh を source し、TFCI環境変数を設定
2. バージョン番号算出
   └─ bazel run //tensorflow/tools/ci_build:calculate_full_version でバージョンを取得
   └─ Nightlyの場合: --wheel-type nightly（例: 2.16.0-dev20240105）
   └─ Releaseの場合: --wheel-type release（例: 2.16.0-rc1）
3. GCSステージングからダウンロード
   └─ gsutil -m rsync -r でステージング領域の全成果物をローカル一時ディレクトリにダウンロード
4. GCS最終ディレクトリへアップロード（条件付き）
   └─ gcloud auth activate-service-account でサービスアカウント認証
   └─ gsutil -m rsync -d -r でバージョンディレクトリに同期
   └─ gsutil -m rsync -d -r でlatestディレクトリにミラー
5. PyPIアップロード（条件付き）
   └─ twine upload で全wheelファイルをPyPIにアップロード
```

### フローチャート

```mermaid
flowchart TD
    A[バッチ開始] --> B[setup.sh による環境初期化]
    B --> C[バージョン番号算出]
    C --> D[GCSステージングから全成果物ダウンロード]
    D --> E{GCS最終アップロード有効?}
    E -->|Yes| F[サービスアカウント認証]
    F --> G[バージョンディレクトリに同期]
    G --> H[latestディレクトリにミラー]
    H --> I{PyPIアップロード有効?}
    E -->|No| I
    I -->|Yes| J[twine upload でPyPIにアップロード]
    I -->|No| K[バッチ終了]
    J --> K
```

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

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

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

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 非ゼロ終了 | バージョン算出エラー | calculate_full_versionの失敗 | Bazel設定・バージョンファイルを確認 |
| 非ゼロ終了 | GCSダウンロードエラー | ステージング領域へのアクセス失敗 | GCS URI・認証情報を確認 |
| 非ゼロ終了 | GCSアップロードエラー | 最終ディレクトリへの書き込み失敗 | サービスアカウント権限を確認 |
| 非ゼロ終了 | PyPIアップロードエラー | twine upload失敗 | PyPI認証情報・既存パッケージの確認 |

### リトライ仕様

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

### 障害時対応

GCSへのrsyncは `gsutil -m rsync -d -r` で行われるため、再実行時にはソースとデスティネーションの差分のみが同期される。PyPIアップロードの失敗時は、twineの出力を確認し、既にアップロード済みのパッケージとの重複等を確認する。

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

| 項目 | 内容 |
|-----|------|
| トランザクション範囲 | 該当なし（GCS rsyncおよびPyPI uploadは個別ファイル単位） |
| コミットタイミング | 該当なし |
| ロールバック条件 | GCS rsync -d によりソースにないファイルはデスティネーションから削除される |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定処理件数 | ステージング領域の全成果物（数ファイル〜数十ファイル） |
| 目標処理時間 | ファイルサイズとネットワーク帯域に依存（通常数分〜十数分） |
| メモリ使用量上限 | 一時ディレクトリに全成果物を保持する容量が必要 |

## 排他制御

CI/CDパイプラインの最終ジョブとして実行される。GCS rsync -d により、デスティネーションの内容がソースと完全同期されるため、並行実行は避ける必要がある。

## ログ出力

| ログ種別 | 出力タイミング | 出力内容 |
|---------|--------------|---------|
| 開始ログ | setup.sh 実行時 | TFCI環境変数の一覧 |
| 進捗ログ | 各コマンド実行時 | `set -x` による全コマンドのトレースログ |
| 進捗ログ | ダウンロード後 | ls $DOWNLOADS による成果物一覧 |
| 終了ログ | バッチ終了時 | cleanup_summary.sh によるResultStoreリンク |
| エラーログ | エラー発生時 | エラー発生コマンドの出力 |

## 監視・アラート

| 監視項目 | 閾値 | アラート先 |
|---------|-----|----------|
| ジョブ実行結果 | 非ゼロ終了コード | CI/CDシステムの通知機能 |

## 備考

- `gsutil -m rsync` の `-m` フラグにより並列転送が有効になる
- `gsutil rsync -d` の `-d` フラグにより、ソースに存在しないファイルがデスティネーションから削除される（完全同期）
- GCSはシンボリックリンクをサポートしないため、latestディレクトリはrsyncによるコピーで実現される
- `$TF_VER_FULL` は `calculate_full_version` で算出され、例として "2.15.0-rc2" や "2.16.0-dev20240105" のような形式
