zudo-test-wisdom
GitHub リポジトリ

検索したい単語を入力

いつでも検索バーを開ける

CIランナーのサイジング

リポジトリの可視性で決めるプロバイダー選択、Blacksmithランナーの形状と料金、最小構成を既定とするスタンス、そして「大きい/別のランナーが本当に効くのはいつか」を判断する4つのルール。

このページが埋める空白

このガイドの他のページは、「CIランナー」を単一の固定された存在であるかのように扱っています。実行ティアはPRゲートが「10分未満」で走ることを前提とし、重いテストの判断ルールは環境的に実行不能なテストを「対応可能なハードウェア」へ送り、定期再試験はプラットフォーム依存のスペックを「ホスト型のmacOS」に載せます。これらのページはどれも、2 vCPUのLinuxランナーが存在し、安価で、既定で手を伸ばす対象である、ということを暗黙のうちに前提にしています。

しかしそのどれもが、その下の層を文書化していません。どんなランナーの形状が存在し、どう課金され、そして「大きい/別のランナーが本当に効くのはいつか」を判断するルールは何か。 その知識はたいてい、あるプロジェクトのワークフローファイル冒頭のコメントに書かれたまま、そこで死んでいきます — 次のプロジェクトが見つけられる場所には決して書き残されないのです。このページはその欠けた層であり、これらの戦略がチューニング対象としているBlacksmithというランナープロバイダーに対して書かれています。

Note

このページの料金は、2026-07-05にBlacksmithのライブページ(ランナー概要料金)に対して再検証しました。 従量課金のレートは変動します。すべての金額を「2026-07時点」のものとして扱い、予算に記載する前に必ず2つの出典ページを再確認してください。

サイジングの前に、プロバイダー選択

以下のすべてのルールは、CIの分数に金を払っていることを前提にしています。その前提がそもそも成り立つかどうかは、どのラベルやサイジング表よりも前に来るひとつの問いで決まります。リポジトリはパブリックか、プライベートか?

  • パブリックリポジトリ → 標準のGitHubホスト型ランナー一択。 最大の理由は、それだけで十分な理由です:無料だからです。GitHubの課金ポリシーは直接こう述べています — 「GitHub Actions usage is free for self-hosted runners and for public repositories that use standard GitHub-hosted runners(セルフホスト型ランナーと、標準のGitHubホスト型ランナーを使うパブリックリポジトリでは、GitHub Actionsの利用は無料)」(2026-07-05検証)。どんな分単価の割引も、請求額ゼロには勝てません。パブリックリポジトリなら、プロバイダーの問いはここで終わりです。注意点はひとつだけで、それはこのページの既定スタンスの予告でもあります:より大きなランナーは、パブリックリポジトリであっても常に課金されます — パブリックリポジトリのジョブが標準形状を離れた瞬間に、請求額が存在し始めるのです。

  • プライベートリポジトリ → Blacksmith。理由の第1位はコストです。 プライベートリポジトリはプランに込みの分数を消費し、使い切った後は1分ごとにGitHubの定価を払います。エージェント駆動のPR量では込みの枠は数日で蒸発するため、効いてくるのは限界的な1分の値段です — そして、より速いマシンでおよそ半額というBlacksmithのLinux分単価が、その比較に完勝します。このガイドのプライベートリポジトリのCIがBlacksmithで走っているのはそれが理由であり、このページの残りがBlacksmithに対して書かれているのも同じ理由です。

可視性が先、プロバイダーが次、サイジングは最後。以下のセクションが意味を持つのは、この問いがあなたを従量課金のランナーの上に置いたときだけです。

Blacksmithを1分で

Blacksmithのランナーは、GitHubホスト型ランナーのドロップイン置き換えです。runs-on を変えるだけで、他は何も変わりません。価値の要点は、より高速なマシンをより低い分単価で、GitHubの「込みの分数」モデルではなく従量課金で使える、という点にあります。

ランナーのラベル

ラベルは形状を直接エンコードしているので、ジョブのサイジングはトークン1つ分の編集で済みます。

jobs:
  test:
    runs-on: blacksmith-4vcpu-ubuntu-2204
vCPU2vcpu4vcpu8vcpu16vcpu32vcpu
OSイメージubuntu-2204(安全な既定値)、ubuntu-2404
アーキテクチャx64(既定)、arm64には -arm サフィックス

つまり blacksmith-8vcpu-ubuntu-2404-arm は、Ubuntu 24.04上の8 vCPU arm64ランナーです。既定のイメージには ubuntu-2204 を選ぶのが無難です — GitHubの長年の ubuntu-latest の挙動に最も近いため、ワークフローを移行してもツールチェーンのバージョン差でつまずくことがめったにありません。ubuntu-2404 へは、ジョブが実際に新しいベースを必要とするときに、意図的に移りましょう。

料金と無料枠

  • 月3,000分の無料枠。x64の2 vCPU相当分で計上されます。より大きい形状、arm、Windows、macOSの形状は、同じ予算をそれぞれの倍率で消費します(arm 2 vCPU分はx64より安く、Windows分は高く、macOS分ははるかに高い — 後述)。

  • **x64 2 vCPUランナーで約 0.004/分** — 標準的な2コアLinuxランナーに対するGitHubホスト型の定価 0.008/分の、およそ半分です。Blacksmith自身の料金ページは、分単価と速度を組み合わせた優位性を「総コストでおよそ3分の2の削減」と表現しています。マシンが同じジョブをより速く走らせるためです。

  • 料金はvCPU数にほぼ線形にスケールします。 料金ページは2 vCPUのベースについて正確な数値を公開しており、そこから4 vCPUランナーは2 vCPUレートのおよそ2倍(約 0.008/分)、8 vCPUはおよそ4倍(約 0.016/分)……と課金されます。この線形性が、後述のルール1を支える要の事実です — 覚えておいてください。

透過的な依存キャッシュ — そして、それを省くべきとき

Blacksmithは、標準的なキャッシュアクション(actions/cache や普及しているエコシステムのラッパー)が高スループットで透過的に利用するキャッシュをコロケーション(同一拠点配置)しています。恩恵を受けるのに特別な設定は要りません。

直感に反するのは、明示的なキャッシュをまったく追加しないほうがよいことが多い、という点です。

Warning

Blacksmithのインストール速度では、actions/cache の保存/復元ステップを追加することは、しばしば差し引きで損になります。 x64 2 vCPUランナー上で、pnpm install --frozen-lockfile はワークフローにキャッシュステップを一切置かずに約2秒で完了することが観測されています。保存/復元の往復 — キーのハッシュ化、tarballのアップロード、tarballのダウンロード、展開 — は、それが省こうとしていたインストールよりも、実測時間でもYAMLの記述量でも、日常的に高くつきます。

これは、より遅いランナーから持ち込まれる、あらゆるCIエンジニアが身につけている反射 — 「依存はキャッシュせよ」という無条件の助言 — に反します。ここではそれは条件付きです。まずキャッシュなしのインストールを計測してください。 すでに2〜3秒なら、キャッシュは純粋なオーバーヘッドです。明示的なキャッシュは、本当に高コストなアーティファクト — コンパイル済みのRustのターゲットディレクトリ、Playwrightのブラウザダウンロード — にだけ手を伸ばし、高速なパッケージインストールには使わないでください。

macOS(Apple Silicon)ランナー

macOSは別次元のコストであり、その違いの形が、あなたがそれをどう使ってよいかを決めます。

  • 最小のmacOS形状は6 vCPUです。 小さくて安価なMacランナーは存在しません — 入口の価格が6 vCPUマシン(blacksmith-6vcpu-macos-latest や、blacksmith-6vcpu-macos-15 のようなピン留めバリアント)であり、その上に12 vCPUの選択肢があります。

  • 課金はx64 2 vCPU分のおよそ20倍です。 6 vCPUのmacOS分は約 **0.08/分** — x64の約 0.004/分レートの20倍です。設計で織り込むべきなのは、絶対額ではなくこの倍率です。

その帰結は、好みではなく、動かしがたいアーキテクチャ上のルールです。

Danger

Macレーンは schedule:workflow_dispatch: のジョブとしてなら成立します — エージェント駆動のPR量で、PRごとに走らせることは決してありません。 20倍の倍率は、すべてのプルリクエストで走らせた瞬間に、ありふれたMacジョブを4桁ドルの月次コスト項目に変えてしまいます。

具体例:夜間の45分Mac試験は 45 × $0.08 ≈ $3.6/晩 ≈ 約 $110/ のコストです — 上限があり予測可能です。同じジョブを、月約400回のCI実行でPRごとに走らせるよう配線すると、400 × 45 × $0.08 ≈ 約 $1,400/ になります。同じ作業が、トリガーだけの違いで一桁分かけ離れるのです。

その計算には、隠れた好機があります。予測可能な約 $110/月 という数字こそ、Metal/WebGLのカバレッジが現在は開発者のローカルMacでしか走らないプロジェクトにとって、スケジュール型の実GPU重量レーンを現実的にするものです。これはまさに、重いテストの判断ルールの「環境的に実行不能」「プラットフォーム的に実行不能」のケースです。実GPUや実macOSを必要とするテストは、対応可能なハードウェア上のスケジュール型T3ティアへ移ります。ホスト型のApple Siliconランナーは、そのティアを「誰かがリリース前にローカルで走らせてくれることを祈る」ではなく、上限のある月次コストにするものです。スケジュール型のmacOSジョブそのものの配線については、定期再試験 & 夜間試験を参照してください。

ランナーサイジングの4つのルール

ラベルと料金は簡単な部分です。難しいのは、大きい/別のランナーが正しい道具となるのはいつかを見極めることです — なぜなら「とにかくコアを増やせばいい」という直感は、およそ半分は正しく、残り半分は積極的に間違っているからです。この4つのルールが、このページの核心となる知恵です。

既定値:動作する最小の形状

4つのルールが働き始める前に、まず既定値を守ってください。すべてのレーンは、確実に完走する最小・最安の形状で走らせる — 以下のどれかが理由を名指しするまでは 2vcpu です。

その根拠は、CIのレイテンシが実際に誰の時間を消費しているのかという、AI開発時代の観察です。実装がエージェント駆動なら、遅いレーンの実測時間はエージェントのターンとターンの合間に落ち、人間が画面の前で待つ時間には落ちません — エージェントは人間がレビューするより速く成果を生み出すので、PRゲートが数分余計にかかっても、人間のレビューの歩調の内側に余裕で収まります。誰も待っていないレイテンシに、金を払う価値はありません。

だから、大きい・特殊なランナーには、雰囲気ではなく明示的に名指しされた理由が必要です。正当な理由の例:チームが本当に座って待つプレビューデプロイ、OS固有のビルド環境(macOS、Windows)、ルール2・ルール3で診断された失敗モード。ルール1が教えてくれるのは、大きなランナーを買うと決めたときに何が買えるか、です — 既定は依然として、そのレイテンシに名前の付いた持ち主が現れるまで買わないことです。

ルール1:大きなランナーはコスト削減ではなくレイテンシのレバー

並列化可能なワークロードでは、大きくすることは速度を買うのであって、節約を買うのではありません。

Playwrightのワーカーは既定ではコアにスケールし、そして — 上の料金セクションのとおり — 料金もコアに線形にスケールします。この2つの線形の関係は相殺します。4から8 vCPUへ倍にすれば、実測時間はおよそ半分になる一方、総コストはほぼ据え置きです。分単価は2倍を払いますが、分数がおよそ半分になるからです。この相殺は完全に最初の脚に乗っています — 成り立つのは、ジョブの実効ワーカー数が追加されたコアに実際にスケールしている間だけです。

4vcpu:  ~10 min  ×  ~$0.008/min  ≈  $0.08
8vcpu:  ~5 min   ×  ~$0.016/min  ≈  $0.08   ← half the wait, same bill

したがって、この判断は純粋にフィードバックループの速度についてのものです。より速いPRゲートがエンジニアリングの注意を割く価値があるなら、並列化可能なジョブは大きくしましょう。待ち時間がすでに許容できるなら、小さいままにしておきます。請求額が縮むと期待して大きくしてはいけません — この種の作業では縮みません。

Tip

この相殺が崩れる形は2つあり、直列に見えるのはそのうち1つだけです。本質的に直列な作業 — シングルスレッドのビルドステップ、直列のマイグレーション — は、vCPUを増やしても実測時間の恩恵をまったく得られず、そのジョブにとって大きなランナーは純粋な追加コストです。そして、本質的には並列な作業も、人為的に上限をかけられていることがあります。playwright.config.ts の明示的な workers: N(あるいはCLIの固定数値の --workers=N--workers=50% のようなパーセント指定はコアにスケールし続けます)は並行数をピン留めし、相殺の「ワーカーはコアにスケールする」側の脚を取り除きます。上限をかけられたジョブは直列ではありません — 大きなランナーは、ピン留めされたワーカー数におけるCPU飢餓をなお緩和できます。それはルール3の領分であり、ルール3の天井を持ちます — しかし、このルールが約束する自動的なスケーリングは失われます。競合が消えた点を過ぎれば、コストは上がり続け、実測時間は動かなくなります。「Playwrightだから」は、そのジョブがスケールする証明にはなりません。サイズを上げる前に、設定に workers のピン留めがないか確認してください。

ルール2:大きなランナーはメモリ律速の失敗を修正しない

これは最も高くつく間違いです。なぜなら、大きなマシンは効きそうに見え、しかもしばらくは効いているように見えることがあるからです。

JavaScriptヒープのOOMに当たっているvitest/jsdomレーンは、2から4 vCPUへ移しても修正されませんでした。大きなマシンはヒープの天井を上げますが、それは同じOOMを遅らせるだけです — プロセスは依然として新しい天井まで登りつめて死にます。失敗はメモリの蓄積に律速されており、天井が高くなっても登りの傾きは変わりません。

実際の修正は、シャード間でメモリが回収されるよう、プロセスあたりのファイル数を制限することです。

vitest --shard=1/4

シャーディングは、1つのワーカープロセスが新しいプロセスへロールオーバーするまでに読み込むテストファイルの数に上限をかけ、マシンの総RAMに関わらずピークヒープを天井以下に保ちます。注意として、--shard=1/4 は4つのシャードの最初の1つだけを実行します — CIレーンは4つすべて(1/4 から 4/4 まで、マトリクスか逐次実行で)を走らせなければならず、さもないとスイートの4分の3が黙って未実行になります。このフラグはプロセスあたりのメモリに上限をかけるだけで、それ自体でスイート全体を実行するわけではありません。(証拠:zudo-pattern-gen #1912 — 2→4 vCPUのアップグレードを生き延び、--shard がプロセスあたりのファイル数を制限してはじめてグリーンになったヒープOOMレーン。)周辺のワーカー・タイムアウト予算の設定については、Vitestパターンを参照してください。

Warning

「大きくしたら通った」は、サイズが原因だった証拠にはなりません。 大きなランナーで解消したメモリ律速の失敗は、その日のファイル順序に対するノイズの閾値を下回っただけ、ということがよくあります — スイートが次に成長したときに再浮上します。修正をvCPUに帰する前に、メカニズム(ピークヒープが律速の制約なのか?)を確認してください。

ルール3:サイズを変える前に失敗モードを診断する

ルール2は、大きなランナーがメモリ問題を修正しないと言います — しかしそれは、外から見ればほとんど同じに見える別の問題は、間違いなく修正するのです。

CPU飢餓(starvation): 2 vCPUランナー上では、e2eワーカーとdevサーバーが同じ2コアを奪い合います。競合下では、スペックがタイミング予算を外し、タイムアウトとして失敗します — これは表面上、flakyな、あるいはリソース不足のテストとまったく同じように見えます。ここでは、4 vCPUへ移すことが修正になります。devサーバーとテストワーカーにそれぞれ専用のコアを与えれば、競合が消えるからです。(証拠:zudo-pattern-gen #3321 — 2コア競合下でのスペックタイムアウトが、4 vCPUで解消。)リサイズにあわせてワーカー数を環境変数でチューニングするなら、値は境界で検証してください — NaN に変換されるPlaywrightの workers オーバーライドはゼロ件のテストを実行してgreenで終了します。出発点だったタイムアウトより、偽のgreenの方がたちが悪いのです。

この修正には、ルール1の相殺には無い天井があります。メカニズムは固定されたワーカー数における競合の緩和であって — 並列度の追加ではありません — そしてそれは飽和します。おおよそ、ピン留めされたワーカーとdevサーバーがそれぞれ自分のコアを持った時点で、それ以上のvCPUは何も買いません。workers: 2 がピン留めされた状態で4→8 vCPUへ引き上げると、2つのワーカーと1つのdevサーバーに使い切れない暇なコアを渡すだけです — 実測時間はほぼ据え置き、請求額は2倍。これは、ルール1のピン留めワーカーの罠に反対側から入った姿です。コア数は公式ではなくヒューリスティックとして扱ってください(ブラウザはサブプロセスを生み、OSも取り分を持っていきます)。本当の停止条件は、競合によるタイムアウトが消え、もう1段のサイズアップが実測時間を動かさなくなることです。その点までサイズを上げ、そこで止めてください。

つまり、どちらも「負荷で死ぬテスト」として現れる2つの失敗が、正反対の対処法を持つのです。

flowchart TD A[負荷でテストが失敗] --> B{律速している制約は何か?} B -->|ピークヒープが天井まで登り<br/>そしてOOM| C[メモリ律速<br/>ルール2] B -->|ワーカー+devサーバーが<br/>コアを奪い合う → タイムアウト| D[CPU飢餓<br/>ルール3] B -->|CPUが暇なままネットワークウォーターフォールで<br/>同一オリジンのリクエストがキューに滞留| E[コネクション飢餓<br/>下のNote参照] C --> C1[大きなランナーでは修正されない<br/>修正:vitest --shard] D --> D1[大きなランナーで修正される<br/>2vcpu → 4vcpu] E --> E1[大きなランナーでは修正されない<br/>修正:アプリ/配信レイヤー]

そこから導かれるルール:サイズを変える前に律速の制約を診断し、各ジョブをそれ自身の失敗モードに合わせてサイジングする。 ワークフロー全体を一律にサイジングしてはいけません — 同じワークフロー内のメモリ律速のvitestレーンとCPU飢餓のe2eレーンは、それぞれ異なる扱いを望んでおり、「すべて8vcpuに」という一括対応は、メモリのバグを覆い隠しつつ、それを必要としなかったジョブに払い過ぎることになります。

Note

まったく同じ症状を見せながら、どちらのレバーにも応えない第3の失敗モードがあります:コネクション飢餓 — 開発サーバーのモジュールストームがブラウザのホストごとコネクションプール(HTTP/1.1のケースでホストあたり6本)を使い果たし、CPUが暇なまま待機がタイムアウトするケースです。CPUが暇というだけでこのブランチに進んではいけません(リモートI/O、ブロックされたロック、ハングした依存も同じに見えます) — ネットワークウォーターフォールの証拠、すなわち同一オリジンのリクエストがキューで停滞している様子を必須としてください。プールはvCPUを増やしても増えません。修正はアプリ/配信レイヤーにあります。フレイク根本原因カタログのエントリ6を参照してください。

ルール4:コスト管理はランナー選びではなく、トリガー設計から生まれる

CIの請求額に対する最大のレバーは、どのランナーを選ぶかではありません — 高コストなレーンをそもそもいつ走らせるかです。

8 vCPUランナー上の重量レーンをすべてのトピックPRで発火させれば、同じレーンをスケジュールで走らせるよりもはるかに高くつき、その差の前ではランナーのサイズは端数の誤差です。上のmacOSの試算はその極端なケース — 分あたり20倍が、トリガーをすべての物語にします — ですが、この原則はどんな高コストなレーンにも当てはまります。

高コストなレーンは、次の2つでゲートしましょう。

  1. PRのベースブランチ。 重いスイートは、リリース/ラウンドのPR — ベースが main のもの — でだけ走らせ、統合ブランチへ流し込むすべてのトピックブランチPRでは走らせません。エージェント駆動のフローでは大半がトピックPRであり、重量レーンをそこから外すだけでコストの大部分が消えます。このルールが前提とする具体的なブランチトポロジーとCIワークフローについては、リリースラウンド § 重いCIをベースブランチでゲートするを参照してください。

  2. 夜間の schedule: ベースブランチのゲートを、スケジュール型のフル実行でバックアップし、トピックPRをスキップしたものが長く未検証のまま残らないようにします。これは、T3の定期再試験ティアがその役目を果たしている姿です。

レーンを速くするには大きなランナーに手を伸ばし(ルール1)、レーンを安くするにはトリガー設計に手を伸ばす(ルール4)。この2つを混同すること — PRごとの重量レーンをPRごとから完全に外すのではなく、ダウンサイズして節約しようとすること — は、端数の誤差を最適化して請求額を無視することです。

まとめ

症状誤った直感正しいレバー
そもそもCIをどこで走らせるかどのリポジトリにも同じプロバイダーパブリック → 無料の標準GitHubホスト型。プライベート → 限界分単価でBlacksmith(プロバイダー選択が最初)
パブリックリポジトリの標準ランナーが遅く感じる有料プロバイダーや大きなランナーへ移る意図して速度を買うのでない限り無料の標準形状に留まる — 大きなランナーはパブリックでも課金される
PRゲートが遅く感じ、作業は並列化可能放っておく。コアは金がかかるレイテンシのために大きく(ルール1) — 実効並行数がコアにスケールする間はコストほぼ据え置き(まず workers のピン留めを確認)。ただし名指しの理由があるときだけ(既定は最小形状)
vitest/jsdomのヒープOOMRAMを増やすため2→4 vCPUvitest --shard(ルール2) — サイズでは直らない
e2eスペックが負荷でタイムアウトflakyと決めつけてリトライを足すまず診断:CPU飢餓 → 2→4 vCPU、ただし競合が消えるまで(ルール3)、コネクション飢餓 → アプリ/配信レイヤーで修正(サイズ変更では直らない)
月次CI請求額が高すぎるランナーをダウンサイズベースブランチ+スケジュールでレーンをゲート(ルール4)
実GPU/macOSカバレッジが必要Macランナーで、PRごとに走らせるスケジュール型T3 macOSレーン(約 110/月、約 1,400/月ではなく)

一貫する筋道:ランナーのラベルはトークン2つ分の編集だが、それをうまく選ぶとは、まず律速の制約に名前を付けることを意味する。 レイテンシ、メモリ、CPU競合、総コストは4つの異なる問題であり、4つの異なるレバーを持ちます。そして大きなランナーは、そのうちちょうど2つ — レイテンシ(ルール1)とCPU飢餓(ルール3) — に対する正しい答えであり、どちらの答えも同じ設定ノブ、すなわち実効ワーカー数に縛られているのです。

参考リンク

  • GitHub Actionsの課金について — パブリックリポジトリの標準ランナーは無料というポリシーと、「大きなランナーは常に課金される」という注意点(2026-07-05検証)。

  • Blacksmith ランナー概要 — ラベルの全マトリクス、OSイメージ、無料枠/消費倍率の詳細(2026-07-05検証)。

  • Blacksmith 料金 — 形状ごとの分単価(2026-07-05検証)。

  • 実行ティア — これらのサイジングルールが仕える T0–T4 モデル。

  • 重いテストの判断ルール — 環境/プラットフォーム的に実行不能なテストが、スケジュール型のmacOSティアへどう到達するか。

  • 定期再試験 & 夜間試験 — スケジュール型(T3)のmacOSジョブが実際にどう組まれるか。

Revision History

作成更新