Blacksmith Testbox
スコープ
Testbox は、リモート CI パリティ、注入されたシークレット、ホステッドサービス、またはローカルマシンでは安価に提供できない OS/ランタイムイメージが必要な場合に使用します。
OpenClaw では、Blacksmith が利用できない場合や、所有するクラウド容量が推奨される場合に、Crabbox がサポートされる代替手段です。
通常のローカルテスト/ビルドループには Testbox をデフォルトで使用しないでください。リポジトリに通常の反復処理用のドキュメント化されたローカルコマンドがある場合は、それらを最初に使用して、ウォームキャッシュ、ローカルビルド状態、および高速フィードバックを維持してください。
Testbox は高価なパスです。意図的に使用してください。
OpenClaw メンテナーは、環境変数 OPENCLAW_TESTBOX=1 を設定するか、エージェントルールに記述することで、Testbox 優先の検証をオプトインできます。このモードはメンテナーのみが使用でき、Blacksmith へのアクセスが必要です。
OpenClaw で OPENCLAW_TESTBOX=1 が設定されている場合:
- 長時間、広範囲、または不確実な作業のために、早期に Testbox をプリウォームします。
pnpmゲート、e2e、パッケージライクな証明、および広範なスイートには Testbox を優先します。- 同じタスク/セッション内のすべての run コマンドで、同じ Testbox ID を再利用します。
- タスクで
OPENCLAW_LOCAL_CHECK_MODE=throttled|fullが明示的に設定されている場合、またはユーザーがローカルでの証明を要求した場合にのみ、ローカルコマンドを使用します。
CLI のインストール
blacksmith がインストールされていない場合は、インストールします:
curl -fsSL https://get.blacksmith.sh | sh
カナリーチャンネル(最先端)の場合:
BLACKSMITH_CHANNEL=canary sh -c 'curl -fsSL https://get.blacksmith.sh | sh'
次に認証します:
blacksmith auth login
エージェントトリガーによるブラウザ認証(非対話型)
エージェントが testbox コマンド(ウォームアップ、実行など)を実行する前にユーザーが認証されていることを確認する必要がある場合、非対話型モードでブラウザベースの認証を使用します。これにより、ユーザーがサインインするためのブラウザが開きます。エージェントはブラウザと対話しません。ダッシュボードの組織セレクターはスキップされ、ユーザーはサインインフローのみを表示します。
必須コマンド(--non-interactive を使用する場合、--organization は必須です):
blacksmith auth login --non-interactive --organization <org-slug>
組織スラッグは、環境変数 BLACKSMITH_ORG または --org グローバルフラグから取得できます。どちらも設定されていない場合、エージェントはプロジェクトの既知の組織(例:リポジトリ設定やユーザーコンテキストから)を使用する必要があります。例:
blacksmith auth login --non-interactive --organization acme-corp
blacksmith --org acme-corp auth login --non-interactive --organization acme-corp
フロー: CLI がローカルコールバックサーバーを起動し、ダッシュボード認証ページにブラウザを開き、最大2分間ブロックします。ユーザーはブラウザでサインインと承認を完了します。ダッシュボードがローカルホストにトークンでリダイレクトします。CLI が認証情報を保存して終了します。その後、エージェントが続行します。
このフローでは --api-token を使用しないでください — それはヘッドレス/トークンベースの認証用です。このスキルは、ユーザーが Web UI 経由でのサインインを希望する場合のブラウザベースの認証に焦点を当てています。
オプションフラグ:
--dashboard-url <url>— ダッシュボード URL を上書きします(例:ステージング環境用)
最初に決定: ローカルか Testbox か
ウォームアップする前に、リポジトリの独自の手順を確認してください。
以下の場合、ローカルコマンドを優先します:
- リポジトリがサポートされているローカルテスト/ビルドワークフローをドキュメント化している場合
- 単体テスト、リンター、型チェック、フォーマット、またはその他のローカルのみの検証を反復処理している場合
- ウォームなローカルキャッシュと高速な繰り返し実行から価値が得られる場合
- コマンドにリモートシークレット、ホステッドサービス、または CI のみのイメージが必要ない場合
以下の場合、Testbox を優先します:
- リポジトリが CI パリティまたはリモート検証を明示的に必要とする場合
- コマンドにシークレット、サービスコンテナ、またはプロビジョニングされたインフラが必要な場合
- CI のみの障害を再現している場合
- GitHub Actions の正確なワークフローイメージ/ジョブ環境が必要な場合
特に OpenClaw では、通常のローカル反復処理は、メンテナー Testbox モードが OPENCLAW_TESTBOX=1 で有効になっていない限り、ローカルのままです:
pnpm check:changedpnpm test:changedpnpm test <path-or-filter>pnpm test:serialpnpm build
OPENCLAW_TESTBOX=1 が有効な場合、これらの同じリポジトリコマンドをウォーム Testbox 内で実行します。ユーザーが1つのコマンドに対してラップトップに優しいローカルでの証明を希望する場合は、明示的なエスケープハッチ OPENCLAW_LOCAL_CHECK_MODE=throttled を使用します。
インストール可能パッケージのプロダクト証明には、アドホックな Testbox コマンドよりも GitHub Package Acceptance ワークフローを優先します。これは、1つのパッケージ候補(source=npm、source=ref、source=url、または source=artifact)を解決し、それを package-under-test としてアップロードし、GitHub/Blacksmith ランナー上でその特定の tarball に対して再利用可能な Docker E2E レーンを実行します。信頼できるワークフロー/ハーネスコードには workflow_ref を、古い信頼できるブランチ、タグ、または SHA をテストする際にパックするソースリファレンスには package_ref を使用します。
セットアップ: コーディング前のウォームアップ
Testbox が必要と判断した場合は、早期にウォームアップします。これにより、ID が即座に返され、作業中にバックグラウンドで CI 環境が起動します:
blacksmith testbox warmup ci-check-testbox.yml
# → tbx_01jkz5b3t9...
この ID を現在のセッションで保存します。すべての run コマンドに必要です。blacksmith testbox list は診断用であり、再利用可能な作業キューとしては扱わないでください。リストされたボックスは、組織/リポジトリレベルで表示可能であっても、現在のローカルエージェントレーンでは使用できないか、古くなっている可能性があります。
OpenClaw メンテナー Testbox モードでは、長時間または広範囲のタスクの開始時にプリウォームします:
blacksmith testbox warmup ci-check-testbox.yml --ref main --idle-timeout 90
pnpm testbox:claim --id <ID>
ビルドアーティファクトのウォームアップは、e2e/パッケージ/ビルドの証明がシードされた dist/、dist-runtime/、およびビルドオールキャッシュの恩恵を受ける場合に使用します:
blacksmith testbox warmup ci-build-artifacts-testbox.yml --ref main --idle-timeout 90
pnpm testbox:claim --id <ID>
ウォームアップは、完全な CI 環境(依存関係がインストールされ、サービスが開始され、シークレットが注入され、デフォルトブランチでリポジトリがクリーンチェックアウトされた状態)で VM をプロビジョニングする GitHub Actions ワークフローをディスパッチします。
OpenClaw では、raw コミット SHA は warmup --ref の信頼できるディスパッチ参照ではありません。ブランチまたはタグを使用してください。ビルドアーティファクトワークフローは、openclaw@beta および openclaw@latest を内部的に SHA キャッシュキーに解決します。
オプション:
--ref <branch|tag> ディスパッチ対象の Git 参照(デフォルト: リポジトリのデフォルトブランチ)
--job <name> ワークフロー内の特定のジョブ(複数ある場合)
--idle-timeout <min> アイドルタイムアウト(分)(デフォルト: 30)
重要: 常にリポジトリルートから実行
blacksmith testbox コマンドは常に git リポジトリのルート から呼び出してください。CLI は、現在の作業ディレクトリを rsync の --delete を使用して testbox に同期します。サブディレクトリから実行すると(例: cd backend && blacksmith testbox run ...)、rsync はそのサブディレクトリのみをミラーリングし、testbox 上の その他すべてを削除 します — dashboard/、cli/ などの他のディレクトリが消去されます。
# 正しい — リポジトリルートから実行し、コマンド内でパスを使用
blacksmith testbox run --id <ID> "cd backend && php artisan test"
blacksmith testbox run --id <ID> "cd dashboard && npm test"
# 間違い — CLI を呼び出す前にサブディレクトリに cd しないでください
cd backend && blacksmith testbox run --id <ID> "php artisan test"
シェルがサブディレクトリにある場合は、最初にリポジトリルートに cd します:
cd "$(git rev-parse --show-toplevel)"
blacksmith testbox run --id <ID> "cd backend && php artisan test"
コマンドの実行
blacksmith testbox run --id <ID> "<command>"
run コマンドは、testbox がまだ起動中の場合は自動的に準備完了を待機するため、ウォームアップ直後にステータスを確認せずに run を呼び出すことができます。
OpenClaw では、ガード付きランナーラッパーを優先して使用することで、古い/再利用された ID が Blacksmith CLI が時間を費やして同期したり、紛らわしいキー欠落エラーを出力する前に失敗するようにします:
pnpm testbox:run --id <ID> -- "OPENCLAW_TESTBOX=1 pnpm check:changed"
このラッパーは、ローカルの Testbox ごとのキーがない場合、またはこの OpenClaw チェックアウトで pnpm testbox:claim --id <ID> によって ID が要求されていない場合に実行を拒否します。これは、GitHub アカウントや通常の SSH キーの問題ではなく、期待される修復として扱ってください。ローカルキーだけでは不十分です。準備完了したボックスでも、別のレーンからの古い rsync 状態が残っている可能性があります。
エージェントがクラッシュした場合、リモートボックスは Blacksmith のアイドルタイムアウトに依存します。ローカルの OpenClaw 要求マーカーは自動的に削除されないため、ラッパーは12時間以上経過した要求を古いものとして扱います。意図的な長時間実行作業の場合のみ、OPENCLAW_TESTBOX_CLAIM_TTL_MINUTES=<minutes> で上書きしてください。
手動で組み立てたコマンドで広範なゲートを実行する前に、次のコマンドも実行できます:
pnpm testbox:sanity -- --id <ID>
Testbox からのファイルダウンロード
download コマンドを使用して、実行中の testbox からローカルマシンにファイルまたはディレクトリを取得します。これは、ビルドアーティファクト、テスト結果、カバレッジレポート、または testbox で生成された出力を取得するのに便利です。
blacksmith testbox download --id <ID> <remote-path> [local-path]
リモートパスは、testbox の作業ディレクトリを基準とします(run と同じ)。ローカルパスが指定されていない場合、ファイルは同じベース名を使用して現在のディレクトリに保存されます。
ディレクトリをダウンロードするには、リモートパスの末尾に / を追加します。これにより、再帰モードがトリガーされます:
# 単一ファイルのダウンロード
blacksmith testbox download --id <ID> coverage/report.html
# 特定のローカルパスへのファイルダウンロード
blacksmith testbox download --id <ID> build/output.tar.gz ./output.tar.gz
# ディレクトリ全体のダウンロード
blacksmith testbox download --id <ID> test-results/ ./results/
オプション:
--ssh-private-key <path> SSH 秘密鍵へのパス(ウォームアップで --ssh-public-key を使用した場合)
ファイル同期の仕組み
このモデルを理解することは、Testbox を正しく使用するために重要です。
run を呼び出すと、CLI はコマンドを実行する前に、ローカルの変更をリモート testbox に デルタ同期 します:
-
Testbox VM は、ウォームアップ時の参照でクリーンな
actions/checkoutから起動します。ウォームアップ中にワークフローのセットアップ手順(例:npm install、pip install、composer install)が実行され、リモート VM 上の依存関係ディレクトリが設定されます。 -
各
runで、CLI は git を使用して、前回の同期以降にローカルで変更されたファイルを検出します。追跡されているファイルと、無視されていない untracked ファイル(つまり、git ls-filesが報告するファイル)のみを同期します。 -
.gitignoreで無視されたディレクトリは同期されません。 つまり、node_modules/、vendor/、.venv/、build/、dist/などのディレクトリはローカルマシンから転送されません。testbox は、ウォームアップワークフローの手順で設定されたこれらのディレクトリの独自のコピーを使用します。 -
前回の同期以降に何も変更されていない場合(同じ git コミットとワーキングツリーの状態)、同期は速度向上のために完全にスキップされます。
これが重要な理由
-
依存関係の変更:
package.json、requirements.txt、composer.json、go.modなどの依存関係マニフェストを変更した場合、ロック/マニフェストファイルは同期されますが、実際の依存関係ディレクトリは同期されません。testbox 上でインストールコマンドを再実行する必要があります:blacksmith testbox run --id <ID> "npm install && npm test" blacksmith testbox run --id <ID> "pip install -r requirements.txt && pytest" blacksmith testbox run --id <ID> "composer install && phpunit" -
生成/ビルドアーティファクト: テストがビルドステップ(例:
npm run build、make)に依存しており、ビルド出力に影響するソースファイルを変更した場合は、テスト前に testbox でビルドを再実行します。 -
新しい untracked ファイル: ローカルで作成した新しいファイルは同期されます(gitignore されていない限り)。事前に
git addする必要はありません。 -
削除されたファイル: ローカルで削除したファイルは、リモート testbox でも削除されます。同期モデルは、リモートをローカルの管理対象ファイルセットと一致させます。
重要: ローカルテストを禁止しないでください
ローカル検証が禁止されていると想定しないでください。多くのリポジトリは、高速でウォームなローカルループに意図的に投資しており、すべての実行を Testbox に強制すると、その利点が失われます。
Testbox は、実際に必要なチェック(リモートパリティ、シークレット、サービス、CI のみのランナー、またはワークフローイメージに対する再現性)に使用してください。
リポジトリがローカルテスト/ビルドが通常のパスであると示している場合は、リポジトリに従ってください。
OpenClaw メンテナーの例外: OPENCLAW_TESTBOX=1 がユーザーまたはエージェント環境によって設定されている場合、このリポジトリでは Testbox を通常の検証パスとして扱います。OPENCLAW_LOCAL_CHECK_MODE=throttled|full を明示的なローカルエスケープハッチとして使用します。
使用すべき場合
以下の場合に Testbox を使用します:
- データベースマイグレーションまたは破壊的な環境チェックを実行する場合
- ローカルにないシークレットや環境変数に依存するコマンドを実行する場合
- CI のみの障害を再現するか、ワークフローイメージに対して検証する場合
- プロビジョニングされたサービスやリモートランナーを必要とする動作を検証する場合
- リポジトリまたはユーザーがそれを望む場合に、コミット/プッシュ前の最終的なパリティチェックとして
リポジトリのガイダンスに基づいて、そのリストを調整してください。リポジトリがサポートされているローカルテスト/ビルドをドキュメント化している場合は、ルーチンの反復処理にはローカルを優先し、パリティまたはリモート状態が必要なチェックに Testbox を取っておきます。
ワークフロー
- リポジトリのローカルループが適切なデフォルトかどうかを判断します。OpenClaw の場合、
OPENCLAW_TESTBOX=1により Testbox がメンテナーのデフォルトになります。 - Testbox が必要な場合、早期にウォームアップします:
blacksmith testbox warmup ci-check-testbox.yml --ref main --idle-timeout 90→ ID を保存、次にpnpm testbox:claim --id <ID> - testbox がバックグラウンドで起動している間にコードを記述します。
- 必要なときにリモートコマンドを実行します:
pnpm testbox:run --id <ID> -- "OPENCLAIM_TESTBOX=1 pnpm check:changed" - テストが失敗した場合、コードを修正し、同じウォームボックスに対して再実行します。
- 依存関係マニフェスト(package.json など)を変更した場合は、インストールコマンドを先頭に追加します:
blacksmith testbox run --id <ID> "npm install && npm test" - 小さな PR で完全な同期が報告されたり、ボックスが再利用されたり期限切れになったりした場合は、低速ゲートの前にリモートコピーの健全性を確認します:
pnpm testbox:run --id <ID> -- "pnpm testbox:sanity"。ルートファイルの欠落や大量の追跡ファイル削除が報告された場合は、ボックスを停止して新しいものをウォームアップします。意図的にボックスを再利用する場合にのみOPENCLAW_TESTBOX_ALLOW_MASS_DELETIONS=1を使用しますが、その前に対応するチェックアウトと基本的なgit statusが期待どおりであることを確認してください。 - 終了したら、特に
idle-timeoutをカスタム値に設定している場合は、blacksmith testbox stop --id <ID>でボックスを停止してリソースを節約します。テストボックスは30分のデフォルトのアイドルタイムアウト後に自動的に停止します。
トラブルシューティング
認証エラー
認証されていない場合は、以下を実行します:
blacksmith auth login --non-interactive --organization <org-slug>
依存関係の欠落
依存関係マニフェストを変更した場合、またはウォームアップ後にインストールされたが、同期に含まれないディレクトリ(例: node_modules)にある場合は、testbox で依存関係を再インストールします:
blacksmith testbox run --id <ID> "npm install"
blacksmith testbox run --id <ID> "pip install -r requirements.txt"
ボックスが応答しない
ボックスが応答しない場合、最も可能性の高い原因はアイドルタイムアウトです。新しいボックスでウォームアップし、以前の ID は破棄します。
blacksmith testbox warmup ci-check-testbox.yml --ref main --idle-timeout 90
# 新しい ID を保存
ファイル同期の問題
ファイルが同期されていない場合は、リポジトリルートにいて、リモートパスが正しいことを確認します:
cd "$(git rev-parse --show-toplevel)"
blacksmith testbox run --id <ID> "ls -la"
ウォームアップボックスをそのままにして、問題が解決しない場合は、新しいボックスでウォームアップします。
セキュリティに関する考慮事項
Testbox は、ウォームアップ中にワークフロー定義に従ってシークレットと環境変数を注入します。シークレットは testbox の存続期間中利用可能であり、ウォームアップに使用されたのと同じワークフロー設定を使用して実行されるすべての run コマンドで利用できます。
- 機密性の高い操作には専用のボックスを使用します
- 機密性の高いコマンドを実行した後はボックスを停止します
- ボックス ID を安全に保存します(セッションキーと同様に扱います)
- 機密データを扱う testbox からダウンロードしたファイルをクリーンアップします
- ダウンロードしたアーティファクトの権限を確認します
- 必要がなくなったらボックスを停止します
- 複数のボックスでシークレットを再利用しないでください
CI/CD 統合
Testbox は CI/CD パイプライン内から直接使用できます。例えば:
# CI ジョブからのウォームアップ
blacksmith testbox warmup ci-check-testbox.yml --ref ${{ github.ref }} --idle-timeout 30
# later in the pipeline
blacksmith testbox run --id <ID> "pnpm test"
ただし、CI 環境では、Blacksmith のビルトイン CI ランナー機能が、手動の Testbox 管理なしで CI ジョブを実行するためのよりシームレスなオプションを提供する場合があることに注意してください。Testbox は主に、CI 環境のアドホックなリモート検証と再現のために設計されています。