# バッチ設計書 17-lerna:publish

## 概要

本ドキュメントは、Decap CMSプロジェクトにおけるパッケージ公開バッチ `lerna:publish` の設計仕様を定義する。本バッチはLernaを使用して、変更のあるパッケージをnpmレジストリに公開する。

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

本バッチは、Decap CMSモノレポ内の複数パッケージをnpmレジストリに一括公開するためのスクリプトである。Lernaの `from-package` モードを使用し、各パッケージのpackage.jsonに記載されたバージョンとnpmレジストリ上のバージョンを比較して、未公開のバージョンのみを公開する。

**業務上の目的・背景**：Decap CMSはモノレポ構成で複数のnpmパッケージ（decap-cms-core, decap-cms-app, 各種バックエンド・ウィジェットパッケージ等）を管理している。これらのパッケージを個別に公開するのは煩雑であるため、Lernaを使用して一括公開する仕組みが必要である。GitHub Actionsの Publish Packages ワークフロー（.github/workflows/publish.yml）から `decap-*@*` 形式のタグpush時に自動的にトリガーされる。

**バッチの実行タイミング**：`decap-*@*` 形式のタグがpushされた時に、GitHub Actionsから自動実行される。ビルドとテストが成功した後に実行される。OIDCトラステッドパブリッシャーを使用するため、NODE_AUTH_TOKENは不要。

**主要な処理内容**：
1. Lernaが各パッケージのバージョンをnpmレジストリと比較
2. 未公開バージョンが存在するパッケージを特定
3. 対象パッケージをnpmレジストリに公開（--yes で確認プロンプトをスキップ、--no-private でprivateパッケージを除外）

**前後の処理との関連**：Publish Packagesワークフローにおいて、npm ci -> npm run build -> npm run test:ci の後に本バッチが実行される。lerna.json でバージョニング設定（independent, conventionalCommits）が管理されている。公開の巻き戻しには No.24 scripts/revert_publish.sh が使用される。

**影響範囲**：npmレジストリ上のパッケージバージョンが更新される。公開されたパッケージは世界中のnpmユーザーがインストール可能になる。

## バッチ種別

リリース（パッケージ公開 - npmレジストリへの配布）

## 実行スケジュール

| 項目 | 内容 |
|-----|------|
| 実行頻度 | イベント駆動 |
| 実行時刻 | イベント発生時 |
| 実行曜日 | なし |
| 実行日 | なし |
| トリガー | `decap-*@*` 形式のタグpush |

## 実行条件

### 前提条件

| 条件 | 説明 |
|-----|------|
| Node.js | Node.js 24.x がインストールされていること |
| 依存パッケージ | `npm ci` で依存関係がインストール済みであること |
| ビルド完了 | `npm run build` が成功していること |
| テスト完了 | `npm run test:ci` が成功していること |
| Git | fetch-depth: 0 で完全な履歴がチェックアウトされていること |
| npm認証 | OIDCトラステッドパブリッシャーが設定されていること |
| environment | production環境が設定されていること（GitHub Actions） |

### 実行可否判定

タグが `decap-*@*` パターンに一致する場合のみPublish Packagesワークフローがトリガーされる。ビルドとテストが成功した場合のみ公開処理に進む。

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | デフォルト値 | 説明 |
|-------------|-----|-----|-------------|------|
| --yes | フラグ | Yes | 有効 | 確認プロンプトをスキップ |
| --no-private | フラグ | Yes | 有効 | privateパッケージを公開対象から除外 |
| --loglevel | オプション | No | success（lerna.json） | ログレベル（CIでは silly に上書き） |

### 入力データソース

| データソース | 形式 | 説明 |
|-------------|------|------|
| packages/*/package.json | JSON | 各パッケージのバージョン情報 |
| lerna.json | JSON | Lernaのバージョニング設定（independent, conventionalCommits） |
| npmレジストリ | API | 各パッケージの公開済みバージョン情報 |
| packages/*/dist/ | ビルド成果物 | 公開対象のビルド済みパッケージ |

## 出力仕様

### 出力データ

| 出力先 | 形式 | 説明 |
|-------|------|------|
| npmレジストリ | npmパッケージ | 公開されたパッケージ |
| 標準出力 | テキスト | 公開処理のログ |
| プロセス終了コード | 数値 | 0: 成功、1以上: 失敗 |

### 出力ファイル仕様

本バッチはローカルファイル出力を行わない。npmレジストリへのパッケージ公開のみ。

## 処理フロー

### 処理シーケンス

```
1. Lerna初期化
   └─ lerna.json から設定を読み込み（packages, version: independent, npmClient: npm）
2. パッケージスキャン
   └─ packages/* 配下の各パッケージを検出
3. バージョン比較（from-package モード）
   ├─ 各パッケージのpackage.jsonバージョンを取得
   ├─ npmレジストリの公開済みバージョンを取得
   └─ 未公開バージョンのパッケージを特定
4. パッケージ公開
   ├─ privateパッケージを除外（--no-private）
   ├─ 対象パッケージをnpm publishで順次公開
   └─ OIDCトラステッドパブリッシャーで認証
5. 公開結果のログ出力
```

### フローチャート

```mermaid
flowchart TD
    A[タグpush: decap-*@*] --> B[npm ci]
    B --> C[npm run build]
    C --> D[npm run test:ci]
    D --> E{ビルド・テスト成功?}
    E -->|失敗| Z[エラー終了]
    E -->|成功| F[lerna publish from-package]
    F --> G[packages/*/package.jsonスキャン]
    G --> H[npmレジストリのバージョンと比較]
    H --> I{未公開パッケージあり?}
    I -->|なし| J[公開対象なし - 正常終了]
    I -->|あり| K[対象パッケージをnpm publish]
    K --> L{公開成功?}
    L -->|失敗| Z
    L -->|成功| M[バッチ正常終了]
```

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

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

本バッチはデータベースへのアクセスを行わない。npmレジストリへのHTTPリクエストのみ。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 1 | 認証エラー | OIDCトラステッドパブリッシャーの設定不備 | npmレジストリのOIDC設定を確認 |
| 1 | バージョン重複 | 同一バージョンが既に公開済み | バージョンを更新して再タグ |
| 1 | ビルド成果物なし | distディレクトリが空 | ビルドを再実行 |
| 1 | ネットワークエラー | npmレジストリへの接続失敗 | 再実行またはnpmレジストリの状態を確認 |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | なし（タグの再pushで再トリガー） |
| リトライ間隔 | なし |
| リトライ対象エラー | なし |

### 障害時対応

公開に失敗した場合は、GitHub Actionsのログで原因を確認する。部分的に公開された場合（一部パッケージのみ成功）は、No.24 scripts/revert_publish.sh で巻き戻すか、未公開分のみ再度タグpushで対応する。loglevel: silly でCIでは詳細なデバッグ情報が出力される。

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

| 項目 | 内容 |
|-----|------|
| トランザクション範囲 | パッケージ単位（各パッケージの公開は独立） |
| コミットタイミング | 各パッケージの公開完了時 |
| ロールバック条件 | npm unpublish または scripts/revert_publish.sh で巻き戻し |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定処理件数 | packages/ 配下の非privateパッケージ数 |
| 目標処理時間 | ビルド・テスト含め数十分以内 |
| メモリ使用量上限 | Node.jsデフォルトヒープサイズ |

## 排他制御

GitHub Actionsのタグトリガーにより、同一タグに対して重複実行されることはない。Lernaのfrom-packageモードにより、既に公開済みのバージョンは自動的にスキップされる。production環境の設定により、承認要件やデプロイメント保護が適用される可能性がある。

## ログ出力

| ログ種別 | 出力タイミング | 出力内容 |
|---------|--------------|---------|
| 開始ログ | Lerna初期化時 | Lernaバージョン、設定情報 |
| デバッグログ | 処理中 | Node/npmバージョン、npm設定、Git状態、レジストリ情報（Debug step） |
| 進捗ログ | パッケージ公開中 | 各パッケージの公開状況 |
| 終了ログ | 公開完了時 | 公開されたパッケージ一覧 |
| エラーログ | エラー発生時 | 公開失敗の詳細情報 |

## 監視・アラート

| 監視項目 | 閾値 | アラート先 |
|---------|-----|----------|
| ジョブ失敗 | 1回 | GitHub Actions通知 |
| 公開パッケージ数 | 0（公開対象なし） | ログ確認 |

## 備考

- 本バッチは `npm run lerna:publish` コマンドで実行される（CI上では `--loglevel silly` オプション付き）
- Lernaバージョニング: independent モード（各パッケージが独自バージョンを持つ）
- conventionalCommits: true（Conventional Commitsに基づくバージョニング）
- 許可ブランチ: main, release/*（lerna.json command.version.allowBranch）
- ignoreChanges: `**/__fixtures__/**`, `**/__tests__/**`, `**/*.md` はバージョン変更の検出対象外
- OIDCトラステッドパブリッシャーを使用するため、NODE_AUTH_TOKENのシークレット設定は不要
- GitHub Actionsのpermissions: contents: read, id-token: write が必要
- environment: production によりデプロイメント保護ルールが適用される可能性がある
