Keyboard shortcuts

Press ← or → to navigate between chapters

Press ? to show this help

Press Esc to hide this help

CI & Actions

すべてのワークフローは .github/workflows/ に配置されています。以下のセクションでは、トリガー別にグループ化しています: git イベントでの自動実行、または workflow_dispatch とスケジュールによるメンテナー起動/アドバイザリワークフロー。

自動ワークフロー

品質ゲート (ci.yml)

master を対象とするすべてのPRと、master への信頼されたプッシュで実行されます。複数のマトリックスレッグを持つ複合ジョブです:

  • fmt: cargo fmt --all -- --check
  • history-guard: 完全な履歴を取得し、テスト対象のコミットを origin/master と照合します。プルリクエストでは明示的な github.event.pull_request.head.sha を使用し、信頼されたプッシュとマージキューの実行では github.sha を使用します。このガードとそのフィクスチャテストは、空の git merge-base を拒否し、マージ後に graft された 2 つ目のルートによって git blame が崩れるのを防ぎます。
  • lint: cargo clippy --workspace --exclude zeroclaw-desktop --all-targets --features ci-all -- -D warnings、続いて cargo doc --no-deps --workspace --exclude zeroclaw-desktop(rustdoc の警告は .cargo/config.toml の build.rustdocflags により致命的なエラーとして扱われます。デスクトップは xtask build_api / docs-deploy に合わせ、リントランナー上で GTK/glib-sys を避けるため除外されます)、さらにコメントの衛生チェックゲート
  • build: x86_64-unknown-linux-gnu と aarch64-apple-darwin のマトリクスを無条件で実行します。パッケージの所有権によっていずれかのコマンドが選択された場合は、個別の windows-build ジョブが x86_64-pc-windows-msvc を検証します。
  • check: ワークスペース全体(zeroclaw-desktop を除く)に対して、警告をエラー扱いにする 2 つのパスを実行します。1 つ目はデフォルト機能なし、2 つ目はデフォルト機能ありで --all-targets を付けたパスです。後者は、デフォルト機能の範囲でテストターゲットをコンパイルする唯一のレッグです。全機能サーフェスは lint によってコンパイルおよび型チェックされます。lint の clippy パスは同じワークスペースに対して --features ci-all --all-targets を実行します。全機能版の独立した cargo check レッグは、このコンパイルを重複させるだけでカバレッジを追加しないため、設けていません。
  • check-32bit: デフォルト機能なしの i686-unknown-linux-gnu
  • check-plugin-backends: scripts/ci/plugin_backend_change_filter.sh によって選択されます。zeroclaw-plugins を各実行バックエンドでコンパイルし、plugins-wasm-cranelift の下でコンポーネント、ランタイム許可、およびルート CLI プラグインのテストを実行します。別の plugin artifact smoke レグは、同じ機能を有効にして zeroclaw バイナリをビルドし、scripts/ci/build_plugin_smoke_packages.sh のパッケージを使って scripts/ci/plugin_artifact_smoke.sh を実行します。スモークテストは任意の zeroclaw バイナリを受け取り、使い捨ての設定ディレクトリと scripts/ci/plugin_smoke_provider.py のスクリプト化されたローカルプロバイダーを使用して、オペレーター自身のコマンドである plugin install、config set、およびツールを実行するエージェントターンを操作します。検証内容は次のとおりです。インストールされたプラグインは、オペレーターがプラグインシステムを有効化し、検出を有効にし、ツールを承認するまで未使用のままであること。パッケージが要求していない設定値は配信されないこと。ダイジェストが不正なペイロード、コンポーネントではないペイロード、別の WIT ワールド向けのコンポーネントは拒否されること。厳格な署名モードでは、未署名、信頼されていない、または編集されたパッケージを拒否し、信頼されたパッケージは実行されること。このレグの最後のステップでは、逆の期待値でスモークテストを実行し、失敗したチェックのために予約された終了ステータスを要求します。エージェントターンは、zeroclaw-providers、zeroclaw-tools、zeroclaw-memory、zeroclaw-api など、パスフィルターでは選択されないクレートにも依存するため、そこでの破損は、ジョブが常に実行されるマージキューおよび master の実行で初めて表面化します。
  • bench: ベンチマークのコンパイルチェックを行います。master へのプッシュ、merge-queue の実行、手動ディスパッチ時にのみ実行されます。PR ではスキップされます(ゲートはスキップを致命的エラーとして扱いません)。これにより、PR ごとにコンパイルのコストをかけることなく、リリース前にベンチマークの劣化を検出できます。
  • テスト: scripts/ci/firmware_protocol_gate.sh によるスタンドアロンのファームウェアプロトコル・ホストゲートと、Linux 上での cargo nextest run --locked --workspace --exclude zeroclaw-desktop。後者には、設定書き込みの分離と Fluent カバレッジ(ユーザー向け文字列の直書き禁止)のアーキテクチャガードが含まれます。最後の情報提供ステップでは、crates/zeroclaw-gateway/tests/golden_frames.rs のゲートウェイ・ゴールデンフレームのシナリオ(WebSocket チャット、webhook の JSON と SSE、/api/events、ACP)を、記録済みのフィクスチャに対して --run-ignored only で再生します。このステップはジョブのビルドを再利用し、ドリフトがあれば警告付きでステップサマリーに書き出し、ジョブを失敗させることはありません。ゲートウェイが RPC 経由でコアと通信するようになるまで、情報提供ステップのままとします。
  • test-tool-features: オプトインの SaaS、コーディング CLI、外部アダプターのテストです。Cargo の default ではビルドされなくなりました。--features tools-compat を付けて、ルート、config、tools、runtime、channels、gateway のライブラリテストと、ルートの report-template 統合テストに対して cargo nextest run を実行します。lint は同じコードを ci-all でコンパイルしますが、テストは実行しません。
  • memory-postgres-test: cargo nextest run --locked -p zeroclaw-memory --features memory-postgres に続けて、エフェメラルな PostgreSQL 17 サービスに対して実行される、クレートのシリアル実行 ignored 受け入れテスト
  • parallel-runtime-test: scripts/ci/parallel_runtime_test_gate.sh に含まれる同一プロセスのランタイム/チャンネルテストを繰り返し実行するジョブ。関連するPRパスに対してはメインテストジョブと並列で実行され、master へのプッシュおよびマージキューの実行時は無条件で実行されます
  • security: cargo deny check
  • nix-eval: NixOS モジュールのアサーションを評価します(nixos-module-eval flake チェック)
  • docs-style: Markdown lint、emダッシュの散文チェック、および scripts/ci/docs_quality_gate.sh と scripts/ci/docs_links_gate.sh による変更行のリンクゲート

Linux ジョブは、カーネル依存の Landlock チェックを除き、Blacksmith 上で必須ゲートを実行します。コンパイル負荷の高いフリートは blacksmith-8vcpu-ubuntu-2404 を使用します。ハウスキーピング用のセット(fmt、変更検出ジョブ、リポジトリガード、ドキュメントおよびポリシーゲート、Nix チェック、コンテナスモークテスト、security、web-permission-tests、そして gate 集約ジョブ自体)は blacksmith-4vcpu-ubuntu-2404 を使用します。唯一の意図的な Linux 例外は test-landlock で、Landlock LSM チェックがホステッドカーネルに依存するため、GitHub ホステッドの ubuntu-latest に残します。Windows のタスクオーナーリカバリーは blacksmith-8vcpu-windows-2025 を使用します。macOS およびその他の Windows ジョブは、GitHub ホステッドのプラットフォームランナーを維持します。この分割は、2026-09-14 に GitHub のホステッドランナー割り当てが組織全体で停止した一方、Blacksmith は稼働し続けたことを受けて行われました。ハウスキーピングジョブを移動したことで、ホステッドの障害が招くのはプラットフォーム固有のチェックのみとなり、必須ゲート全体が止まることはなくなります。すべてのジョブは、ランナーラベルとキャッシュプロバイダーの入力を直接指定しています。tests/architecture/ci_runner_labels.rs は、Linux のインベントリ(コンパイルフリート、ハウスキーピングフリート、ホステッド Linux の許可リスト)と、リカバリー専用の Windows ランナーおよびキャッシュ書き込みの契約を検証します。作業ジョブは fmt の完了を待ちません。その意図的なトレードオフとして、フォーマットに失敗した PR では追加のランナー作業が発生します。CI Required Gate は引き続き fmt に直接依存し、必須結果を集約するため、フォーマットエラーは引き続きマージをブロックします。ラベルでゲートされる別の参考用 Windows ワークフローは、このゲートの外に残ります。その Linux セレクターも Blacksmith 4vcpu クラスで実行されます。ブランチ保護は複合ゲートジョブを固定しています。master へのプッシュ実行は、同じ品質シグナルを維持しつつ、後続の PR 実行のために信頼された Rust キャッシュをシードします。

プルリクエストとマージキューのエントリで [workspace.package] version を安定版の X.Y.Z に変更した場合は、crates-preflight も実行されます。このジョブは pub-crates.yml を stage: preflight、シークレットなし、コンパイル用フリートのランナーラベルで呼び出します。crates-preflight-changes は scripts/ci/crates_preflight_trigger.sh でこの判定を行います。それ以外の変更では両方のジョブがスキップされ、スキップされたジョブはゲートを失敗させません。このジョブは runs-on を持たない再利用可能ワークフローの呼び出しであるため、tests/architecture/ci_runner_labels.rs が個別に棚卸しし、フリートのラベルを渡していることを必須としています。

ランナーのインベントリは ci.yml と windows-tests.yml の両方を対象とし、ワークフローで修飾されたジョブ識別子を使うことで、同名のジョブが互いを隠すことがないようにしています。Linux/macOS の build マトリクスは、いかなる detector も待機しません。独立した Windows のコンパイル、サービス、リカバリのジョブは、Blacksmith の windows-required-changes detector を待機します。この detector は、レジストリの解決やダウンロードを行わずに、cargo metadata --locked --offline --no-deps でパッケージの所有関係を読み取ります。非 Rust の path-changes detector は、このパッケージグラフからは独立したままです。

master へのプッシュに限り、コンパイル負荷の高いジョブ(および Windows clippy と parallel-runtime ジョブをゲートする検出ジョブ)は、まず master-debounce で5分間待機します。master へのプッシュはバーストで届くことが多く、実行全体に設定された cancel-in-progress は、後続のプッシュによって置き換えられたプッシュを、そのコンパイル用フリートが起動した後にようやくキャンセルします。この待機があれば、待機ウィンドウ内で置き換えられたプッシュは、その軽量ジョブがスリープしている間にキャンセルされます。このジョブは pull request およびマージキューの実行ではスキップされ、スキップされたジョブはランナーを使わずに完了するため、それらのレイテンシは変わりません。GitHub はスキップされた上流ジョブを暗黙の success() を通じて伝播させるため、master-debounce の下流にあるすべてのジョブには、明示的な !cancelled() 条件と、各依存ジョブに対する結果チェックが付与されており、いずれかが欠けていると tests/architecture/ci_runner_labels.rs が失敗します。CI Required Gate は master-debounce に依存しているため、debounce が失敗してもゲートが緑のままコンパイルジョブがスキップされた状態で残ることはありません。トレードオフとして、master の実行がコンパイルを開始するまでに5分余分にかかり、master の Rust キャッシュのシードも同じ時間だけ遅れます。

フレッシュな必須 CI は通常、それが実際に実行する Cargo サーフェスの共有エビデンスです。同じ head、ターゲット、feature セットに対する同じ Cargo コマンドのローカル再実行は、重複した確信であり、より強い証明ではありません。追加の Cargo や Clippy を求める前に、変更されたサーフェスを現在のワークフローファイルと PR 上の実際のチェックと比較してください。追加の検証は、必須ゲートがレビュー対象を証明しない箇所に属します:

  • プラットフォームはコンパイルチェックを受けましたが、テストは受けませんでした。
  • プラットフォーム、crate、またはパスが必須の lint ジョブの範囲外です。
  • デスクトップの変更ではデスクトップワークフローがトリガーされませんでした。
  • リリースターゲットは PR マトリックスの範囲外であり、release/manual ワークフローでのみカバーされます。
  • 失効、キャンセル、スキップ、または利用不可の CI は最新の証拠ではありません。

定義やインポートがフィーチャーによって条件付けされている場合は、その cfg 条件をすべての利用側と比較します。有効な構成と、関連する無効な構成をそれぞれ検証してください。フィーチャーを有効にした検証では利用側が引き続き動作することを確認でき、一方、ワークスペース全体での no-default-features チェックでは、未使用の非公開定義やインポートなど、警告を発生させる不一致を検出できます。この検証では --all-targets なしで cargo check を実行するため、テストターゲットは決してコンパイルされません。単なる test によって条件付けされたヘルパーで、その唯一の呼び出し元がフィーチャーの背後にある場合は、代わりに default-features/all-targets の検証段階で検出されます。必要な CI 構成のいずれでも変更された条件が検証されない場合は、対象を絞ったフィーチャーの組み合わせが引き続き必要です。

PostgreSQL メモリジョブは、memory-postgres を有効にして zeroclaw-memory の非 ignored テストをすべて実行し、その後、クレートの ignored テストを ZEROCLAW_TEST_POSTGRES_URL を使用棄い捨て可能なサービスに向けて直列に実行します。データベースを利用する後半部分をローカルで再現するには、分離された PostgreSQL データベースを用意し、ZEROCLAW_TEST_POSTGRES_URL=postgres://<user>:<password>@127.0.0.1:5432/<database> cargo test --locked -p zeroclaw-memory --features memory-postgres -- --ignored --test-threads=1 を実行してください。各受け入れテストは一意の名前を持つスキーマを所有し、そのスキーマのみを削除します。

ラベルがなくても必須の Windows コンパイルは自動的に実行されますが、チェック対象はコマンドがコンパイルできるコードのみです。PR では、scripts/ci/windows_test_scope.py --required-jobs がパッケージルートの分類と逆依存関係の閉包を再利用します。ルートコマンドは、影響を受ける閉包に zeroclaw が含まれる場合に実行されます。voice-wake コマンドは、閉包に zeroclaw-channels が含まれる場合に実行されます。内部パスのエッジには、オプショナル依存、ターゲット固有の依存、ビルド依存、開発依存を保守的に含めます。ZeroCode のみを単独で編集した場合、これらの無関係なコマンドは実行されません。ワークスペースのマニフェスト、ロックファイル、ツールチェーン、Cargo 設定、ワークフロー/アクションの制御、不明なパス、欠落または不正な形式の証跡があると、必須の Windows ジョブがすべて選択されます。master へのプッシュおよびマージキューのビルドでは、常にすべてのジョブが実行されます。Linux/macOS のコンパイルは、引き続き無条件で実行されます。

サービススモークはwindows_service_smoke_fixtureをビルドします。このフィクスチャは、合成デーモンと引数ディスパッチを所有しています。ルートCLIの変更(src/main.rs)では、これは自動的に選択されません。サービスのソース、ランタイムモジュールの配線、フィクスチャとスモークスクリプト、設定/spawnの依存関係、および関連するマニフェスト/ビルド制御は、引き続きカバレッジの対象となります。タスクオーナーのリカバリジョブは、コントロールプレーンおよびランタイムモジュール配線の直接トリガーを引き続き保持します。パッケージマニフェストとビルドスクリプトは、その逆依存閉包がruntimeに到達する場合にこれらのネイティブジョブを選択します。無関係なgatewayやスタンドアロンアプリのマニフェストは選択しません。リカバリ用シェルのエントリポイントは、所有権レジストリを別途管理するのではなく、同じパッケージセレクタに処理を委譲します。

回復テストは、専用の windows-task-owner-recovery ジョブで blacksmith-8vcpu-windows-2025 上で実行され、コンパイルと並行して動作します。これは、ランタイムの単体テストハーネスが cargo check の出力を再利用できないためです。選択されなかったジョブは、Windows ランナーを確保する前にスキップされます。CI Required Gate は検出器と必須の各 Windows ジョブの結果を直接参照し、選択結果の出力が欠けている場合は拒否し、選択されたすべてのジョブが成功することを要求します。選択されたのにスキップされたジョブ、失敗したジョブ、またはキャンセルされたジョブは、意図的なスキップとして扱うことはできません。

Recovery は、固定バージョンの Swatinem/rust-cache アクションを shared-key: windows-recovery-blacksmith で直接呼び出します。GitHub のビルドランナーのキャッシュに互換性のある Rust 環境ハッシュがあると想定することはありません。この専用の依存関係キャッシュを保存するのは、refs/heads/master に対して成功した push 実行のみです。PR および merge-queue の実行はキャッシュを復元するだけです。キャッシュミスの場合は通常どおりビルドされ、どちらのテストもスキップされません。既定のワークスペース成果物のクリーンアップは有効のままなので、ランタイムハーネスは引き続きコンパイルされます。これによりキャッシュの名前空間が1つ追加され、リポジトリのストレージを消費します。コンパイルとサービスのスモークテストは、既存のランナーとキャッシュをそのまま使用します。

Label-gated Advisory Windows Tests (windows-tests.yml) ラベルで制御される Advisory Windows テスト (windows-tests.yml)

ci:windows は、コンパイルだけでは検証しきれない実質的な欠落を、Windows 上でのテスト実行によって補う場合に使用します。典型的なケースとしては、プロセスやサービスのライフサイクルの変更、PowerShell の実行、ファイルシステムとパス処理、エンコーディング、ネイティブ依存関係、Windows CI の選択や実行方法の変更などが挙げられます。すべての Rust PR、ドキュメントのみの変更、無関係な Linux テストの失敗に対して既定で付けるラベルではありません。

候補が Windows での有用な検証結果を得られる程度に安定したら、ラベルを追加してください。Windows 向けの反復作業中で、更新のたびに再実行が必要な間はラベルを維持してください。単発の検証が完了し、以降のプッシュでそのカバレッジが不要な場合は、ラベルを削除してください。ラベルがなくても、必須の Windows コンパイルは自動的に実行されます。夜間のプラットフォームテストはマージ後のバックストップであり、変更に Windows 固有の検証が必要な場合に、マージ前の実行の代わりにはなりません。

master を対象とする PR に ci:windows ラベルを追加すると、参考情報としての Windows テストにオプトインできます。このラベルを追加すると、現在の PR のリビジョンに対してワークフローが開始されます。ラベルが付いている間は、プッシュおよび再オープンのイベントでワークフローが再実行されます。無関係なラベルの追加では、テストは再実行されず、実行中の Windows ワークフローもキャンセルされません。ラベルを削除すると、以降の自動実行は停止しますが、すでに進行中の実行はキャンセルされません。このラベルは計算コストを切り替えるためのものであり、セキュリティ上の承認ではありません。GitHub のフォークからのワークフローに対する通常の承認要件は引き続き適用されます。

このワークフローは、pull_request_target ではなく、通常の読み取り専用の pull_request イベントを使用し、イベントの固定されたマージSHAをテストします。手動ディスパッチトリガーはありません。ci.yml とは別に保持することで、ラベルの追加によって助言的なワークフローのみが開始され、必須CIが再開されることはありません。必須ゲートはこれらのジョブに依存しません。

次のステップに進む前に、Windows ジョブ自身の結論とログを確認してください。Windows ジョブは continue-on-error を使用しているため、ワークフロー全体が成功(緑)になっていても、テストが合格したことの証明にはなりません。テスト対象のリビジョン、選択されたスコープ、失敗した実行フェーズを記録し、ログを使ってテストの失敗と、セレクタまたはワークフローの失敗を区別してください。

Linux セレクターはフォーマットをチェックし、PR のベース SHA とチェックアウト済みのマージリビジョンを比較して、Cargo ワークスペースのメタデータを生成します。ベースラインの mode、JSON 形式の packages、簡潔な reason、および needs_plugin_host をジョブ出力とステップサマリーに書き込みます。このラベルは既存のセレクターをオプトインするものであり、無条件にフルスイートを実行するものではありません。ナイトリーのプラットフォームテストは、マージ後の自動的なバックストップとして引き続き機能します。

skip は、変更されたパスが現在のワークスペーススイートでカバーされる Rust のコンパイルやテストに影響しないことを意味します。scoped は、Rust のソース、テスト、ベンチマーク、サンプル、およびパッケージローカルの manifest パスを Cargo メタデータ由来のパッケージルートにマッピングし、そのセットをワークスペースの逆依存関係について閉包化し、ルートの src/ と tests/ をルートパッケージにマッピングし、パッケージ名の重複を排除し、既存のワークスペーススイートと同様に zeroclaw-desktop を除外します。full は、ワークスペースの manifest または依存関係解決、.cargo、Rust ツールチェーン、CI またはテストインフラ、セレクタまたはワークフロー、不明なパス、曖昧なメタデータ、その他安全にマッピングできない変更に対して選択されます。Cargo.lock への変更はすべて full を選択します。ワークスペース全体の依存関係解決は、直接変更された manifest を超えてパッケージに影響しうるためです。ルート、gateway、provider パッケージへの直接の変更、および plugin、runtime、plugin config、WIT、ルートの plugin 有効化、plugin バックエンドフィルター、dependency、selector、selector-contract、ci.yml、windows-tests.yml パスへの変更は、needs_plugin_host=true を設定します。制御ファイルのケースにより、ワークフローの改訂が、それらが所有する plugin-host パスを確実に検証するようになります。不正な形式または利用できない変更パスの入力は、ベースラインの full および needs_plugin_host=true を選択します。Cargo メタデータが欠落している、または不正な形式の場合も、依存関係の閉包を安全に確立できないため、ベースラインの full と needs_plugin_host=true を選択します。

scoped の Windows ジョブは、cargo nextest に明示的な -p 引数を渡します。full では cargo nextest run --locked --no-fail-fast --workspace --exclude zeroclaw-desktop を実行します。needs_plugin_host=true の場合は、wasm32-wasip2 をインストールし、機能が有効な zeroclaw-plugins のコンポーネントターゲット(channel_plugin_e2e、tool_plugin_timeout_e2e、reference_plugin、reference_plugin_e2e、tool_plugin_e2e)、プラグインライブラリのテスト、ランタイムのライブ設定および admission の回帰テスト、ゲートウェイのライブラリテスト、ルート CLI のプラグインテスト(プラグインレジストリクライアント、egress ceremony の Windows シェル検証を含む plugins:: モジュール、CLI の egress ceremony テスト、ルートバイナリの plugin update テスト)、実バイナリを実行する plugin_update_cli および plugin_info_cli のコンポーネントテスト、ルートの plugin_channel_runtime_e2e と channel_egress_e2e のターゲットを追加します。追加された各呼び出しは、先行する呼び出しが失敗しても必ず実行され、サマリーには各フェーズの状態と失敗の一覧が残ります。ジョブは、ベースライン、プラグインホスト、合計の所要時間をそれぞれ別々に報告します。通常の scoped および full の選択では、プラグインホストのコンパイルコストは発生しません。この PR ワークフローは、互換性のある platform-test のキャッシュエントリを復元しますが、保存は行いません。固定された PR マージ SHA をチェックアウトし、チェックアウトの認証情報は永続化しません。Windows ジョブがスキップされた場合は意図的なものであり、セレクターの結果の横に表示されます。

定期実行のプラットフォームテスト (platform-tests.yml)

cargo nextest run --locked --workspace --exclude zeroclaw-desktop --no-fail-fast を macos-15 と windows-latest で、安価な Linux のフォーマットチェックの後に実行する。この夜間の全ワークスペース実行は、ラベル選択による Windows カバレッジのバックストップであり、--no-fail-fast で失敗を一覧化する。マトリクス実行の対象は以下のとおり:

  • platform-tests.yml 自体を変更するプルリクエスト;
  • 手動ディスパッチ、および
  • 毎晩 03:17 UTC に実行されるスケジュール。

これらのジョブは continue-on-error を使用しており、CI Required Gate には接続されていません。これらはプラットフォーム互換性の証跡であり、マージの必須要件ではありません。通常のコードPRでは、このフルマトリクスは自動的には起動されません。メンテナーは、完全なプラットフォームでの検証が有用な場合に、ブランチに対して手動でディスパッチできます。このワークフローは、通常の push や merge_group イベントでは実行されません。master 上の nightly 実行および手動ディスパッチによる実行は信頼されたキャッシュを書き込めますが、pull request からの実行は書き込めません。--no-fail-fast により、単一の実行ですべてのプラットフォームの失敗が表示され続けます。

日次アドバイザリスキャン(daily-audit.yml)

毎日 09:00 UTC に依存関係ツリーに対して cargo deny check advisories を実行します。問題が見つかった場合は issue を作成します。脆弱性が報告されない限り、何も行われません。

日次 npm 監査 (daily-npm-audit.yml)

web/package-lock.json に対して毎日 09:23 UTC に npm audit --audit-level=high を実行します。コミット済みの web ロックファイルに高深刻度の npm アドバイザリが影響する場合、重複排除された security + dependencies の issue を 1 件作成します。

週次 Trivy イメージスキャン (trivy-scheduled.yml)

公開された dist および default-features の GHCR イメージを毎週土曜日にスキャンし、HIGH/CRITICAL の検出結果を SARIF として Security タブにアップロードします。スキャンはレポート優先(検出結果に対して exit-code: 0)ですが、想定されるイメージが見つからない場合は、欠落しているタグと所有元の公開ワークフロー名をエラーに示して、Trivy のセットアップ前にジョブを失敗させます。

週次 Scoop Bucket Canary (scoop-bucket-canary.yml)

毎週月曜日に、現在の安定版リリースに対する Scoop の公開フローをリハーサルします。最新の vX.Y.Z タグを解決し、pub-scoop.yml を dry_run: true と credential_canary: true の両方を指定して呼び出すため、何も書き込まずに実際の SCOOP_BUCKET_TOKEN を実際のバケットに対して使用して動作を検証します。

credential_canary はその契約におけるフェイルクローズ部分です。SCOOP_BUCKET_REPO または SCOOP_BUCKET_TOKEN が欠落していると実行は失敗し、設定済みの認証情報は git push --dry-run の認可プローブまで到達しなければなりません。dry_run: true だけを指定した汎用的な手動 pub-scoop.yml 実行は、マニフェスト生成に対しては引き続き許容的であり、認証情報を利用できない場合はそのプローブをスキップすることがあります。認証情報検証の証拠として汎用モードを使用しないでください。

これは SCOOP_BUCKET_TOKEN がアカウントに紐付いているために存在します。つまり、有効期限が切れ、所有者の ID に付与されたバケット上のコラボレーター権限が変更されると、書き込み権限をひそかに失います。どちらも実際に起きました。カナリアの前は、認証情報を使用していたのは公開後の scoop ジョブだけだったため、無効なトークンが発見されたのはリリースがすでに作成され、告知された後であり、バケットは手動で更新する必要がありました。

カナリアは認証情報の陳腐化を検出します。これは意図的にバケットを正しい状態に保つものではなく、Release Stableにも組み込まれていません。使用不能になったパッケージマネージャーの認証情報によって、リリースがブロックされたり遅延したりすることは決してあってはなりません。

Scoop バケットの整合性が保たれる仕組み

現在、自動書き込みを行うのはリリースパブリッシャーだけです:

  1. pub-scoop.yml はリリース時にプッシュされます。 Scoop ユーザーは、これが成功するとすぐに新しいバージョンを確認できます。リポジトリ間で使用する SCOOP_BUCKET_TOKEN が必要で、ここが壊れやすい部分です。
  2. メンテナーは失敗した push を復旧します。 トークンをローテーションまたは修復し、Scoop Bucket Canary をディスパッチしてフェイルクローズの credential_canary パスを通じて検証し、dry_run: false でパブリッシャーを再実行して、バケットマニフェストにリリースバージョンが反映されたことを確認します。

bucket 側の Excavator が scoop-zeroclaw#1 で提案されています。そのワークフローがマージされ、bucket リポジトリで Actions にワークフローの読み取り/書き込み権限が付与され、メンテナーによるスモークテストで更新がコミットされることが確認されれば、認証情報に依存しない復旧レイヤーにできます。3 つすべての条件が満たされるまでは、失敗した publisher が自動復旧すると想定しないでください。

checkver と autoupdate のブロックは、計画中の Excavator パスですでに不可欠です。現在の push パスでも、scripts/release/scoop_metadata.sh を使用して autoupdate からリリース URL テンプレートを導出しているため、両方のパスで 1 つのマニフェスト契約を共有しています。これらのブロックを削除したり、dist/scoop/zeroclaw.json から手作業で取り除いたりしないでください。

PR パスラベラー (pr-path-labeler.yml)

変更されたファイルに基づいて、パスおよびスコープのラベルを自動的に適用します。PRのオープン、再オープン、およびPRブランチへのプッシュ更新のたびに実行されます。sync-labels: true が有効になっているため、.github/labeler.yml で定義されたラベルは、現在のPRファイルセットから再計算されます。

このワークフローでは risk:*、size:*、type:*、コントリビューター階層、status、resolution、stale、pickup のラベルは適用しません。PR にパス/スコープのラベルが付いていない場合は、.github/labeler.yml のパスが変更内容をカバーしているか確認してください。

Dependabot は独自の PR 用に .github/dependabot.yml で個別のラベル設定を持っています。Cargo の更新 PR は dependencies で始まり、GitHub Actions と Docker の更新 PR は ci と dependencies で始まります。

PR Size Labeler (pr-size-labeler.yml)

Applies exactly one canonical size:* label from PR file metadata. It runs on PR open, reopen, and every pushed update to the PR branch. The classifier counts additions plus deletions after excluding docs-like files and Cargo.lock, then applies the threshold table from Labels.

このワークフローは、フォークからの PR にラベルを付与できるように pull_request_target で実行されますが、分類スクリプトは信頼されたワークフロー/デフォルトブランチのリビジョンから取得します。プルリクエストのコードをチェックアウト、ビルド、インポート、source、実行することはありません。risk:*、type:*、コントリビューター階層、status、resolution、stale、pickup、ProjectV2 フィールドは適用しません。

PRリスクレポート (pr-risk-labeler.yml)

pull_request_target を通じて、PR の更新および risk/security ラベルの変更時に実行され、単一の PR に対する手動ディスパッチでも実行されます。信頼されたワークフローのリビジョンから分類器と JSON 互換のポリシーを取得し、#9530 のテスト専用の証明に必要な場合にのみ、PR のメタデータ、変更されたファイル、ラベル、API のソーステキストを読み取ります。そして、人間が読めるステップサマリーと JSON の証拠を書き出します。pull request のコードをチェックアウト、ビルド、インポート、ソース読み込み、実行することは一切ありません。

Phase 2 は report-only です。ワークフローには contents: read と pull-requests: read の権限のみがあり、ラベルの追加・削除・置換は行わず、コミットステータスも作成せず、承認件数の強制も行わず、リポジトリのルールセットも必須にしません。risk:manual は将来の変更に対するハードフリーズとして報告され、domain:security は提案された risk:* の結果とは独立して報告されます。

分類器は不確実な証拠を上方向に倒します。ドキュメント、フィクスチャ、既知の機械的なメタデータは risk:low となる場合があります。通常の動作変更は risk:medium です。設定済みの信頼、認証情報、互換性、ガバナンス、リリース権限、セキュリティ、またはツールチェーン下限のパスは risk:high です。

チェックイン済みのポリシーには、決定論的な変更行エスカレーションルールも含まれています。対象は、ワークフローの権限拡大、シークレットへのアクセス、OIDC、アーティファクトの公開、リリース動作、昇格された pull_request_target、ツールチェーンのインストールまたはコンテナのベースライン、リリース下限の変更、そして WIT コントラクトの可能性が高い変更です。これらの内容に敏感なファイルのいずれかが変更されたものの、パッチが利用できない、または不正な形式である場合、レポートは推測で risk:medium とせず、risk:high のままとします。

#9530 の例外では、完全な Rust パッチと一致する base/head のソースによって、高リスクの Rust 変更がすべて既存の #[cfg(test)] コード内に留まることが証明される場合に限り、risk:medium を推奨できます。欠落、切り詰め、不正な形式、混在、条件付きコンパイル、リネーム、追加、削除の証拠がある場合は、risk:high のままとします。

プロジェクトダッシュボードプランナー (project-dashboard-plan.yml)

手動で単一の issue 番号に対して実行します。issue の状態とラベルを読み取り、その issue に最も適合する既存の Project Status 値を提案するレポート専用のステップサマリーを書き込みます。

このワークフローは、Issue イベントによる自動実行、ProjectV2 フィールドへの書き込み、Issue の編集、ラベルの追加、コメントの投稿、PR の risk:* または type:* ラベルの再計算は行いません。ライブの ProjectV2 変更や Issue イベントの自動計画には、別途承認されたフィールドマッピング、トリガーポリシー、およびプロジェクトスコープの認証情報が必要です。

PRタイトルの検証(pr-title.yml)

すべてのPRのopen/edit/synchronizeで実行されます。バリデータのユニットテスト(scripts/check-pr-title.test.sh)を実行し、PRタイトルをConventional Commits(scripts/check-pr-title.sh)に照らしてチェックします。

Pages に mdBook ドキュメントをデプロイ (docs-deploy.yml)

タグのプッシュ(および workflow_dispatch)でトリガーされ、バージョン管理されたドキュメントをビルドして gh-pages ブランチに公開します。バージョンの下限とブートストラップのルールについては、リリース Runbook → バージョン管理されたドキュメントのデプロイを参照してください。

Docker イメージ PR チェック (docker-image-pr.yml)

このワークフローは、Docker イメージ、Compose、リリース用 Docker コンテキストのファイルが変更された場合にのみ実行されます。デフォルトの Compose 設定と Alpine 向けの Compose 設定をマージした構成を検証します。Compose 以外の変更を含む場合は、デフォルトと Debian のビルド済みスモークテスト用イメージ、およびソース用 Dockerfile をビルドしますが、プッシュはしません。変更された Docker 関連ファイルが release-stable-manual.yml のみの場合は、ビルド済みスモークテスト用イメージだけをビルドします。リリースワークフローの Docker ジョブは、scripts/ci/prepare_docker_context.sh を通じてビルド済みバイナリをパッケージ化しており、これらのイメージはそれを検証します。また、ソース用 Dockerfile は一切使用しません。Dockerfile、Containerfile、Compose ファイル、.dockerignore、設定テンプレート、Docker コンテキストスクリプト、このワークフロー自体のいずれかのソースイメージ入力にも変更が及ぶ差分の場合は、ソース用の完全なマトリクスをビルドします。デフォルトおよび Alpine のソース用イメージは linux/amd64 と linux/arm64 向けにビルドし、Debian のソース用イメージは linux/amd64 向けにビルドします。Alpine と Debian の linux/amd64 レーンは個別に plugins-wasm-runtime-only を有効にし、プラグイン対応のソースビルドでリポジトリの WIT 契約が利用可能であることを継続的に検証します。

全機能版の Containerfile ソースイメージは、そのファイルまたは Docker ワークフローが変更された際に linux/amd64 向けにビルドされます。分離されたキャッシュスコープを使用し、ロードもプッシュもされません。Alpine amd64 レーンでは両方のバイナリを実行し、マージされた Compose 構成を通じてビルドされたイメージを起動して、ゲートウェイのヘルスチェックとダッシュボードの表示を検証します。Alpine arm64 レーンは、コンパイルとイメージ組み立てのカバレッジのみです。blacksmith-8vcpu-ubuntu-2404 上でクロスビルドを行います。これは既存の 32 GB ヘビー Rust ランナークラスで、リリース時のリンクが ubuntu-latest でメモリを使い果たしたためです。他の Docker ジョブは ubuntu-latest に残ります。リリースの最適化、ビルドフラグ、マトリックスのサイズは変更されていません。Compose のみの変更では、関連のないイメージを再ビルドせずにランタイム契約を検証できるよう、縮小された Alpine amd64 マトリックスを使用します。すべてのジョブはリポジトリへの読み取り専用権限を持ち、レジストリへの書き込み権限はありません。

Docker 公開 (docker-publish.yml)

dev/ci/docker-tags.toml から生成された4バリアントのマトリックス(minimal、default-features、dist、all-features)をビルド、署名、スキャンします。人手で作成した v* タグによって、このワークフローが直接開始されます。workflow_dispatch で開始された安定版リリースは GITHUB_TOKEN を使用してタグを作成しますが、これによって別のタグプッシュイベントは発生しません。そのため、正規のリリースおよび Docker ジョブが成功した後、release-stable-manual.yml が不変のリリースタグで Docker Publish を同期的に呼び出します。

このマトリックスは、安定版リリースのビルド済み latest、バージョン付き、および debian イメージを置き換えるのではなく、補完するものです。2つのパスは異なるビルド入力を使用し、異なるタグを公開します。

Discord リリース (discord-release.yml)

安定版リリースが成功した後に実行されます。リリースノートをコミュニティの Discord に投稿します。

Tweet リリース (tweet-release.yml)

安定版リリースが成功した後に実行されます。アナウンス用のツイートを投稿します。

AUR の週次最新性チェック (aur-freshness-check.yml)

毎週月曜日に、公開されている zeroclawlabs AUR バージョンを GitHub の現在の安定版リリースと比較し、AUR が遅れている場合は失敗します。

AUR への公開は投げっぱなしです。pub-aur.yml が失敗すると再確認されないため、パッケージがひそかに遅れます。v0.8.4 の後に、まさにそれが起きました。aur.archlinux.org のメンテナンス期間がリリースと重なり、再試行されなかった1回の clone が The AUR is down due to maintenance で失敗し、パッケージは何の通知もないまま3週間遅れた状態になりました。公開処理では現在、アクティブな non-dry-run の公開を最大1件に制限し、短時間の停止を乗り越えられるよう再試行します。同じ concurrency group 内では、GitHub が先にキューへ入った実際の公開を後続の公開で置き換える場合がありますが、dry run では別のグループを使用します。すべての試行で正本となるパッケージ状態を再度 clone し、より新しい epoch:pkgver-pkgrel タプルをより古いもので置き換えることを拒否します。再試行予算でもすべての失敗をカバーすることはできないため、このチェックが、サイレントな取りこぼしや置き換えられた実行を可視化する最後の防波堤になります。

AUR RPC に到達できない場合、チェックは警告を出してパスし、失敗にはしません。AUR の停止は上流の可用性の問題であり、パッケージの陳腐化ではありません。次回のスケジュール実行で再チェックされます。陳腐化は持続するため、検出が遅れても問題ありませんが、他者のメンテナンスウィンドウについて毎週ページを送るのは適切ではありません。

ドキュメントは、master へのプッシュごとではなく、リリースパイプラインの一部としてビルドおよび公開されます。翻訳は、専用の翻訳キャッシュ PR、新しいロケール、リリース翻訳パスのためのローカル専用ワークフローです。通常の英語ドキュメント PR では、生成される .po の広範な変更を延期してもかまいません。コントリビューター向けのガイダンスについては Docs & Translations を、リリース手順については Release Runbook を参照してください。

手動およびアドバイザリワークフロー

月次の古いパッケージスキャン (monthly-outdated.yml)

毎月1日の09:00 UTCに定期的なスキャンを実行します。すべてのワークスペースメンバーに対して cargo outdated --workspace を実行します。古い依存関係が見つかると、dependencies-ラベル付きのイシューを作成します。権限: contents: read + issues: write。重複防止ガードにより、前回のイシューがまだオープンのままの場合に積み重なるのを防ぎます。

The issue のプレビューは切り詰められている場合がありますが、リンクされた monthly-outdated-report アーティファクトには、完全なスキャン結果が 30 日間保持されています。

新しい issue の最初のトリアージ手順: 報告された古いクレートに semver 非互換のバンプがあるか、および利用側クレートの API が変更されたかどうかを確認する。バンプが軽微 (patch/minor) な場合は、短い依存関係のみの PR を作成する。アップグレードが semver 破壊によってブロックされている場合は、メモとブロックしているクレート名を添えて issue をクローズする。

クロスプラットフォームビルド (cross-platform-build-manual.yml)

リリースバイナリをフルターゲットマトリックス(Linux x86_64/aarch64 GNU および MUSL、armv7、arm ハードフロート、macOS Intel/ARM、Windows x86_64、aarch64-linux-android(NDK でビルド))向けにビルドする手動トリガー。タグ付け前に非 Linux ターゲットでブランチがクリーンにコンパイルされることを確認する際に使用してください。

各ディスパッチでは、ビルドとは独立して、小規模なリリースツールのスモークマトリックスも実行されます。この証跡だけが必要な場合は release_tools_only を設定します。その場合、web ジョブと release-build ジョブはスキップされます。信頼済みの GitHub ホスト型 Linux x86_64 では、スモークで固定された cross アーカイブをインストールし、cross と cross-util の両方を確認して、cross --version を記録します。信頼済みの GitHub ホスト型 Windows x86_64 では、安定版リリースワークフローと同じ Rust バージョンおよび Bash-to-Cargo のパス形状を使用し、その後 cargo-tauri.exe --version と cargo tauri --version の両方を記録します。各レッグでは、テストした正確なコミットとランナーのアーキテクチャを公開ジョブサマリーに記録します。スモークはリポジトリへの読み取り専用権限を使用し、公開ジョブ、環境、シークレット、アーティファクトのアップロードはありません。

MUSL ビルドレッグも cross を scripts/ci/install_release_tool.sh 経由でインストールします。このスクリプトは、ピン留めされた上流のリリースアセットを正確にダウンロードし、インストール前に SHA-256 を検証します。必須の Repository Structure ジョブは、ネットワーク呼び出しを行わずに、サポート対象のランナーとアセットのマッピングおよびスモークワークフローの契約をテストします。

qualification_profile: normal をデフォルトとして、完全なマトリクス、dist-broad のraw-binary smoke ルート、標準の dist アーカイブルート、通常のキャッシュポリシー、および既存の ARM64 メモリライフサイクルと macOS の180分上限を保持します。5つのジョブはいずれもジョブスコープで CARGO_INCREMENTAL=0 を維持します。release-tool smoke はツールをインストールする前にディスパッチ入力を検証します。通常のプロダクトジョブは独立したスケジューリングを維持します。

qualification_profile: stable-gnu-ubuntu22 と distribution: dist、release_tools_only: false を指定すると、有限かつ非公開の認定(qualification)が実行されます。空、未知、不正な形式、広範な distribution、tools-only の組み合わせは拒否されます。Ubuntu22 上で GNU のビルド行が4つ実行されます:x86_64、aarch64、armv7、arm。いずれも Stable と同じローカルの build-release-payloads アクションを呼び出し、既存のリンカーおよび ARMv6 のバインディング、Rust1.98、locked release プロファイル、明示的な正規 features、通常の Cargo ジョブ、行ごとに3つのペイロード、90分の上限、上限値を含む83,886,080バイトのメインバイナリ上限を使用します。アクションの features 出力を有効にするのは認定処理のみで、そのマニフェストはこの単一の解決結果を利用します。Stable では証跡スイッチをオフのままにします。

分離された web 用と fixture 用のプロデューサーは、既存のエントリポイントと Stable ツールチェーンのセットアップを使用します。これら3つのビルドロールは、元の web、plugin-smoke-packages、build の共有キーを指定して、固定バージョンの Swatinem アクションを直接呼び出します。fixture のプレフィックスと各 Ubuntu22 ターゲットのプレフィックスは Stable と一致しており、デフォルトのターゲット復元は有効のままです。すべての qualifier キャッシュは、master 上であっても save-if: false を使用します。これらのロールは、Stable と同様に、ワークフロー/ジョブレベルの CARGO_INCREMENTAL 宣言を省略します。固定バージョンのキャッシュアクションは、キャッシュ構成を構築する前に CARGO_INCREMENTAL=0 をエクスポートし、その値を後続のステップにも残します。プロデューサーの受領記録では、実効値である文字列 "0" を必須とし、記録します。完了チェックでも同じ値を確認します。アクションがエクスポートした値は保持されます。通常の web キャッシュポリシーは変更されません。キャッシュの同等性を認めるには、アクションログにおいて実際のプライマリキー、リストアキー、ヒット状況、およびキャッシュのソースが示されている必要があります。これらの入力は、ウォームキャッシュや、後続の Stable ビルド時間を保証するものではありません。

2つのネイティブ・コンシューマーは、Ubuntu22上でx86 GNUを、Ubuntu24-arm上でARM64 GNUを実行し、それぞれ30分の上限が設定されています。それぞれが同一実行のアーカイブを検証・展開し、5分以内にフルverboseのscripted-providerスイートを実行し、無条件にアーカイブ認識型プラグインのスモークテストを呼び出します。rawフォールバックはありません。選択された完全性ジョブは、上流の失敗後も実行され、欠落・スキップ・失敗・キャンセルされたロールをすべて拒否します。変更されていない検証ツールで4つのアーカイブを検査し、12の入力ハッシュとその保存済みELF、コンパイラ/sysrootおよびリソースの観測結果、さらに2つのネイティブ証跡キャリアを確認します。ソースのcommit、tree、run、attempt、profile、web、fixtureの各ハッシュにより、receiptが1つのdispatchに紐付けられます。

以下のルートを受け入れる前に、実際のキャッシュ受領記録を保存し、12件のABI観測結果をすべて解釈し、各ネイティブキャリアについて名前が付けられた13件のプロバイダーテストと18件のアーカイブ対照を確認してください。ジョブが成功したことやキャリアの一覧があることだけでは、これらの結果やメンテナーによるレビューの代わりにはなりません。証拠が欠けている場合や解釈できない場合は受け入れを保留します。予算、リソース、機能、ABIポリシーの自動変更を許可するものではありません。Ubuntu24 ARM64での実行は、Ubuntu22 ARM64のランタイム証明にはなりません。ARM32、コンパニオン実行、Darwin、MUSL、Android、Windows、Stableの全マトリクス、およびリリース準備完了には、それぞれ独自の証拠が必要です。ソースの変更だけでは、これらのいずれのランタイム結果も証明されません。

クロスプラットフォーム Clippy (cross-platform-clippy.yml)

macOS aarch64 および Windows x86_64 ターゲットでの手動および週次スケジュールのアドバイザリ lint カバレッジ。各プラットフォームに --target を設定した必須の PR lint コマンドをミラーしますが、意図的に PR では実行されず、CI Required Gate の一部ではありません。

必須の Linux Clippy、非必須のクロスプラットフォーム Clippy、および対象を絞った Windows Clippy は scripts/ci/run_clippy.sh を呼び出します。このランナーは、サポート対象のコマンド形式、Cargo の終了ステータスの伝播、および共通の実行時間・キャッシュ・コンパイル回数・ダウンロード回数の診断を担当します。ワークフローファイルは引き続き、トリガー、ランナー、ツールチェーン、キャッシュ、タイムアウト、必須ゲートへの所属を担当します。

リリース安定版 (release-stable-manual.yml)

完全なリリースパイプラインを手動でトリガーします。すべてのターゲットをビルドし、GitHub Release を作成し、事前ビルド済みの latest、バージョン付き、および debian の Docker イメージを GHCR にプッシュし、リリースタグで生成された Docker バリアントマトリックスを呼び出し、Web サイトの再デプロイをトリガーし、配布サブワークフロー(Scoop、AUR、Discord、tweet)を呼び出します。Homebrew Core は独自の autobump サービスを通じて新しいリリースを検出します。2 つの環境ゲートでは実行途中でメンテナーの承認が必要です:github-releases(publish ジョブ)と docker。

ダウンロード可能なアセットは、GitHub がホストする Build Level 2 アテステーションを使用します。オフラインバンドルと信頼されたルートマテリアルは、1 つの検証アーカイブに含めて提供され、両方の SBOM 形式はリリースが作成される前にチェックサムが生成され、アテステーションされます。Cosign は引き続き GHCR イメージの署名に限定されます。

64ビットのアーカイブのうち、実験的なAndroid版以外はすべてWASMプラグインホストを含みます。ディスパッチされたリリースでは、GitHub Releaseとそれぞれのイメージpushの前に、この点が検証されます。plugin-smoke-packagesがLinux上でフィクスチャのプラグインパッケージを一度ビルドします。plugin-smokeは各アーカイブを、そのプラットフォームのランナー上でダウンロードし、パッケージ化されたバイナリに対してscripts/ci/plugin_artifact_smoke.shを実行します(これはプルリクエストでcheck-plugin-backendsのスモークレッグが実行するのと同じスクリプトです)。publishとdockerは、すべてのレッグの完了を待ちます。xtaskのテストにより、レッグの一覧がレジストリのターゲットごとのプラグインポリシーと一致するよう保たれます。そのため、ホストを含むターゲットにレッグがない、あるいはホストを含まなくなったのにレッグだけが残る、という状態は起こりません。ビルドレッグは、サイズチェックステップで設定された80 MiBの上限を超えるバイナリを失敗させます。手動実行するCross-Platform Buildワークフローは、ビルドしたバイナリに対して同じレッグを再現します。そのため、配布の変更は、リリースを実行する前に一度のディスパッチで計測・検証できます。タグpushによって開始されたリリースでは、自身のv*タグトリガーでDocker Publishも起動しますが、そのrun はスモークの完了を待ちません。

完全な手順については、リリースランブックを参照してください。

リリース専用のビルドツールは、実行のたびにソースからコンパイルするわけではありません。ワークフローは scripts/ci/install_release_tool.sh を介して、バージョンを固定した上流の cross と Tauri CLI のリリースバイナリをインストールします。このスクリプトは、ランナー固有の各アーカイブについてリポジトリで管理する SHA-256 を検証してから、バイナリを Cargo の bin ディレクトリに配置します。いずれかのツールを更新するには、そのバージョン、アセット名、チェックサムをまとめて更新し、その後 scripts/ci/install_release_tool.test.sh を実行する必要があります。

パッケージの公開者

それぞれは workflow_dispatch でバージョン入力とともにトリガーされます。また、公開が成功した後にリリースワークフローから呼び出されます。

ワークフロー何をするものか
pub-aur.ymlArch User Repository の PKGBUILD を更新し、AUR にプッシュします。
pub-crates.ymlワークスペースの連携リリースをパッケージ化して検証し、その後、crates-io 環境ゲートの下で依存関係順に crates.io へ公開します
pub-scoop.ymlWindows用のScoopマニフェストを更新します

Homebrew Core の公式自動更新サービスは、GitHub の安定版リリースを検出し、独立して formula の更新を作成します。プロジェクト所有の Homebrew publisher や fork token を復元しないでください。これは Homebrew の正式な自動化と重複します。

必要なシークレット

シークレット使用される
AUR_SSH_KEYpub-aur.yml
CARGO_REGISTRY_TOKENリポジトリシークレットは pub-crates.yml に明示的に渡され、保護された公開ジョブからのみ参照される。v0.8.5 では、zerorelay、zeroclaw-relay-proto、zeroclaw-tls に publish-new が必要で、後続の連携更新では publish-update が必要になる
DISCORD_WEBHOOK_URLdiscord-release.yml
TWITTER_ACCESS_TOKEN, TWITTER_ACCESS_TOKEN_SECRET, TWITTER_CONSUMER_API_KEY, TWITTER_CONSUMER_API_SECRET_KEYtweet-release.yml
SCOOP_BUCKET_TOKENpub-scoop.yml, release-stable-manual.yml, scoop-bucket-canary.yml; zeroclaw-labs/scoop-zeroclaw に限定し、Contents の読み取り/書き込み権限を持つ fine-grained PAT
WEBSITE_REPO_PATrelease-stable-manual.yml(ウェブサイトリポジトリの再デプロイをトリガーします)
GITHUB_TOKEN (自動)コミットのプッシュ、PR の作成、または GHCR へのイメージのプッシュを行うすべてのワークフロー

Docker イメージは自動的に提供される GITHUB_TOKEN を使用して GHCR にプッシュされ、別個のレジストリトークンはありません。CARGO_REGISTRY_TOKEN はリポジトリシークレットとして保存し、その名前付きシークレットだけを再利用可能なパブリッシャーにマッピングします。呼び出し先ワークフローがこれを参照するのは、取り消し不能な公開ステップのみです。このステップのジョブでは、crates-io 環境を通じた承認が必要です。トークンを使用しないプレフライトは、これを参照もエクスポートもしません。承認者が公開ジョブを開始できる前に、プレフライトで同じ不変のリリースコミットをパッケージ化します。

Release Stable は、stage 入力を通じて パブリッシャー を2回呼び出します。crates-preflight ジョブは、バイナリのビルドと並行して stage: preflight を実行し、シークレットは使用しません。dispatch によるリリースはまだタグが存在しないため、実行のコミットを直接検証します。GitHub Release の publish ジョブはこれに依存しているため、crates の失敗はリリースが公開される前にリリースを停止させます。GitHub Release の後、crates ジョブはトークンを使って stage: publish を実行します。このステージでは、新しいタグが同じコミットに解決されることを要求し、再検証をスキップして、preflight ステージが記録したダイジェストを持つダッシュボードバンドルをアップロードします。pub-crates.yml の手動 dispatch では、依然として両方の処理が1回の呼び出しで実行されます。

両方のジョブは、scripts/release/ の第二のスパースチェックアウトを .release-tooling に配置し、そこにあるリリーススクリプトを実行します。このチェックアウトはパッケージ化されたツリーから除外され、ツリーは PUBLISH_SOURCE_ROOT を通じて渡されます。リリース実行では、このチェックアウトがリリースコミットになります。既存のタグに対して master から手動ディスパッチすると、master のスクリプトがタグ付きのツリーに対して使われるため、タグを移動させずに公開スクリプトの修正をリリースに反映できます。resolve_crates_release.sh は、それ以外のツーリングコミットをすべて拒否します。

ルートクレートは生成されたダッシュボードを web/dist 配下に含めて提供します。プリフライトでこれを一度ビルドし、すべてのファイルパスと内容のダイジェストを記録し、そのツリーを使ってパッケージを検証したうえで、crates-io-web-dist アーティファクトとしてアップロードします。公開ジョブはダッシュボードを再ビルドしません。このアーティファクトを復元し、publish-crates.sh は、復元されたツリーが記録されたダイジェストと一致しない限り crates.io への公開を行いません。承認が遅れた場合や失敗した公開ジョブを再実行した場合でも見つけられるよう、アーティファクトは 30 日間保持されます。

調整リリースセット内のほとんどの crate はすでに存在し、crates.io の trusted publishing の対象となっています。v0.8.5 リリースではさらに zerorelay、zeroclaw-relay-proto、zeroclaw-tls が作成されるため、そのブートストラップトークンには publish-new を含める必要があります。環境トークンは、このワークフローのすべての crate に trusted-publisher エントリが設定されるまで、引き続きブートストラップ経路となります。これらのエントリを設定したら、CARGO_REGISTRY_TOKEN を保持する代わりに、GitHub が OIDC ID を短期間有効なトークンと交換するようジョブを移行します。

現在、組織では Scoop バケットのデプロイキーが無効化されており、自動の GITHUB_TOKEN は別のリポジトリに書き込めません。SCOOP_BUCKET_TOKEN のスコープはバケットに限定し、メンテナーの広範な権限を持つ CLI トークンを再利用しないでください。パブリッシャーは git push --dry-run で書き込み権限を確認し、その後、実際の更新には同じ Git トランスポートを使用します。

SCOOP_BUCKET_TOKEN のローテーション

デプロイキーが利用できないため、この認証情報は個人アクセストークンであり、そのため独立した2つの障害モードがあります。どちらもリリースを失敗させたことがあります:

  1. トークンの有効期限が切れます。 Fine-grained PAT には最大有効期間が設定されているため、ほかに何も変更がなくても、これは一定のスケジュールで繰り返されます。
  2. 所有者の ID がバケットへの書き込み権限を失う。 トークンが有効なままでも、それに紐付くアカウントが read コラボレーターにすぎない場合があります。この場合、remote: Permission to zeroclaw-labs/scoop-zeroclaw.git denied to <account> と HTTP 403 が返されます。これは認証エラーではないため、権限の問題なのにコードの問題のように見えます。

トークンは個人アカウントではなくZeroClaw-Botアカウントで管理し、リリース手順が1人のメンテナーの認証情報に依存しないようにします。ローテーションするには:

  1. ZeroClaw-Bot として、リソース所有者を zeroclaw-labs に設定し、リポジトリアクセスを単一のリポジトリ zeroclaw-labs/scoop-zeroclaw のみに制限した、きめ細かい PAT を作成してください。リポジトリ権限 → コンテンツ: 読み取りと書き込みのみを付与してください。それ以外は何も設定しないでください。
  2. org がトークンを承認したことを確認してください。組織をリソース所有者とするきめ細かい PAT は承認されるまで保留中のままであり、保留中のトークンは認証できますが push はできません。
  3. ZeroClaw-Bot がバケットに対する write 権限をまだ持っていることを確認します: gh api repos/zeroclaw-labs/scoop-zeroclaw/collaborators/ZeroClaw-Bot/permission --jq '.role_name'。手順 1 ではリポジトリへのアクセスは付与されず、トークンが使用できる範囲を限定するだけです。トークンが所有者がすでに持っている権限を超えることはできません。
  4. シークレットを設定します: gh secret set SCOOP_BUCKET_TOKEN --repo zeroclaw-labs/zeroclaw。
  5. バケットに触れずに Scoop Bucket Canary をディスパッチして検証します。グリーンの実行により、新しいトークンで push できることが証明されます。

ローテーションする際は、有効期限を永続的な場所に記録してください。いずれにせよ、カナリアは期限切れのトークンを 1 週間以内に検出しますが、検出されるのはすでに機能しなくなった後です。

AURパッケージのオーナーシップ

プロジェクトが所有するパッケージは現在 zeroclawlabs で、zeroclaw-bot によってメンテナンスされています。正規名 zeroclaw パッケージはサードパーティのパッケージであり、AUR_SSH_KEY のローテーションによって引き継ぐことはできません。そのメンテナが引き続き非アクティブである場合は、pkgname またはワークフローのクローン対象を変更する前に AUR orphan-request プロセス に従ってください。所有権の移転後は、パッケージ名の変更またはマージをレビュー済みの 1 つの変更としてまとめて調整してください。

ビルドキャッシュの動作

ci.yml 内の Rust 負荷の高いジョブの多くは、ローカルの ./.github/actions/rust-cache コンポジットアクションを通じてキャッシュしています。このアクションには、Blacksmith のコンパイル呼び出し元から use-blacksmith: 'true' が渡されます。これは、それらのジョブが直接指定しているランナーラベルと一致します。両方の値は、Actions の変数ではなく、ci.yml にチェックインされた定数です。vars はフォーク由来の pull_request 実行では読み取れないため、以前の CI_USE_BLACKSMITH トグルは、すべてのフォーク PR(このリポジトリの PR の 90%)を、キャッシュがコールドな GitHub ホステッドランナーへ黙って送っていました。master が Blacksmith へ移行した際に GitHub Actions キャッシュのシードを停止していたためです。定数に切り替えたことで、これらのフォーク PR のジョブは、master の対応するジョブと同様に、Blacksmith ランナー上で useblacksmith/rust-cache(Blacksmith NVMe sticky disk)を使用します。Linux コンパイルジョブのラベルとプロバイダー入力を変更すると、tests/architecture/ci_runner_labels.rs がそれらを同期させるため、レビュー済みの 1 つのコミットで、そのジョブ群を ubuntu-latest + Swatinem/rust-cache に戻せます。選択にかかわらず、両方のアクション参照はコンポジットに存在するため、両方とも許可リストに残しておく必要があります。Windows のタスク所有者リカバリは、Blacksmith 上での直接の Swatinem/rust-cache の例外であり、master でシードされた独自の依存関係キャッシュを持ちます。macOS と Windows のビルドレッグは、GitHub Actions キャッシュに対して Swatinem/rust-cache を使い続けます。また、fmt、nix-eval、docs-style ジョブ(いずれもワークスペースをコンパイルしない)は Rust キャッシュを使用しません。codeql.yml も Rust スキャンに同じ Blacksmith ラベルを固定しているため、もはやどのワークフローも CI_USE_BLACKSMITH 変数を読み取りません。この変数はリポジトリの設定から削除できます。キャッシュ関連の不安定な挙動を調査する際には、次の動作を把握しておくと役立ちます:

  • Matrixレグには個別のキャッシュキーが必要です。 キャッシュキーは、ジョブID(またはshared-key)、ランナーのOSとアーキテクチャ、ツールチェーン、CARGO*/RUST*環境変数、そしてlockfileから導出されます。そのため、feature flagやcargo引数のみが異なるMatrixレグは同じキーに解決されてしまいます。最初に保存したレグがそのキーを所有し、他のすべてのレグは依存関係セットが一致しないキャッシュを復元することになります。レグごとのキーを導入する前は、cranelift plugin-backendレグが、pulleyおよびruntime-onlyレグとキーを共有していたため、masterを含むすべての実行で約620個の依存クレート(約4分)を再コンパイルしていました。そのため、checkとcheck-plugin-backendsでは、各レグにcache-keyというカンマを含まないMatrixフィールドを与え、それをshared-keyとして渡しています。依存関係セットが実際に一致するレグは、同じキーを共有しても構いません。新しいRust Matrixジョブも同じようにすべきです。
  • キャッシュへの書き込みはマスターのみで行われます。 save-if は github.ref == 'refs/heads/master' を条件としているため、PR の実行ではマスター由来のキャッシュを読み取りますが、更新は行いません。PR ブランチがブランチ固有のアーティファクトで共有キャッシュを汚染することはありません。master への push トリガーによって、マージ後に信頼できるキャッシュ書き込みの実行がワークフローに提供されます。
  • Recoveryは成功時のみ保存します。 そのcache-on-failure: 'false'により、失敗したRecoveryの実行ではキャッシュの初期投入(シード)が行われません。composite-cacheを使う他のコンパイルジョブはcache-on-failure: trueのままなので、masterの部分的な実行でも、次回の試行をウォームな状態で開始できるようキャッシュを投入できます。
  • Windows ビルドキャッシュが有効になっています。 Windows ビルドレグは、Linux や macOS と同じ固定された Rust キャッシュアクションを実行します。Windows のキャッシュ動作が不安定になったり、リグレッションが発生したりした場合は、ワークフローの変更を元に戻し、失敗した restore/save の証跡をキャッシュの issue に記録してください。
  • 増分コンパイルは無効化されています。 ワークフローレベルで CARGO_INCREMENTAL: 0 が設定されています。増分ビルドはキャッシュサイズを増大させ、部分的に古くなった条件の下で再現性のないアーティファクトを生成します。
  • cargo-deny と cargo-nextest は毎回新規インストールされます。 security ジョブは cargo install cargo-deny --locked を実行し、Linux の test ジョブと定期実行される platform-tests.yml の両レッグは、適切な cargo-nextest バイナリを get.nexte.st から取得します。Windows の advisory PR ジョブは、多数の信頼されていない PR で実行されるため、固定されたバージョンの nextest リリースアーカイブをダウンロードし、展開前にハードコードされた SHA-256 を検証します。どちらのツールもキャッシュされないため、各インストールはそれぞれのジョブに一定のコストを加えます。どちらかを taiki-e/install-action に切り替えればキャッシュできるようになりますが、そのアクションは現時点では許可リストに含まれていません。

ゲートが赤になったとき

症状最初に確認すべきこと
uses: の参照が変更された後、Release Stable がジョブ数ゼロで startup_failure により停止する実行サマリーとリポジトリのActionsポリシーを確認してください。GitHubがselected-actionsの拒否を報告している場合は、変更されたrefを許可リストと比較し、拒否されたパターンのみを追加して、設定の反映を待ってから新しい実行をディスパッチしてください。それ以外の場合は、ワークフロー定義またはその他のリポジトリポリシーを調査してください。startup_failure だけでは原因を特定できません
CI Required Gate 赤まず fmt、次に lint、続いて test、最後に build を実行します
validate のリリースに失敗しましたCargo.toml のバージョンがワークフローの入力と一致しない、またはタグが既に存在します
リリースビルドのステップが失敗しました特定のターゲットのジョブログ。Android は experimental であり、continue-on-error で実行されます。
環境ゲートがタイムアウトしましたワークフロー実行ページからタイムアウトしたジョブのみを再実行する
配布元のパブリッシャーに失敗しましたまず、対応するサブワークフローを手動で dry_run: true で再実行してください。

許可されたアクション

このリポジトリは selected モードで Actions を実行しており、この許可リストに含まれるアクションのみ実行できます。許可リストは厳格に保つ必要があります。新しいサードパーティ製アクションを追加する前には、メンテナーの明示的な承認が必要です。

すべてのサードパーティ参照は、末尾にバージョンコメントを付けた完全なコミット SHA に固定されています。以下のバージョン列には、そのコメントが記録されています。

対応使用される目的
actions/checkout (v6.0.2)ほとんどのワークフローリポジトリのチェックアウト
actions/cache (v4.2.3, v5.0.5)docker-image-pr.yml、tweet-release.yml汎用依存関係および Trivy データベースのキャッシュ
actions/setup-node (v7.0.0)ci-sbom.yml, ci.yml, cross-platform-build-manual.yml, daily-npm-audit.yml, pub-crates.yml, release-stable-manual.ymlnpm SBOM の生成、Web テスト/監査、Web/デスクトップ ビルド用の Node ツールチェーン
actions/upload-artifact (v7.0.1)release-stable-manual.yml、cross-platform-build-manual.yml、docker-publish.yml、trivy-scheduled.ymlビルド成果物と Trivy SARIF 引き継ぎ成果物をアップロードする
actions/download-artifact(v8.0.1)release-stable-manual.yml、cross-platform-build-manual.yml、docker-publish.ymlビルド成果物と Trivy SARIF ハンドオフ成果物をダウンロード
actions/attest (v4.2.2)release-stable-manual.ymlリリースアセット向けに GitHub ホスト型の Build Level 2 プロベナンスを生成する
actions/labeler (v6.1.0)pr-path-labeler.yml.github/labeler.yml からパス/スコープラベルを適用する
dtolnay/rust-toolchain (stable, v1)ci.yml, platform-tests.yml, pub-crates.yml, release-stable-manual.yml, cross-platform-build-manual.yml, cross-platform-clippy.yml, daily-audit.yml, docs-deploy.yml, codeql.ymlRust ツールチェーンをインストールする
Swatinem/rust-cache (v2.9.2)ci.yml(GitHub ホスト型の composite パスと Blacksmith Windows への直接リカバリ)、platform-tests.yml、pub-crates.yml、release-stable-manual.yml、cross-platform-build-manual.yml、cross-platform-clippy.yml、docs-deploy.ymlCargo のビルド・依存関係キャッシュ(GitHub ホステッドランナーおよび Blacksmith Windows でのリカバリ)
useblacksmith/rust-cache (v3.0.1)ci.yml(./.github/actions/rust-cache の Blacksmith パス)Cargoのビルド/依存関係キャッシュ(Blacksmith sticky disk)。各Blacksmithコンパイルジョブがコンポジットに渡すuse-blacksmith: 'true'入力によって選択される(リポジトリにチェックインされた定数)
docker/setup-buildx-action (v3.11.1, v4.0.0)release-stable-manual.yml、docker-publish.ymlDocker Buildx のセットアップ
docker/login-action (v3.4.0, v4.1.0)release-stable-manual.yml, docker-publish.yml, trivy-scheduled.ymlGHCR認証
docker/build-push-action (v6.18.0, v7.1.0)release-stable-manual.yml、docker-publish.ymlマルチプラットフォームのイメージビルドとプッシュ
sigstore/cosign-installer (v3.8.1)release-stable-manual.yml、docker-publish.ymlキーレスなGHCRコンテナイメージ署名のためにcosignをインストールする
anchore/sbom-action (v0.24.0)release-stable-manual.yml各リリースごとに SPDX + CycloneDX の SBOM を生成する
aquasecurity/trivy-action (v0.36.0)docker-image-pr.yml, docker-publish.yml, trivy-scheduled.ymlコンテナの脆弱性スキャン(レポートのみ)
github/codeql-action/upload-sarif (v3.36.2)docker-publish.yml, trivy-scheduled.yml, ci-code-analysis.ymlTrivy と Semgrep の SARIF レポートを Security タブにアップロードする
github/codeql-action/init (v4.37.8)codeql.ymlCodeQL 分析(Rust および JS/TS)を初期化する
github/codeql-action/analyze (v4.37.8)codeql.ymlCodeQL SARIFをセキュリティタブにアップロードする

GitHub Releaseそのものは、releaseアクションではなく、publishジョブ内のgh release createで作成されます。

同等の許可リストパターン(意図的に狭く保たれています):

actions/*
dtolnay/rust-toolchain@*
Swatinem/rust-cache@*
useblacksmith/rust-cache@*
docker/*
sigstore/cosign-installer@*
anchore/sbom-action@*
aquasecurity/trivy-action@*
github/codeql-action/upload-sarif@*
github/codeql-action/init@*
github/codeql-action/analyze@*

現在の有効なポリシーをエクスポートします:

sh

gh api repos/zeroclaw-labs/zeroclaw/actions/permissions
gh api repos/zeroclaw-labs/zeroclaw/actions/permissions/selected-actions

uses: アクションのソースを追加または変更するすべてのPRには、本文にホワイトリストの影響に関する注記を含める必要があります。広範なワイルドカードの例外を避け、確認済みの不足しているアクションに対してのみホワイトリストを拡張してください。

メンテナンスルール

  • CI Required Gate を決定論的で小さく保つ。ゲートにジョブを追加するには、明確な品質の根拠が必要。
  • すべてのサードパーティのアクション参照は、上記の許可リストポリシーに従って完全なコミット SHA に固定する必要があります。
  • ci.yml、dev/ci.sh、.githooks/pre-push の整合性を保ってください。共通ゲートは scripts/ci/ に配置し、各呼び出し元はコマンドをコピーするのではなくヘルパーを呼び出す必要があります。スタンドアロンのファームウェアプロトコルゲートについて、ドキュメント化されているローカルのエントリーポイントは ./dev/ci.sh firmware-protocol です。
  • scripts/ci/prepare_docker_context.sh、docker-image-pr.yml、および release-stable-manual.yml 内の Docker ジョブを揃えておくことで、リリースワークフローが公開するのと同じコンテキスト形状を PR の検証でも確認できるようにします。
  • リリースアテステーション、チェックサム、SBOM、または検証アーカイブのシーケンスを変更した後は python3 scripts/ci/release_attestation_contract_test.py を実行してください。
  • docs-style ゲートジョブは bash scripts/ci/docs_quality_gate.sh(markdown lint + emダッシュの文章チェック)と bash scripts/ci/docs_links_gate.sh(変更行のリンクゲート)を実行します。ドキュメントの変更をプッシュする前に、ローカルで両方のスクリプトを実行してください。

緊急ロールバック

もしホワイトリストがインシデント中に重要なアクションをロックアウトする場合:

  1. 一時的にActionsのポリシーをallに戻します。
  2. 欠落しているエントリを特定した後、selected の許可リストを復元する。
  3. インシデントと最終的な許可リストの差分を記録します。

これは all モードへの唯一の正当な経路であり、インシデントを超えて存続させてはなりません。