# バッチ設計書 21-publish-assets

## 概要

本ドキュメントは、Roslynプロジェクトのビルド成果物（NuGetパッケージ）を外部リポジトリに公開するためのスクリプト `eng/publish-assets.ps1` の設計を記述する。

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

このバッチは、Roslynプロジェクトのビルドによって生成されたNuGetパッケージを、nuget.orgやAzure DevOpsフィードなどの外部リポジトリに公開する処理を実行する。

**業務上の目的・背景**：Roslynコンパイラおよび関連ライブラリは、Visual Studioやその他の.NET開発ツールに不可欠なコンポーネントである。本バッチは、ビルドされたNuGetパッケージを適切なフィードに公開することで、開発者コミュニティや依存プロジェクトがこれらのパッケージを利用できるようにする。公開操作はビルド後のオプションかつ再実行可能な操作として設計されており、ネットワーク障害等による失敗からの復旧が可能となっている。

**バッチの実行タイミング**：本バッチはビルド完了後の任意のタイミングで手動実行、またはCIパイプラインの一部として自動実行される。リリースブランチへのマージ後やリリースタグの付与時に実行されることが多い。

**主要な処理内容**：
1. ビルド設定（configuration）の検証
2. ブランチに対応する公開設定データの取得
3. NuGetパッケージ種別（Shipping/NonShipping/PerBuildPreRelease）ごとのパッケージ公開
4. 各パッケージに対応するフィードURLの特定とAPIキーの取得
5. dotnet nuget pushコマンドによるパッケージの公開

**前後の処理との関連**：本バッチはビルドバッチ（eng/build.ps1）の後続処理として位置づけられる。ビルドによって artifacts ディレクトリ配下に生成されたNuGetパッケージを入力として受け取り、外部フィードへの公開を行う。公開後は署名検証やシンボルサーバへの登録など、追加の公開後処理が実行される場合がある。

**影響範囲**：このバッチはnuget.org、Azure DevOpsフィード（pkgs.dev.azure.com）などの外部パッケージリポジトリに影響を与える。公開されたパッケージは.NETエコシステム全体で利用可能となり、依存プロジェクトのビルドに影響を与える可能性がある。

## バッチ種別

パッケージ公開（NuGet公開）

## 実行スケジュール

| 項目 | 内容 |
|-----|------|
| 実行頻度 | 随時（リリース時） |
| 実行時刻 | 指定なし |
| 実行曜日 | 指定なし |
| 実行日 | 指定なし |
| トリガー | 手動/CIパイプライン |

## 実行条件

### 前提条件

| 条件 | 説明 |
|-----|------|
| ビルド完了 | artifacts ディレクトリにNuGetパッケージが生成されていること |
| 設定パラメータ | -configuration パラメータが指定されていること |
| 認証情報 | nuget.orgへ公開する場合は -nugetApiKey が設定されていること |
| ネットワーク | 公開先フィードへのネットワーク接続が確立されていること |

### 実行可否判定

configurationパラメータが空の場合はエラーで終了する。公開対象のNuGetパッケージが存在しない場合、処理はスキップされる。

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | デフォルト値 | 説明 |
|-------------|-----|-----|-------------|------|
| configuration | string | Yes | "" | ビルド構成（Debug/Release） |
| test | switch | No | false | テストモードで実行（実際の公開を行わない） |
| prValidation | switch | No | false | PR検証モード（vsフィードに公開） |
| nugetApiKey | string | No | "" | nuget.org用のAPIキー |

### 入力データソース

| データソース | 形式 | 説明 |
|-------------|------|------|
| artifacts/packages/{nugetKind}/*.nupkg | NuGetパッケージ | 公開対象のNuGetパッケージファイル |
| PublishData/PublishData.json | JSON | ブランチごとの公開設定 |
| PublishData/FeedData.json | JSON | フィード名とURLのマッピング |
| PublishData/PackagesData.json | JSON | パッケージ名とフィード名のマッピング |

## 出力仕様

### 出力データ

| 出力先 | 形式 | 説明 |
|-------|------|------|
| nuget.org | NuGetパッケージ | nuget.orgへ公開されるパッケージ |
| pkgs.dev.azure.com | NuGetパッケージ | Azure DevOpsフィードへ公開されるパッケージ |

### 出力ファイル仕様

本バッチはファイル出力を行わず、外部フィードへのパッケージ公開のみを行う。

## 処理フロー

### 処理シーケンス

```
1. 設定検証
   └─ configuration パラメータの存在チェック
2. SDK初期化
   └─ Ensure-DotnetSdk による .NET SDK の確保
3. 公開データ取得
   └─ GetBranchPublishData によるブランチ設定の読み込み
4. エントリ検証
   └─ nugetKind の妥当性確認（Shipping/NonShipping/PerBuildPreRelease）
5. パッケージ公開ループ
   └─ 各 nugetKind ディレクトリ内のパッケージを順次公開
6. 個別パッケージ処理
   └─ フィード特定 → APIキー取得 → dotnet nuget push 実行
```

### フローチャート

```mermaid
flowchart TD
    A[バッチ開始] --> B{configuration指定あり?}
    B -->|なし| C[エラー終了]
    B -->|あり| D[SDK初期化]
    D --> E[公開データ取得]
    E --> F{nugetKind検証}
    F -->|不正| G[エラー終了]
    F -->|正常| H[パッケージディレクトリ取得]
    H --> I[パッケージループ開始]
    I --> J{.nupkgファイルあり?}
    J -->|なし| K[ループ終了]
    J -->|あり| L{シンボルパッケージ?}
    L -->|はい| M[スキップ]
    L -->|いいえ| N[フィード名取得]
    N --> O{arcadeフィード?}
    O -->|はい| P[スキップ]
    O -->|いいえ| Q[URL/APIキー取得]
    Q --> R{テストモード?}
    R -->|はい| S[スキップ]
    R -->|いいえ| T[dotnet nuget push]
    M --> I
    P --> I
    S --> I
    T --> I
    K --> U[バッチ終了]
```

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

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

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

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 1 | パラメータ不足 | configuration未指定 | -configurationパラメータを指定して再実行 |
| 1 | ファイル不存在 | 公開対象パッケージが存在しない | ビルドを再実行してパッケージを生成 |
| 1 | 設定エラー | パッケージに対応するフィードが未設定 | PackagesData.jsonにパッケージを追加 |
| 1 | 設定エラー | フィード名に対応するURLが未設定 | FeedData.jsonにフィードを追加 |
| 1 | 公開失敗 | dotnet nuget pushが失敗 | ネットワーク状態・認証情報を確認して再実行 |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | なし（スクリプトレベル） |
| リトライ間隔 | - |
| リトライ対象エラー | - |

### 障害時対応

本バッチは再実行可能（idempotent）として設計されている。公開失敗時は、エラーメッセージを確認し、原因を解消した後に再実行する。既に公開済みのパッケージを再度pushしようとした場合、nugetサーバー側でエラーとなるが、同一バージョンのパッケージ内容が同一であれば実質的な問題は発生しない。

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

| 項目 | 内容 |
|-----|------|
| トランザクション範囲 | パッケージ単位 |
| コミットタイミング | 各パッケージ公開完了時 |
| ロールバック条件 | 公開失敗したパッケージはスキップ（全体はロールバックされない） |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定処理件数 | 数十〜数百パッケージ |
| 目標処理時間 | パッケージ数とネットワーク速度に依存 |
| メモリ使用量上限 | 特に制限なし |

## 排他制御

同一パッケージの同時公開は避けるべきである。CIパイプラインでは通常、ビルドごとに一意のバージョン番号が付与されるため、競合は発生しない。

## ログ出力

| ログ種別 | 出力タイミング | 出力内容 |
|---------|--------------|---------|
| 開始ログ | 各パッケージ処理開始時 | "Publishing {nupkg}" |
| スキップログ | シンボルパッケージ検出時 | "Skipping symbol package {nupkg}" |
| スキップログ | arcadeフィード指定時 | "Skipping publishing for {nupkg} as it is published by arcade" |
| エラーログ | エラー発生時 | 例外メッセージとスタックトレース |

## 監視・アラート

| 監視項目 | 閾値 | アラート先 |
|---------|-----|----------|
| 公開失敗 | 1件以上 | CI通知（Azure DevOps） |
| 処理時間 | 環境依存 | CI通知 |

## 備考

- 公開処理はビルド出力に依存するため、ソースコードの存在を前提としない設計となっている
- prValidation モードでは全てのパッケージが "vs" フィードに公開される
- Azure DevOpsへの公開では、パイプラインで認証されるため、APIキーには任意の非空文字列（"AzureArtifacts"）を使用する
- TLS 1.2がセキュリティプロトコルとして強制される
