リリース手順書
暫定的な手動プロセス。 このランブックでは、
release-stable-manual.ymlを使用して本日安定版リリースを公開する方法について説明します。これは release-plz が導入されて置き換えられるまで有効なプロセスとして残ります。その移行はまだ行われていません(今後の方向性を参照)。ここにあるものが何か重く感じられるとしても、それは意図的な摩擦です。私たちにはまだ、それを安全に取り除けるだけの自動化の規律がありません。
最終確認は v0.8.2 リリースサイクルに対して行われました。
7つのステップで進めるプロセス
CHANGELOG-next.mdを changelog スキルを使って生成する(バイナリサイズの表付き)- バージョンアップのPRを開いてマージする
- リリースワークフローを
actでローカルにドライラン実行する - 手動ディスパッチで
Release Stableワークフローをトリガーする - プロンプトが表示されたら2つの環境ゲートを承認する
- リリースが存在し、アセットがダウンロード可能であることを検証する
- バージョン管理されたドキュメントのデプロイ
これがプロセス全体です。それ以外(crates.io、Docker、ウェブサイトの再デプロイ、Scoop、AUR、Discord、ツイート)は、下流ジョブとして自動的に実行されます。Homebrew Core は独自の autobump サービスを通じて安定版の GitHub リリースを検出します。ジョブが明示的に失敗するか、Homebrew の外部 bump が古いままになっている場合を除き、これらについて何かする必要はありません。
ステップ1: CHANGELOG-next.md を生成する
changelog-generation スキルを実行して CHANGELOG-next.md を生成します。その完全な手順は .claude/skills/changelog-generation/SKILL.md にあります。
このスキルは、最後の安定版タグから HEAD までの git log から changelog を生成し、GitHub GraphQL を介してコントリビューターを解決して、ファイルを書き込みます。結果を短命なブランチに直接コミットして、バージョン引き上げ PR(ステップ 2)に含めるか、差分が大きい場合は別の先行 PR として開いてください。
以前に中断したリリースサイクルで CHANGELOG-next.md がすでに存在する場合は、再利用する前に内容が正確かどうか確認してください。
このファイルには、プリアンブルの直後に ## In brief セクションを置く必要があります。短い段落を2つ、合計255文字以内で記述し、そのリリースが何であるかを説明してください。X と Discord のお知らせワークフローはこのセクションを公開し、その後にプリアンブルのコミット数と貢献者数、そしてウェブサイトのリリース記事へのリンク(記事がまだない場合は GitHub リリース)が続きます。このセクションがない場合、ワークフローは最初の Highlights の箇条書きにフォールバックし、それもない場合は生のコミット一覧を使用します。スキルのスタイルルールと参考例は SKILL.md にあります。
投稿せずに、公開済みの任意のタグのアナウンス文をプレビューします:
gh workflow run tweet-release.yml -f release_tag=vX.Y.Z -f dry_run=true
gh workflow run discord-release.yml -f release_tag=vX.Y.Z -f dry_run=true
作成されたテキストは、実行のジョブサマリーに表示されます。
バイナリサイズの変化を記録
バージョンを上げる前に、前回のリリースと現在の master のリリースバイナリを計測し、compare の表を CHANGELOG-next.md の Contributors の前に、text コードブロックの中に入れた ## Binary size セクションとして貼り付けます。CHANGELOG-next.md がリリース本文になるため、この表はリリースとともに公開されます。この表が報告するのは、1 台のマシンでの 2 つのソースリビジョンのローカルビルドです。リリースワークフローがターゲットごとに固定のツールチェーンとターゲットフラグでビルドする公開アーカイブは計測しないため、計測したターゲットトリプルを表の横に記載してください。
scripts/ci/binary_size_report.sh は Linux または macOS で実行され、Python 3.11 以降が必要です。その measure コマンドは、dev/ci/dependency-footprint.toml に定義された zeroclaw の各ポリシープロファイルについて、release Cargo プロファイルを用いて zeroclaw バイナリをビルドします。各ポリシープロファイルについて、レポートはバイナリのバイト数、SHA-256、パス、ターゲットトリプル、および解決済みの機能(features)を記録します。レポートはまた、Cargo.toml からの release Cargo プロファイルの設定、Cargo および rustc のバージョン、コード生成を変化させるビルド変数(RUSTFLAGS、CARGO_ENCODED_RUSTFLAGS、CARGO_BUILD_RUSTFLAGS、ターゲットの RUSTFLAGS およびリンカー変数、ZEROCLAW_BUILD_ID)、ワークツリーダイジェストを伴うソースリビジョン、そして Cargo.lock のダイジェストを記録します。
チェックアウト内に追跡されていないファイルがあると、そのチェックアウトの次の計測が dirty とマークされるため、各側は同じマシンと同じユーザーアカウント上で、それぞれ専用のクリーンなチェックアウトから計測し、レポートは両方のチェックアウトの外に保存してください:
git worktree add ../zeroclaw-vPREV vPREV
./scripts/ci/binary_size_report.sh measure --repo-root ../zeroclaw-vPREV \
--profile foundation --profile agent-runtime \
--profile root-default --profile standard-distribution \
--target-dir ../zeroclaw-vPREV/target-size --output ../size-vPREV.json
./scripts/ci/binary_size_report.sh measure \
--profile foundation --profile agent-runtime \
--profile root-default --profile standard-distribution \
--target-dir target-size --output ../size-next.json
./scripts/ci/binary_size_report.sh compare ../size-vPREV.json ../size-next.json \
--output ../size-compare.json
これらのコマンドは、ユーザーが実行するものを表す 4 つのポリシープロファイルを計測します: foundation(--no-default-features)、agent-runtime、root-default(ソースビルドで得られる Cargo のデフォルト)、standard-distribution(リリースアーカイブの機能セット)です。--profile を指定しない場合、measure は ci-all や hardware-probe を含むすべての zeroclaw ポリシープロファイルをビルドします。これらは出荷されるビルドではなく、CI とハードウェアの集約です。別のターゲット向けにビルドするには --target <triple> を渡します。指定しない場合、measure はホストのトリプルに対して standard-distribution の機能を解決するため、Cargo.toml のターゲットごとの除外が、そのターゲットのリリースアーカイブと同じように適用されます。
compare は表を出力します。表の見出しには各側のリビジョンと、作業ツリーに未コミットの変更があったかどうか (dirty) が示されます。JSON の結果は --output で指定されたファイルに書き込まれ、--output を指定しない場合は標準出力に書き出されます。
バイナリには、CARGO_HOME 配下のレジストリのソースパスと、git describe または ZEROCLAW_BUILD_ID から得られるビルドスタンプが埋め込まれます。そのため、同じソースコードでも別のマシンやユーザーアカウントで計測すると異なるバイト列が生成されることがあり、compare はそのようなペアを検出できません。記録されない他の入力もバイナリを変化させます。CC や CFLAGS などの C コンパイラ変数、macOS SDK とデプロイメントターゲット、ユーザーレベルの ~/.cargo/config.toml にある Cargo 設定がこれに該当します。両方の側は、同じマシン・同じユーザーアカウント、同じシェル環境から計測してください。
measure は、RUSTC または CARGO_BUILD_RUSTC が設定されている場合、CARGO_PROFILE_RELEASE_* 変数が release Cargo プロファイルを上書きしている場合、選択されたポリシープロファイルが zeroclaw パッケージをビルドしない場合、またはポリシープロファイルのターゲットディレクトリがチェックアウト内にあるのに Git で無視されていない場合、ビルドの開始を拒否します。ビルドのたびに、Cargo が想定と異なるパスで報告したバイナリは拒否します。例えば、--target を指定していないのに CARGO_BUILD_TARGET または build.target 設定が適用されている場合がこれに当たります。
compare は、Cargo または rustc のバージョン、ホスト、ターゲット、release Cargo プロファイル設定、記録されたビルド変数、ポリシー、ポリシープロファイルの集合のいずれかが異なるレポートを拒否します。レポート間で解決済みの機能またはバイナリパスが変更されたポリシープロファイルは、差分を算出する代わりに、追加された機能と削除された機能とともに比較不可として一覧表示されます。
各ポリシープロファイルは、独自のターゲットディレクトリ <target-dir>/<profile-id> でビルドされるため、依存関係のビルドがポリシープロファイルごとに繰り返されます。macOS arm64 では、これらのディレクトリのサイズは foundation が 0.8 GB、agent-runtime が 1.2 GB、root-default が 1.4 GB、standard-distribution が 2.5 GB でした。ポリシープロファイルの初回ビルドはフル fat-LTO リリースビルドで、完了までに数分かかります。ソースに変更がない場合の再実行では、再ビルドは行われずに完了します。表を変更履歴に記載したら、クリーンアップしてください:
rm -rf target-size
git worktree remove ../zeroclaw-vPREV
For the full target matrix, the job summary of the Cross-Platform Build workflow lists each binary’s bytes and SHA-256.
ステップ2: バージョンPRをバンプしてマージする
ワークスペースの Cargo.toml で workspace.package.version をバンプし、その後 2 つのリリーススクリプトを順番に実行します。まずリポジトリ全体のすべてのバージョン参照を同期します:
sh
./scripts/release/bump-version.sh --release # Cargo.toml からのバージョン
README のバッジ、Tauri の設定、ワークフローの説明例を更新し、cargo generate installers を介して仕様駆動のすべてのインストール対象を再生成します: install.sh、setup.bat、dist/aur/PKGBUILD、dist/aur/.SRCINFO、dist/scoop/zeroclaw.json、flake.nix、Dockerfile/Containerfile の機能セット、dev/ci/docker-tags.toml、docs/book/src/_snippets/install.md、README/プラットフォームドキュメント内の Unix 高速パスブロック、docs/book/src/setup/windows.md 内の Windows プレビルドブロック。バージョン、機能、アプリケーションパッケージングの値は Cargo.toml と [package.metadata.zeroclaw] から取得され、4 つの安定したインストール経路は xtask/src/generate/spec.rs の型付きコントラクトから取得されます。この更新により、これらの対象は自動的に同期されるため、生成領域を手動で編集しないでください。実際のリリースの提供状況は引き続き手動で記述され、ジェネレーターによって推測されることはありません。このスクリプトは、scripts/dev/refresh-nix-hashes.sh を介して Nix の git 依存関係ハッシュ(nix/hashes.json)も更新します。
--release を指定する場合、スクリプトがファイルを編集する前に、cargo、jq、nix-prefetch-git、perl、sha256sum、tomllib を使える Python 3.11 以降、PATH 上の Bash 4 以降、ロックファイル、Nix リフレッシュスクリプトが必要です。macOS では、新しい Bash をインストールし、Nix リフレッシャーが使うように PATH 上で /bin/bash より前に配置してください。ロックファイルの解決、Nix ハッシュ、インストーラーの生成のいずれかが失敗すると、スクリプトは停止します。失敗すると、それ以前の編集がワークツリーに残ることがあります。その場合は変更内容を確認し、報告された前提条件を修正してから再実行してください。不完全なバージョンアップはコミットしないでください。--release を指定しない場合、スクリプトはローカルでの準備に対して、ベストエフォートの動作を維持します。
タグ作成ヘルパー scripts/release/cut_release_tag.sh もリリースモードを使用します。準備段階で失敗した場合、コミット、フェッチ、タグ付け、プッシュの前に処理が停止します。通常のローカルモードは、タグ作成時のフォールバックではありません。
翻訳を更新してピン留めする
bump-version.sh がリリースバージョンを設定した後、ドキュメント翻訳カタログを更新し、対応するタグに固定します。カタログを別途準備した場合は、タグを作成する前にカバレッジを確認し、検証してください。
cargo mdbook stats
cargo mdbook check
次に、リリースラッパーを実行します:
sh
./scripts/release/refresh-translations.sh --model-provider anthropic.release
refresh-translations.sh は Cargo.toml からバージョンを読み取り(手入力は不要)、翻訳処理を実行し、カタログを zeroclaw-labs/zeroclaw-docs-translations サブモジュールにコミットしてプッシュし、そこで v{version} タグを作成し、そのタグに固定されたメインリポジトリの gitlink をステージします。サブモジュールがまだチェックアウトされていない場合は初期化します。読み取られる Cargo.toml のバージョンがリリースバージョンになるよう、bump-version.sh の後に実行してください。リリースがハードコードされたバックエンドに依存しないよう、設定済みのプロバイダーエイリアスを明示的に指定する必要があります。必要に応じて --config-dir を渡してください。--model-provider で選択したエイリアスは providers.models.<kind>.<alias> から解決されます。カタログがすでに最新の場合は --no-translate を使用するか、Cargo.toml のデフォルトを上書きするために --model-provider の前に明示的なバージョンを渡します。例:
./scripts/release/refresh-translations.sh 0.8.2 --model-provider anthropic.release
すべてをまとめてコミット:
chore: bump version to vX.Y.Z
PR が [workspace.package] rust-version またはピン留めされた Rust ツールチェーンも変更する場合は、単なるリリースの配管ではなく、互換性の変更として扱ってください。PR では新しい MSRV を明記し、ソースビルドのアップグレードパスを説明し、CI、Docker、インストーラー、および生成されたサーフェスがマージ前に新しい下限で一致していることを示してください。
PR を作成してください。type:ci、size:XS、および PR ラベラーが追加するパスラベルを付けます。PR がツールチェーンの最低バージョンを引き上げる場合は、risk:high も付与し、レーン D を経由させてください。
Core Team による独立した 2 件の承認がデフォルトです。ツールチェーンの下限およびリリースに関する変更は、expedited second-review lane の下で、その完全な証拠と、通常は 2 件のレビューが必要なこのカテゴリに対する明示的な正当化が揃っている場合に限り検討できます。タイムアウトによって、未解決の互換性またはリリース安全性に関する懸念が解消されることは決してありません。必須の CI がグリーンの場合にのみマージしてください。
Installer Drift ゲートは、生成された成果物が仕様と同期していない場合に CI で PR を失敗させるため、再生成の漏れがマージされることはありません。Validate Translations Pin ゲートは、固定されたコミットでサブモジュールを解決し、カタログのフォーマットと msgid の一致を検証するため、不正なピンもマージされることはありません。翻訳パイプラインの詳細については、Docs & Translations を参照してください。
crates.io Package Preflight ゲートは、[workspace.package] version が安定版の X.Y.Z に変更されたときに必ず実行されます。リリースセットに含まれるすべてのクレートをパッケージ化し、それぞれを独自の tarball からコンパイルします。レジストリトークンは使用しません。そのため、公開できないクレートを含むバージョン更新は、マージできません。バンプPRには約30分が追加されると想定してください。このゲートはマージキューでも再実行されます。失敗した場合は、まず Preflight ステップを確認してください。パッケージングまたはコンパイルのエラーは実際の問題であり、バンプPRで修正する必要があります。crates.io API のエラー、npm のインストール失敗、またはランナーのタイムアウトはインフラストラクチャの問題です。失敗したジョブのみを再実行し、再度 push しないでください。障害が続く場合は、必須 CI がグリーンになるまでバンプをマージせずに保留してください。リリース実行でも、GitHub Release の前に同じ preflight が独立して繰り返されます。
マージが正しく適用されたことを確認します:
sh
git fetch origin
git show origin/master:Cargo.toml | grep '^version'
# 表示する必要があります: version = "X.Y.Z"
ステップ3: act を使ってローカルでリリースワークフローをドライランする
Release Stable ワークフローは GitHub Actions のジョブグラフであり、Run workflow をクリックした瞬間に環境ゲートの承認ウィンドウを消費します。ワークフローのステップに不備がある場合(ビルドアーティファクトの欠落、古いパス、誰かが CI を更新せずに削除した codegen ステップなど)、その失敗が表面化するのは、すでにリリースウィンドウにコミットした 後 であり、バージョン PR はすでにマージされ、master は新しいバージョンになっています。復旧には、緊急修正ブランチをマージし、CI を再実行し、すでに完全リリース版として自身を宣伝しているツリー上で、時間的プレッシャーの中で出荷することが必要になります。
これに対する安価な保険は、GitHub Actionsのフォームを開く前に、まったく同じマージ済みのmasterコミット上で、同じジョブグラフをローカルで先に実行することです。actは、GitHubが使用しているのと同じactions/*エコシステムを使って、Dockerコンテナ内でGitHub Actionsのワークフローを実行します。これはクラウドランナーを完全に再現するものではなく、アーティファクトアップロードランタイム、GitHubが発行するOIDCトークン、環境シークレット、実際のリリースタグに依存するジョブにはアクセスできませんが、これまで遭遇したほぼすべてのリリース時CI失敗の原因となるビルドおよびテストのステップは実行します。
このステップはリリースごとに15〜20分の投資となります。通常のPRごとのCIでは表面化しなかった実際の不具合を検出してきました(失敗するワークフローはpushではなくworkflow_dispatchでのみ実行されるためです)。
1回限りのセットアップ
act はワークフローを実行します。最もクリーンなインストール方法は GitHub CLI 拡張機能です。これは gh 認証を継承し、すべてのワークフロー実行に実際の GITHUB_TOKEN を公開するためです:
-
GitHub CLI を https://cli.github.com からインストールしてください(Linux、macOS、Windows 対応)。一度だけ認証を行います:
gh auth login。 -
act拡張機能をインストールします:sh
gh extension install nektos/gh-actアーティファクトを生成するジョブでは、
actions/upload-artifactv7 とactions/download-artifactv8 が必要とするactのアーティファクトサービスプロトコルが必要ですが、現在リリースされているactのバージョンにはそれを実装したものはありません(本稿執筆時点の最新リリースまで確認済みです)。このヘルパーは、固定されたアーティファクトアクションを使用するジョブを開始する前に、インストール済みのactバージョンを事前チェックし、安全側に倒して停止します。検証されていないバージョンではジョブを実行しません。互換性のあるactリリースが公開され、実際のアーティファクトの往復処理で検証されるまで、アーティファクトを生成または消費するすべてのジョブでは、以下の GitHub-hosted フォールバックを使用してください。これは、まれな例外ではなく、現時点で推奨される方法です。 -
https://docs.docker.com/engine/install/ から Docker Engine または Docker Desktop をインストールします。Linux では、
sudoを使わずに済むように自分自身をdockerグループに追加してください。actは Podman および Colima でも動作します。act runners のドキュメントを参照してください。
以上がセットアップのすべてです。それ以外(ランナーイメージ、シークレットファイル、アーティファクトサーバー、アクション SHA の事前取得)は、リポジトリの .actrc と scripts/dev/act-local.sh が処理します。
リリースごとのドライラン
ステップ2のマージされたmasterの最新状態と作業ツリーが一致していることを確認してください:
sh
git fetch upstream
git checkout upstream/master
すべてのワークフローファイルで実行可能なものを一覧表示します:
sh
./scripts/dev/act-local.sh --list
特定のジョブを実行するか、対話的に選択するか、またはドライラン可能なすべてのジョブを実行します:
sh
./scripts/dev/act-local.sh release-stable-manual:web # 1つのジョブ
./scripts/dev/act-local.sh # インタラクティブピッカー
./scripts/dev/act-local.sh --all # すべての dry-run-safe ジョブ
最初の実行ではランナーイメージ(約1.5 GB)を取得し、Swatinem/rust-cache を通じてRustのビルドキャッシュを準備します。それ以降の実行は大幅に速くなります。このスクリプトはgitignore対象の .secrets ファイルを自動作成し、ピン留めされたすべてのアクションSHAを ~/.cache/act/ に事前取得し(そうしないと、actの浅いクローンでは任意のコミットを解決できません)、親プロセス環境を介して gh 認証からの GITHUB_TOKEN を実行にスレッド渡しし(トークン値がargvに残ることはありません)、--artifact-server-path を設定して actions/upload-artifact と actions/download-artifact がジョブ間で機能するようにします。これらはすべて、内部的には単なる act であり、スクリプトはフラグの煩雑さを取り除いているだけです。
アーティファクトを生成または消費するジョブが開始される前に、ヘルパーは解決済みのスタンドアロン act または gh act のバージョンを、内部の互換性しきい値(act >= 到達不能なセンチネル、現在は 999.0.0)と照合します。このしきい値はgo install するためのバージョンではありません。リリース済みの act バージョンでこれを満たすものはなく、実際のアーティファクトのラウンドトリップがそのリリースに対して検証された場合にのみ、実在する具体的なバージョンへ移行します。現在リリースされているすべての act バージョンは、ビルド開始前の事前チェックに失敗し、GitHub-hosted Actionsを指し示します。ローカルランナーを通過させるために、ピン留めされたアーティファクトアクションをダウングレードしないでください。
--all では、最初のジョブが開始される前に、選択されたジョブセット全体について互換性がチェックされます。選択されたジョブのいずれかがアーティファクトサービスを必要とする場合、スイープはフェイルクローズドとなり(現在リリースされている act ではしきい値を満たせません)、一部のサブセットを実行せずに終了します。--all --no-allowlist も同じ互換性ポリシーに従います。
ローカルでのアーティファクトの事前チェック失敗は、たまに起きる不具合ではなく、現在リリースされているすべての act で予想されるものです。正確なコミットを GitHub にプッシュし、アーティファクトを扱うジョブの検証用フォールバックとしてホステッドワークフローを使用してください。読み取り専用のクロスプラットフォームビルドは、CLI から安全にディスパッチして監視できます:
gh workflow run cross-platform-build-manual.yml --ref <validation-branch>
gh run list --workflow cross-platform-build-manual.yml --branch <validation-branch> --limit 1
gh run watch <run-id> --exit-status
release-stable-manual.yml をドライランの代替として早期に実行しないでください。このワークフローは環境の承認後に公開を行います。バージョンポリシーによりローカルのアーティファクトジョブがスキップされたことを記録し、アーティファクトのラウンドトリップにはホスト型のクロスプラットフォームビルドを使用し、保護された stable-release の実行はステップ 4 まで残してください。
--all は、dry-run-safe な許可リスト上のジョブのみを実行します
act は GitHub の環境保護ゲートを尊重しません。メンテナーの実際の GITHUB_TOKEN が実行に組み込まれている状態では、GitHub に書き込むジョブ(gh release create を呼び出す publish、GHCR にプッシュする docker ジョブ、gh-pages を強制プッシュする docs-deploy、issue を作成する daily-audit、webhook に投稿する tweet-release や discord-release)をローカルで成功裏に呼び出すと、初回の試行で実世界の副作用が実行される可能性があります。
したがって、--all はローカルでの実行が安全であると証明されたジョブのハードコードされた許可リストを強制します。現在は release-stable-manual.yml および cross-platform-build-manual.yml のアーティファクトのみをビルドするステップ(validate、web、release-notes、build、build-desktop)が対象です。それ以外はすべて、理由をログに記録した上でスキップされます。
==> skip release-stable-manual:publish (not on dry-run-safe allowlist)
==> skip release-stable-manual:docker (not on dry-run-safe allowlist)
==> skip release-stable-manual:crates (not on dry-run-safe allowlist)
==> skip release-stable-manual:redeploy-website (not on dry-run-safe allowlist)
==> skip docs-deploy:deploy (not on dry-run-safe allowlist)
==> skip daily-audit:advisories (not on dry-run-safe allowlist)
==> skip tweet-release:tweet (not on dry-run-safe allowlist)
許可リストはフェイルクローズ方式です。リポジトリに追加された新しいワークフローは、メンテナーがレビューして安全なジョブ ID を scripts/dev/act-local.sh の DRY_RUN_SAFE_JOBS に追加するまで、変更を加える可能性があるものとして扱われます。これが重要なのは、discover_jobs がリリースワークフローだけでなく、すべての .github/workflows/*.yml を走査するためです。拒否リスト方式では、将来の書き込みを伴うワークフローを気付かないうちに通過させてしまう恐れがあります。
ローカルで許可リストにないジョブを実行する理由がある稀なケースのために、2つのエスケープハッチが用意されています:
./scripts/dev/act-local.sh release-stable-manual:publish: 明示的な<wf>:<job>形式は指定したものを実行し、ターゲットが許可リストにない場合はactを呼び出す前に目立つ警告を表示します。./scripts/dev/act-local.sh --all --no-allowlist:--allの実行全体に対して許可リストフィルターを無効にします(ワークフローのステップがミューテーション領域に到達しないことを既に確認済みの場合にのみ使用します。例えば、実際のレジストリ認証情報を持たないフォーク上で、.secretsファイルが空の場合など)。
actで失敗が想定されるもの(問題ありません)
act は GitHub 特有のいくつかの機能をシミュレートできません。これらの失敗は実際の不具合ではありません:
- 実際のリリースタグに依存するジョブ(
publishが GitHub Release を作成する)。 - 環境ゲート付きジョブ(
publish、docker、および crates publisher):承認 UI はローカルには存在しません。 - OIDC ベースのフェデレーション ID トークン。
その他のすべて、tsc エラー、ファイルの欠落、Rust のコンパイル失敗、cargo のロックファイルの不一致は、実際の不具合です。これらが master から分岐した標準的な PR で修正されるまで、GitHub Actions フォームの Run workflow をクリックしないでください。
ステップ 4: リリースをトリガーする
移動先:
https://github.com/zeroclaw-labs/zeroclaw/actions/workflows/release-stable-manual.yml
Run workflow をクリックします。次の項目を入力してください。
- ブランチ:
master - リリースする安定版バージョン:
X.Y.Z、vプレフィックスなし
Run workflow をクリックします。
最初のジョブ(validate)は、バージョンが Cargo.toml と一致していること、および vX.Y.Z タグがまだ存在していないことを確認します。失敗した場合は、不一致を修正して再実行してください。回避策を試みないでください。
ステップ 5: 環境ゲートを承認する
3 つのジョブは GitHub 環境保護ルールによって承認待ちになります。それぞれが保留中になると、ワークフローの実行に “Waiting for review” バナーが表示されます。
3 つすべてが表示されたら承認してください。github-releases ゲートが表示されるのは、トークン不要の crates.io プリフライトである Preflight crates.io Workspace がすべてのクレートをパッケージ化してコンパイルし、さらに各 Plugin Smoke <target> レッグが、そのターゲット向けにビルドされたアーカイブからプラグインをインストールして実行した後だけです。プリフライトはバイナリのビルドと並行して実行され、スモークレッグはその直後に実行されます。そのため、クレートを公開できないリリースや、アーカイブでプラグインを実行できないリリースは、GitHub Release が公開される前に停止します。後続の crates-io ジョブは、そのプリフライトが検証したものを、検証を繰り返さずにアップロードします:
| 環境 | ジョブ | 何をするものか |
|---|---|---|
github-releases | publish | GitHub リリースを作成してアセットをアップロードします |
docker | docker | イメージを GHCR にプッシュします |
crates-io | crates / crates.io に公開 | 検証済みの23クレートのワークスペースを依存関係順に公開します |
承認ウィンドウを逃してジョブがタイムアウトした場合は、ワークフロー実行ページから失敗したジョブのみを再実行してください。最初からやり直す必要はありません。
ステップ6: リリースの検証
publish が完了したら、以下を確認してください:
[ ] GitHub Release exists at /releases/tag/vX.Y.Z and is marked Latest
[ ] Release notes are non-empty
[ ] SHA256SUMS asset is present and non-empty
[ ] Both SPDX and CycloneDX SBOM assets are present
[ ] Exactly one zeroclaw-vX.Y.Z-verification.tar.gz asset is present
[ ] No loose *.bundle, *.attestation.jsonl, or *.intoto.jsonl assets are present
[ ] At least one binary archive is downloadable (spot-check linux x86_64)
[ ] Every Plugin Smoke leg is green; each step summary carries its check table
[ ] Prebuilt Docker and generated Docker matrix jobs are green
[ ] Release notes contain the binary size table from step 1
リリース後、CHANGELOG-next.md は意図的に master に残されます。publish ジョブはこれをリリース本文として読み取るだけで、削除はしません。次のリリースサイクルで上書きされるため、手動でのクリーンアップは不要です。
通常の workflow_dispatch 経路では、Docker Publish は安定版リリースワークフロー内で同期的に実行されます。すべてのリリースジョブが成功していれば、Docker を個別に確認する必要はありません。メンテナーが代わりに vX.Y.Z タグをプッシュしてリリースを開始した場合、Docker Publish はタグによってトリガーされた別の実行として開始されます。コンテナーの公開が完了したと判断する前に、その関連する実行が成功していることを確認してください。crates.io、Scoop、AUR について個別に対応する必要があるのは、それぞれのジョブが失敗している場合だけです。Homebrew Core はこのワークフローの対象外です。その autobump service は、対象となる formulae を独自のスケジュールで確認します。
公開されたアーティファクトの署名、SBOM、または SLSA プロベナンスを検証したいコンシューマーは、リリースアーティファクトの検証 に従うことができます。
release-attestation ワークフローに変更を加えた後は、追跡用 issue を閉じる前に、人間のメンテナーが docs/maintainers/release-attestation-runbook.md にあるオンラインおよび切断状態での検証リハーサルも実行する必要があります。ローカルでのワークフロー lint や act の実行は、そのリリースレベルのチェックの代替にはなりません。どちらも GitHub の本番 OIDC 証明を発行できないためです。
ステップ 7: バージョン管理されたドキュメントのデプロイ
ZeroClaw のドキュメントは、gh-pages ブランチ上でバージョン管理された構造を使用します。Release Stable ワークフローの deploy-docs ジョブは、publish が成功すると、そのリリースタグに対して Deploy mdBook docs to Pages ワークフローをディスパッチします。ディスパッチされた実行は、そのバージョンのドキュメントを非同期にビルドして /vX.Y.Z/ に公開します(ディスパッチジョブはそれを待ちません)。以下のブートストラップとバージョン下限の詳細は、gh-pages を再作成する必要がある場合や、サポート対象バージョンの範囲を変更する場合の参考資料です。
明示的なディスパッチを使う理由(タグプッシュトリガーではなく)。
docs-deploy.ymlにはtags: [v*]が記述されていますが、リリースタグはpublishジョブがGITHUB_TOKENを使ってgh release createで作成します。GITHUB_TOKENで作成されたタグプッシュからは新しいワークフロー実行が開始されないため(ドキュメント)、この方法でリリースを切った場合、tags: [v*]トリガーは発火しません。そのためdeploy-docsジョブは、タグを入力としてworkflow_dispatch(GITHUB_TOKEN下でも実行されるとドキュメントに記載された例外)経由でdocs-deploy.ymlを呼び出します。個人トークンを使って手動でタグを切った場合は、tags: [v*]プッシュトリガーが発火し、リリースワークフローのディスパッチは同じデプロイの no-op な再実行となりますが、どちらのパスも/vX.Y.Z/に収束します。
自動的に行われること
deploy-docsジョブは、/vX.Y.Z/に配置されるビルドを起動します。- “stable“は、リリースの既存ドキュメントディレクトリへのポインタです。
bump-version.shはdocs/book/stable-version.txtを書き込みます。masterでの実行時のみ、そのポインタをgh-pagesに公開し、ルートのリダイレクトとバージョンセレクタを更新します。通常のmasterデプロイでは、開発版ドキュメントと共有アセットもビルドされます。重複した/stable/ツリーは存在しません。 - 順序が重要です: バージョン更新の master デプロイは通常、リリースタグのデプロイより前に実行されます。
/vX.Y.Z/が存在するまで、以前の live ポインタを保持します。リリースのdeploy-docsジョブはタグビルドをディスパッチするだけです。ディスパッチジョブが成功しても、ドキュメントのビルドが完了したことにはなりません。そのランが成功したら、下記のプロモーションモードを使用して、別途フルの master ビルドを行わずに stable ポインタを公開してください。 gh-pagesは一時的なブランチであり、公開時には単一のオーファンコミットで置き換えられます。通常のビルドではDOCS_KEEP_VERSIONSによって保持ルールが適用されます(master、stable ポインタの対象、そして最新の N 件の正式リリース)。プロモーションでは、既存のバージョンディレクトリがすべて保持されます。_shared/ディレクトリ(UI CSS、JS、ファビコンを含む)はビルドから更新されるため、テーマはデプロイされたすべてのバージョンに反映されます。- 翻訳済みロケール(
es、fr、ja、zh-CN)はdocs/book/poサブモジュールからレンダリングされます。デプロイ時にはこのサブモジュールがsubmodules: recursiveによって、デプロイされた ref がピン留めしているコミットで解決されます。そのピンはバージョン更新時に設定されます。更新、タグ付け、ピン留めの手順については Step 2 を参照してください。英語ではサブモジュールは不要です。
デプロイ済みのリリースを昇格
ブランチ master から Deploy mdBook docs to Pages をディスパッチし、mode を promote-stable に設定し、tag には正確な最終タグ(例: v0.8.5)を設定します。デフォルトの build モードでは通常のビルド動作が維持されます。
昇格処理では、サイトルートの stable-version.txt、index.html、versions.json、およびルートの llms.txt / llms-full.txt のペアを更新します。このペアは昇格されたリリースの英語版の内容を反映します。リリースに両方のファイルが含まれていない場合はペアを撤去するため、固定の LLM 向け URL は常に / がリダイレクトするリリースを説明します。Rust や mdBook のツールはインストールしません。また、すべてのロケール、API リファレンス、共通UI部品、保持状態を維持します。ワークフローの既存の gh-pages concurrency グループが両モードを直列化します。昇格処理はさらに厳密な push lease を使用するため、他のライターによって変更されたサイトを置き換えることはありません。
ヘルパーは、dispatch コミットが保護された master の現在の HEAD のままであること、コミット済みのポインタが要求されたタグと一致すること、GitHub の Latest が同じ公開の最終リリースを指していることを要求します。タグをコミットに解決し、そのコミットをデプロイ済みバージョンの .docs-source-commit レシートと比較します。そのリリースの locales.toml に記載されたすべてのロケールには、空でないランディングページが存在している必要があります。メタデータの欠落または不整合、API エラー、プレリリース、ドキュメントの最低バージョン未満のバージョン、数値的なバージョンのダウングレードはいずれも、公開前に失敗します。ライブチェックは push の直前に毎回繰り返されます。実行の待機中に master が進んだ場合は、新しい実行をディスパッチします。成功したプロモーションを繰り返しても安全です。
ソースレシートが導入される前にデプロイされたリリースでは、プロモーション前にそのソースを検証できるよう、該当リリースタグに対して通常の build ディスパッチを1回実行する必要があります。レシートは手作業で作成しないでください。プロモーションでは、ページレベルの canonical タグおよび言語代替タグ、または sitemap.xml は書き換えられません。これらの SEO 関連の値は、次回の通常のドキュメントデプロイ時に更新されます。SEO の即時更新が必要な場合は、通常の master ビルドを使用してください。ダウングレードには、別途レビューされた手動ロールバックが必要です。このモードにロールバックのオーバーライドはありません。ワークフローの変更を元に戻しても手動モードは削除されますが、公開済みのポインタは変更されません。
gh-pages のブートストラップ
gh-pagesが削除された場合、または完全に再作成する必要がある場合は、以下の特定の順序でバージョンをシードしてください。
- サポートされている最も古いリリース: タグ
v0.7.5を指定したworkflow_dispatch - 次回のリリース: タグ
v0.8.0-beta-1などを指定したworkflow_dispatch。 - 現在の master:
masterタグを使用したworkflow_dispatch
[!IMPORTANT] ブートストラップ時には
masterを最後にデプロイする必要があります。これは、他のすべてのバージョンが使用する確定的な_shared/クロームレイヤーを書き込みます。
[!NOTE] Stable は
docs/book/stable-version.txt(ソースにコミットされ、stable-version.txtとして gh-pages ルートに公開される)から解決されます。ブートストラップ後、そのファイルが意図した GA リリースを指していることを確認してください。ルートリダイレクトと「Stable (latest release)」セレクターエントリはこれに従います。/stable/ディレクトリは作成されません。
手動再デプロイとバージョンフロア
特定のバージョンを手動で再デプロイするには:
- Actions → Deploy mdBook docs to Pages に移動します
- Run workflow をクリックします
- タグを入力してください(例:
v0.7.5またはmaster)
DOCS_MIN_VERSION の下限: 古すぎるバージョンやサポートされていないバージョンを誤ってデプロイしないように、ワークフローは最小バージョンの下限(現在は v0.7.5)を強制します。
DOCS_MIN_VERSION(v0.7.4など)より古いタグは、ワークフローによって拒否されます。cargo mdbook gen-versions(xtask ヘルパー)は、この下限より下のgh-pages上のディレクトリをすべて無視し、バージョンのドロップダウンから除外します。
サポートを終了して古いバージョンを切り捨てるために下限を引き上げる必要がある場合:
.github/workflows/docs-deploy.ymlのDOCS_MIN_VERSION環境変数を更新します。- 古いバージョンのディレクトリは、次回のデプロイ時に
DOCS_KEEP_VERSIONSの保持ポリシーによって自動的に削除されます。容量を回収するためにgh-pagesを手動で編集する必要はありません。
問題が発生した場合
実行が startup_failure で即座に終了する(作成されたジョブは 0 件): これは許可リストの診断結果ではなく、症状として扱ってください。実行の概要とリポジトリの Actions ポリシーを確認します。GitHub が selected-actions rejection を報告し、リリースワークフローで最近 uses: refs が追加または変更された場合は、それらの refs を 許可されたアクション と比較してください。Settings → Actions → General で拒否されたパターンのみを追加し、設定が反映されるまで数分待ってから、新しい実行をディスパッチします。GitHub がポリシーによる拒否を報告していない場合は、代わりにワークフロー定義または他のリポジトリポリシーを調査してください。
validate の失敗: バージョンの不一致: バージョン更新のPRがマージされていないか、誤ったバージョンを入力しています。不一致を修正して再実行してください。
crates.io の事前チェックが失敗しました: 何も公開されていません。GitHub Release はこのジョブの完了を待っており、このジョブはレジストリのトークンを保持していません。dispatch によるリリースの場合、タグもまだ存在しません。master でパッケージングの問題を修正し、同じバージョンで Release Stable を再度 dispatch してください。修正を確認するため、先に scripts/release/publish-crates.sh をローカルで実行してください。--execute を付けない場合は、パッケージ化と検証のみを行います。
Plugin Smoke レッグが失敗しました: dispatch で起動したリリースでは何も公開されていません。GitHub Release とリリースワークフロー自身のイメージ push は、すべてのレッグの完了を待っています。タグ push で開始されたリリースは Docker Publish も単独でトリガーしますが、その実行はスモークを待たないため、こちらも確認してください。失敗したレッグのステップサマリーを開いてください。レポートには失敗したチェックの名前と、コマンド出力が引用されています。plugin-smoke-<target> アーティファクトにも同じレポートが入っています。plugin install またはツール結果で失敗している場合、そのターゲット向けにビルドされたアーカイブはプラグインを実行できません。master で修正し、Release Stable を再度 dispatch してください。修正を先に確認するには、Cross-Platform Build ワークフローを使ってリハーサルしてください。このワークフローは、ビルドしたバイナリに対して同じレッグを実行します。プロバイダーまたは scratch ディレクトリの名前が出ている失敗はランナーの問題です。失敗したレッグだけを再実行してください。タイムアウトも一度だけ再実行してください。再度タイムアウトした場合は欠陥です。プラグインロード時にハングするバイナリは、同じようにタイムアウトするためです。
ビルドのひとつが、バイナリサイズチェックに失敗しました: 上限は 80 MiB で、ビルドジョブの Check binary size ステップで BINARY_SIZE_HARD_LIMIT として設定されています。上限を引き上げる前に Cross-Platform Build ワークフローでバイナリサイズを計測し、ターゲットごとのサイズをその上限引き上げを行うプルリクエストに記録してください。
環境ゲートがタイムアウトしました: タイムアウトしたジョブのみを再実行してください。ワークフローを再起動する必要はありません。
Scoop または AUR の配布ジョブが失敗した場合: それぞれに手動でトリガー可能なサブワークフローがあります。修正を確認するため、まず該当するものを dry_run: true で再実行し、その後 dry_run: false で再実行してください。これらはあると望ましいものです。配布ジョブが失敗しても、リリース自体が無効になることはありません。Scoop の認証情報関連の失敗の場合は、汎用的な dry run を認証情報の有効性の証明として扱うのではなく、Scoop Bucket Canary を使用してください。canary によって、fail-closed の credential_canary パスが有効になります。
crates.io への公開が一部のクレートのアップロード後に停止しました: バージョンを上げたり、2 回目のリリースを開始したりしないでください。crates.io のバージョンは置き換えも削除もできません。同じリリースコミットで失敗しているクレートを修正し、同じタグに対して dry_run: false を指定して Pub crates.io を再実行してください。公開ツールはまずすべての <crate>@<version> を照会し、すでに公開済みのバージョンはスキップします。最後に成功したクレートについては Publish step を確認してください。プリフライトが失敗した場合は、アップロードは試行されておらず、問題はまだ元に戻せます。公開ジョブが、web/dist がプリフライトで検証されたバンドルと一致しないと報告した場合、またはタグがリリースコミットに解決されないと報告した場合は、いずれもアップロードされていません。新しいプリフライトでバンドルを再ビルドして再検証できるよう、Pub crates.io を再度実行してください。
失敗の原因はクレートではなく publisher スクリプトにあります: v0.8.5 の失敗は両方ともこの種類のものでした。タグは移動せず、手動で公開もしないでください。master でスクリプトを修正してから、同じタグに対して master から Pub crates.io をディスパッチしてください。クレートは引き続きタグからパッケージ化されますが、scripts/release/ 配下のスクリプトは master から取得されます。実行サマリーには両方のコミットが commit と release tooling として表示されます。リゾルバーは、リリースコミットを既に含む master のコミットからの、より新しいツールのみを受け入れ、手動ディスパッチの場合に限ります。リリース実行は常に、タグ付けされた時点のスクリプトを使用します。
scoop ジョブが remote: Permission ... denied to <account>(403)で失敗した場合: マニフェストの問題ではなく、権限の問題です。バケットトークンが無効になっているか、権限の範囲が不足しています。SCOOP_BUCKET_TOKEN のローテーション に従ってトークンをローテーションし、バケットに書き込まずに修正を確認するため、Scoop Bucket Canary をディスパッチします。dry_run: false で Scoop パブリッシャーを再実行し、バケットに新しいバージョンが反映されたことを確認します。バケット側の Excavator の復旧は、zeroclaw-labs/scoop-zeroclaw#1、リポジトリのワークフロー書き込み権限、およびメンテナーによるスモークテストが保留中のままです。これらの手順が完了するまで、リリースを修復するのを待たないでください。
週次の Scoop Bucket Canary が赤になった: トークンの有効期限が切れているか、書き込み権限を失っています。同じローテーション手順です。次のリリースまでに修正してください。
Homebrew Core が古くなっています: Homebrew はリリースワークフローのジョブではありません。リポジトリのフォークトークンを追加する代わりに、Homebrew autobump のステータスとドキュメント化された手動 bump パスを確認してください。
AUR ジョブが The AUR is down due to maintenance で失敗しました: 上流側の障害であり、認証情報の問題ではありません。ログの SSH key diagnostics に鍵のフィンガープリントが表示され、失敗が SSH ではなくサーバーに起因している場合、AUR_SSH_KEY は問題ありません。パブリッシャーはジョブに強制タイムアウトを設定し、約 7 分間に 5 回再試行します。各試行では現在のパッケージを再クローンし、別の実行ですでに新しいバージョンが公開されている場合は、ダウングレードせずに停止します。メンテナンスエラーに到達したということは、その時間がリトライ予算を超えたことを意味します。aur.archlinux.org が復旧するまで待ち、その後、リリースタグで Pub AUR Package を dry_run: true にして再ディスパッチし、続いて dry_run: false にします。curl -fsS 'https://aur.archlinux.org/rpc/v5/info?arg%5B%5D=zeroclawlabs' で結果を確認するか、単に AUR Freshness Check をディスパッチします。これをスキップすると、週次チェックが検出するまで AUR は気付かれないまま遅れた状態になります。
AUR が意図的にロールバックされた安定版リリースより新しい場合: ロールバックタグとパッケージの内容を確認してください。公開済みパッケージに、ロールバックタグには含まれていないゼロ以外の epoch がある場合は、古いタグを再ディスパッチしないでください。リリースメタデータは不変のタグから取得されるため、デフォルトブランチの編集ではその実行を変更できません。その代わり、差し戻したコードを含む、バージョン番号を進めた安定版リリースを準備し、dist/aur/PKGBUILD に対応する epoch= の設定を追加し、cargo generate installers を実行して dist/aur/.SRCINFO を再生成し、両方のファイルを確認してから、マージし、新しいリリースタグを作成してください。そのタグが公開されるまで、鮮度チェックは赤のままです。エポック境界をまたぐために allow_downgrade を決して使用しないでください。同じエポック内のロールバックの場合は、まず dry_run: true を指定して手動の Pub AUR Package ワークフローを一度実行し、メタデータ生成とバージョンガードの対象側を検証してから、dry_run: false と allow_downgrade: true を指定して実行してください。ドライランでない場合のガードでは、新しく取得した AUR クローンも追加で比較します。このオーバーライドは手動ディスパッチでのみ利用できます。再利用可能なインターフェースではこの入力を宣言していないため、要求できません。形式不正な AUR メタデータや説明のないバージョン不一致を回避するために、これを決して使用しないでください。
同じバージョンでパッケージファイルが異なるため、公開が停止されました: パブリッシャーは、既存の epoch:pkgver-pkgrel タプルに対して異なるファイルを意図的に置き換えることを拒否します。差分を確認してください。権限を持つ AUR メンテナーは、そのリリースタグから生成された正規の PKGBUILD と .SRCINFO を復元するか、修正済みのソース変更をマージして新しい安定版リリースタグで公開する必要があります。デフォルトブランチを編集して古いタグを再ディスパッチしても機能しません。パブリッシャーは不変のタグからメタデータを読み取るためです。
公開時に、数値ではない、またはその他の形式不正な現在の AUR バージョンが報告される: 自動公開処理は意図的にフェイルクローズし、allow_downgrade では形式不正なメタデータを回避できません。承認された AUR メンテナーが、手動で AUR にプッシュしてパッケージを正しい形式の epoch:pkgver-pkgrel に修正し、AUR RPC を通じて検証してから、通常の公開処理を再ディスパッチする必要があります。形式不正な公開状態を比較可能にするためにガードを弱めないでください。
レガシーワークフローを削除しました
以前 .github/workflows/ に存在していたいくつかの自動公開ワークフローは、レビューを回避したり取り消し不能な公開を行ったりするため削除されました。これらはもう存在しません。もし PR でいずれかが再び現れた場合は、リグレッションとして扱いブロックしてください。
| ワークフロー | 削除された理由 |
|---|---|
release-beta-on-push.yml | master へのプッシュごとに自動的に公開されます |
publish-crates-auto.yml | バージョン変更時にcrates.ioへ自動公開、取り消し不可 |
version-sync.yml | ボットとしてレビューを回避し、master に直接コミットしました |
checks-on-pr.yml | 重複した CI: 紛らわしい矛盾したステータスが発生しました |
pre-release-validate.yml | 未使用の生成チェックリスト。このランブックが置き換えます |
残っているワークフロー(自動および手動)の完全な一覧は CI & Actions を参照してください。
今後の展望
このランブックと release-stable-manual.yml は、最終目的地ではなく橋渡しの役割を担うものです。
目標とする最終状態:
- release-plz はバージョンの更新と変更履歴を自動的に管理します
- 単一の
release.ymlが、現在のサブワークフローの寄せ集めを置き換えます - SLSA provenanceはパイプラインに組み込まれています
- チームはリリースを行う際、ランブックに従うのではなく、リリースPRをマージすることで行います
それが実現するまでは、このプロセスを使用してください。このランブックを使って手動でリリースを切るたびに、それが自動化に必要な処理を明らかにする練習になります。