# バッチ設計書 11-publish-tag.yml

## 概要

本ドキュメントは、GitHub Actions ワークフロー `publish-tag.yml` の設計仕様を記載したバッチ設計書です。タグ付きリリースの公開処理を行うワークフローの詳細を説明します。

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

このバッチは、Ghosttyプロジェクトの正式リリース版をユーザーに公開するための最終段階の処理を実行します。バージョンタグ付きリリースのAppcastファイルをCloudflare R2ストレージにアップロードし、macOSユーザーがSparkleフレームワーク経由で自動更新を受け取れるようにします。

**業務上の目的・背景**：ソフトウェアリリースにおいて、ビルド成果物をユーザーに配布する最終段階が必要です。特にmacOSアプリケーションでは、Sparkleフレームワークを使用した自動更新機能のためにAppcastファイルの公開が必須であり、本ワークフローはその公開処理を自動化します。手動での公開作業を排除し、一貫性のあるリリースプロセスを確保します。

**バッチの実行タイミング**：手動実行（workflow_dispatch）のみ。リリースマネージャーがバージョン番号を指定して明示的にトリガーします。リリースタグ作成後、ビルド成果物の検証が完了した時点で実行されます。

**主要な処理内容**：
1. バージョン入力値の形式検証（vX.Y.Z形式であることを確認）
2. バージョン番号の抽出（v接頭辞の除去）
3. リリースファイルの存在検証（tarball、署名ファイル、DMG、Appcast等）
4. ステージングされたAppcastファイルのダウンロード
5. Appcastファイルのリネームと準備
6. Cloudflare R2へのAppcastファイルのアップロード

**前後の処理との関連**：release-tag.yml ワークフローで作成されたリリース成果物が前提条件となります。本ワークフローは、リリースファイルがR2ストレージに正しくアップロードされた後に実行される必要があります。後続の処理は特になく、本ワークフローがリリースプロセスの最終段階となります。

**影響範囲**：Cloudflare R2の ghostty-release バケットに保存されるAppcastファイルが更新されます。これにより、Ghosttyアプリケーションの自動更新機能を利用するすべてのmacOSユーザーに新バージョンが通知されます。

## バッチ種別

データ連携 / リリース公開

## 実行スケジュール

| 項目 | 内容 |
|-----|------|
| 実行頻度 | 随時（リリース時） |
| 実行時刻 | 指定なし |
| 実行曜日 | 指定なし |
| 実行日 | 指定なし |
| トリガー | 手動（workflow_dispatch） |

## 実行条件

### 前提条件

| 条件 | 説明 |
|-----|------|
| リリースファイルの存在 | 指定バージョンのリリースファイルがR2に存在すること |
| バージョン形式 | vX.Y.Z形式（例：v1.0.0）であること |
| 実行権限 | リポジトリへのwrite権限を持つユーザー |

### 実行可否判定

バージョン入力値が `^v[0-9]+\.[0-9]+\.[0-9]+$` の正規表現パターンに一致するかを検証します。一致しない場合はエラーで終了します。また、リリースファイルの存在確認をHTTP HEADリクエストで行い、全ファイルのステータスコードが200であることを確認します。

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | デフォルト値 | 説明 |
|-------------|-----|-----|-------------|------|
| version | string | Yes | なし | デプロイするバージョン（vX.Y.Z形式） |

### 入力データソース

| データソース | 形式 | 説明 |
|-------------|------|------|
| release.files.ghostty.org | HTTP/ファイル | リリースファイルのホスト |
| appcast-staged.xml | XML | ステージング済みAppcastファイル |
| ghostty-${VERSION}.tar.gz | tarball | ソースtarball |
| ghostty-${VERSION}.tar.gz.minisig | 署名 | tarball署名ファイル |
| ghostty-source.tar.gz | tarball | ソースtarball（バージョンなし） |
| ghostty-source.tar.gz.minisig | 署名 | ソースtarball署名ファイル |
| ghostty-macos-universal.zip | ZIP | macOSユニバーサルバイナリ |
| ghostty-macos-universal-dsym.zip | ZIP | macOSデバッグシンボル |
| Ghostty.dmg | DMG | macOSインストーラー |

## 出力仕様

### 出力データ

| 出力先 | 形式 | 説明 |
|-------|------|------|
| ghostty-release バケット | R2 | Cloudflare R2ストレージ |
| appcast.xml | XML | 更新情報を含むAppcastファイル |

### 出力ファイル仕様

| 項目 | 内容 |
|-----|------|
| ファイル名 | appcast.xml |
| 出力先 | ghostty-release バケットのルート |
| 文字コード | UTF-8 |
| 形式 | XML（Sparkle Appcast形式） |

## 処理フロー

### 処理シーケンス

```
1. バージョン検証（setupジョブ）
   └─ 入力されたバージョンがvX.Y.Z形式かを正規表現で検証
2. バージョン抽出
   └─ v接頭辞を除去してGITHUB_OUTPUTに保存
3. リリースファイル検証（uploadジョブ）
   └─ curlでHTTP HEADリクエストを送信し、全ファイルの存在を確認
4. Appcastダウンロード
   └─ appcast-staged.xmlをダウンロードしてappcast.xmlにリネーム
5. R2アップロード準備
   └─ blobディレクトリを作成しappcast.xmlを配置
6. R2アップロード実行
   └─ ryand56/r2-upload-actionでCloudflare R2にアップロード
```

### フローチャート

```mermaid
flowchart TD
    A[ワークフロー開始] --> B[バージョン形式検証]
    B -->|無効| C[エラー終了]
    B -->|有効| D[バージョン番号抽出]
    D --> E[リリースファイル存在確認]
    E -->|ファイルなし| F[エラー終了]
    E -->|全ファイル存在| G[Appcastダウンロード]
    G --> H[appcast.xmlにリネーム]
    H --> I[R2にアップロード]
    I --> J[ワークフロー完了]
```

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

本ワークフローではデータベース操作は行いません。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 1 | バージョン形式エラー | vX.Y.Z形式でないバージョンが入力された | 正しい形式でバージョンを再入力 |
| 1 | ファイル不在エラー | リリースファイルがR2に存在しない | release-tag.ymlの完了を確認後に再実行 |
| - | アップロードエラー | R2への接続失敗 | 認証情報を確認し再実行 |

### リトライ仕様

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

### 障害時対応

1. エラーログを確認し原因を特定
2. バージョン形式エラーの場合は正しい形式で再実行
3. ファイル不在エラーの場合はrelease-tag.ymlの実行状況を確認
4. R2接続エラーの場合はシークレット設定を確認

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

| 項目 | 内容 |
|-----|------|
| トランザクション範囲 | ファイルアップロード単位 |
| コミットタイミング | アップロード完了時 |
| ロールバック条件 | アップロード失敗時は自動ロールバック |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定処理件数 | 1ファイル |
| 目標処理時間 | 5分以内 |
| メモリ使用量上限 | 指定なし |

## 排他制御

同時実行は許可されません。concurrencyグループ `${{ github.workflow }}` により、同一ワークフローの複数インスタンスの同時実行を防止します。`cancel-in-progress: false` により、実行中のワークフローはキャンセルされません。

## ログ出力

| ログ種別 | 出力タイミング | 出力内容 |
|---------|--------------|---------|
| 開始ログ | ワークフロー開始時 | GitHub Actions標準ログ |
| 検証ログ | バージョン検証時 | "Version is valid: vX.Y.Z" |
| エラーログ | エラー発生時 | エラーメッセージと終了コード |
| 終了ログ | ワークフロー終了時 | ジョブ完了ステータス |

## 監視・アラート

| 監視項目 | 閾値 | アラート先 |
|---------|-----|----------|
| ワークフロー失敗 | 1回 | GitHub通知 |
| 実行時間 | 10分超過 | GitHub Actions UI |

## 備考

- 本ワークフローはリリースプロセスの最終段階であり、手動実行のみをサポート
- ryand56/r2-upload-action（v1.4）を使用してCloudflare R2にアップロード
- リリースアーティファクトの整合性を保つため、同時実行制御が厳格に設定されている
