# バッチ設計書 9-create-preview-tarballs

## 概要

本ドキュメントは、PRプレビュー用のtarballを生成する `create-preview-tarballs` バッチの設計書である。Gitコミットハッシュとタイムスタンプからプレビューバージョンを生成し、各パッケージをパッケージングする。

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

`create-preview-tarballs` は、Pull Requestの変更内容をプレビュー利用可能にするため、各パッケージのtarballを生成するバッチ処理である。コミットハッシュと日付からプレビューバージョン番号を生成し、パッケージ間の依存関係をvercel-packages URLに書き換えた上でnpm packを実行する。

**業務上の目的・背景**：PRレビュー時に、レビュアーが実際に変更後のNext.jsを試用できるようにすることで、レビュー品質の向上とリグレッション検出の効率化を図る。vercel-packagesサービスと連携し、PRのコミットハッシュからプレビュービルドをインストール可能にする。

**バッチの実行タイミング**：CI環境でPRのビルド後に自動実行される。

**主要な処理内容**：
1. Gitコミットハッシュから短縮SHA取得とコミット日付取得
2. プレビューバージョン番号生成（例: `15.0.0-preview-abc1234-20240101`）
3. ネイティブバイナリの各プラットフォームパッケージへのコピーとtarball生成
4. lernaによるパッケージ一覧取得
5. 各パッケージのバージョン・依存関係をプレビューURL形式に書き換え
6. npm packによるtarball生成
7. プレビュービルドURLの出力

**前後の処理との関連**：ビルド完了後に実行される。生成されたtarballはGitHub Artifactsとしてアップロードされ、vercel-packagesサービスから配信される。

**影響範囲**：指定されたtarballディレクトリ、各パッケージの `package.json`（一時的な書き換え）。

## バッチ種別

パッケージング処理（プレビュービルド）

## 実行スケジュール

| 項目 | 内容 |
|-----|------|
| 実行頻度 | PRビルドごと |
| 実行時刻 | CI/CDパイプライン内 |
| 実行曜日 | 該当なし |
| 実行日 | 該当なし |
| トリガー | CI/CD（PRイベント） |

## 実行条件

### 前提条件

| 条件 | 説明 |
|-----|------|
| ビルド済み | パッケージがビルド済みであること |
| Gitリポジトリ | vercel/next.jsリポジトリ内で実行 |
| コミットSHA | 引数としてGitHub SHAが渡されること |

### 実行可否判定

コマンドライン引数としてgithubShaとgithubHeadShaが渡されること。

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | デフォルト値 | 説明 |
|-------------|-----|-----|-------------|------|
| githubSha | string | Yes | なし | ビルド元のGitコミットSHA |
| githubHeadSha | string | Yes | なし | PR HeadのGitコミットSHA |
| tarballDirectory | string | No | os.tmpdir()/vercel-nextjs-preview-tarballs | tarball出力先ディレクトリ |

### 入力データソース

| データソース | 形式 | 説明 |
|-------------|------|------|
| lerna.json | JSON | 現在のバージョン情報 |
| packages/next-swc/native/*.node | バイナリ | ネイティブバイナリ |
| crates/next-napi-bindings/npm/ | ディレクトリ | プラットフォーム別パッケージ |
| Git | Git | コミットハッシュ、コミット日付 |

## 出力仕様

### 出力データ

| 出力先 | 形式 | 説明 |
|-------|------|------|
| {tarballDirectory}/{packageName}/*.tgz | tarball | 各パッケージのtarball |

### 出力ファイル仕様

| 項目 | 内容 |
|-----|------|
| ファイル名 | npm packが生成するファイル名（{name}-{version}.tgz） |
| 出力先 | {tarballDirectory}/{packageName}/ |
| 文字コード | バイナリ（tar.gz形式） |
| 区切り文字 | 該当なし |

## 処理フロー

### 処理シーケンス

```
1. 出力ディレクトリ作成
   └─ tarballDirectory を再帰的に作成
2. Gitメタデータ取得（並列）
   └─ git rev-parse --short {githubSha} → 短縮SHA
   └─ git show -s --format=%cd --date=format:%Y%m%d {githubSha} → 日付
3. プレビューバージョン生成
   └─ {semverStable}-preview-{shortSha}-{dateString}
4. ネイティブバイナリtarball作成（並列）
   └─ 各プラットフォーム: バイナリコピー → バージョン更新 → npm pack
   └─ バイナリが存在しないプラットフォームはスキップ
5. lernaパッケージ一覧取得
   └─ pnpm --silent lerna list --json
6. 依存関係URL生成
   └─ vercel-packages.vercel.app/next/commits/{githubHeadSha}/{packageName}
7. パッケージtarball作成
   └─ 各公開パッケージ: バージョン更新 → 依存関係URL書き換え → npm pack
8. プレビューURL出力
   └─ vercel-packages の next パッケージURL
```

### フローチャート

```mermaid
flowchart TD
    A[バッチ開始: create-preview-tarballs] --> B[出力ディレクトリ作成]
    B --> C[Git短縮SHA・日付取得]
    C --> D[プレビューバージョン生成]
    D --> E[ネイティブバイナリtarball作成（並列）]
    E --> F[lernaパッケージ一覧取得]
    F --> G[各パッケージのバージョン・依存関係更新]
    G --> H[npm packでtarball作成]
    H --> I[プレビュービルドURL出力]
    I --> J[バッチ終了]
```

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

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

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

| 処理 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| 該当なし | - | - | データベース操作なし |

### テーブル別操作詳細

該当なし。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| ENOENT | ファイル不在 | ネイティブバイナリが存在しない | 警告出力してスキップ（正常動作） |
| NPM_PACK_FAILED | パッケージングエラー | npm pack失敗 | パッケージの整合性を確認 |
| GIT_REV_PARSE_FAILED | Git操作エラー | コミットSHAが不正 | 正しいSHAを指定 |

### リトライ仕様

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

### 障害時対応

処理失敗時はprocess.exit(1)で終了する。CI環境ではジョブの再実行で対応する。

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

| 項目 | 内容 |
|-----|------|
| トランザクション範囲 | パッケージ単位 |
| コミットタイミング | 各tarball生成時 |
| ロールバック条件 | なし（tarballディレクトリの削除で対応） |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定処理件数 | ネイティブ: 約10プラットフォーム + 通常パッケージ: 約10-15 |
| 目標処理時間 | 数分 |
| メモリ使用量上限 | 通常のNode.jsプロセスメモリ |

## 排他制御

tarballディレクトリ内でパッケージ名ごとにサブディレクトリを分離することで、並列実行時の衝突を回避している。

## ログ出力

| ログ種別 | 出力タイミング | 出力内容 |
|---------|--------------|---------|
| 開始ログ | バージョン決定時 | "Designated version: {version}" |
| 進捗ログ | tarball作成時 | "Created tarball {path}" |
| スキップログ | バイナリ不在時 | "Skipping next-swc platform '{platform}'..." |
| 終了ログ | 完了時 | プレビュービルドURL |

## 監視・アラート

| 監視項目 | 閾値 | アラート先 |
|---------|-----|----------|
| 処理時間 | 15分 | CI/CD通知 |
| 終了コード | 0以外（process.exit(1)） | CI/CDパイプライン |

## 備考

- エントリポイント: `scripts/create-preview-tarballs.js`
- プレビューバージョン形式: `{major}.{minor}.{patch}-preview-{shortSha}-{YYYYMMDD}`
- vercel-packages はパッケージ名をtarballパスから抽出するため、tarballディレクトリ内にパッケージ名のサブディレクトリを作成
- ネイティブバイナリが存在しないプラットフォームは警告のみでスキップ（ENOENT）
- 依存関係は vercel-packages.vercel.app のURLに書き換えられ、dependencies/devDependencies/peerDependencies/optionalDependencies すべてが対象
- `next` パッケージのoptionalDependenciesにはnext-swcの各プラットフォームパッケージが追加される
