メインコンテンツへスキップ

AI開発

速くするより、
回す場所を選ぶ。

AIエージェント時代のGitHub Actionsを、
9分31秒から2分09秒へ

公開日:2026年8月19日 著者:飯田 友広(Tomohiro Iida)

この記事の結論

  • AIエージェントでcommitとpushの頻度が上がると、CIの実行回数と重複が新しいボトルネックになります。

  • テスト内部の高速化だけでなく、workflow・job・browser・databaseを「今回、本当に起動する必要があるか」から見直します。

  • Draftではrunnerを起動せず、Readyで変更pathをnpm ciより前に分類し、必要な実行基盤だけを起動します。

  • 未知path、CI自己変更、分類不能はfull pathへ倒し、skipした検査をPASS証拠として扱いません。

  • 実PRのdocs-only canaryでは、通常CIを9分31秒から2分09秒へ短縮し、経過時間を77.4%削減しました。

Claude CodeやCodexのようなAIコーディングエージェントを使うと、コードを書く速度は上がります。

その結果、別の場所が詰まり始めます。

私たちの場合、その一つがGitHub Actionsでした。

AIエージェントは、人間より短い間隔でcommitし、pushし、Pull Requestを更新できます。複数のエージェントを並列で動かせば、その頻度はさらに上がります。CIを「人間が一日に数回pushする」前提のままにすると、コード生成より先にrunner時間、待ち時間、検査の重複がボトルネックになります。

Netsujoでは、すでにテストランナーの起動回数削減、lint・typecheckのキャッシュ、独立workflowの統合などを進めていました。それでも利用量が大きい状態が残りました。

原因を調べると、次の問題が残っていました。

  • Draftの作業中commitにもCIが反応する
  • 通常CIとexact-head検証が重い検査を二重実行する
  • docs-only変更でもPostgresを起動する
  • browserを必要としない変更でもChromiumを導入する
  • 変更内容を分類する前にnpm ciが終わっている
  • 「テストを速くする」改善は進んでも、「そのテストを今回走らせる必要があるか」は十分に設計されていない

そこで、CIの考え方を変えました。

**高価な検査は、その証拠が本当に必要になる最も狭いライフサイクルで実行する。**

この記事では、その設計と実測結果を公開します。

結果:9分31秒から2分09秒へ

最初に結果を示します。

変更pathに応じたCIをmainへ反映したあと、docs/**.mdだけを変更する実際のPull Requestでcanaryを行いました。

結果:9分31秒から2分09秒へ
指標Full pathDocs-only canary差分
通常CIの完了時間9分31秒2分09秒7分22秒短縮
経過時間の削減率--77.4%
Postgres起動起動なし省略
Chromium導入skip省略
lint実行skip省略
typecheck実行skip省略
コード全テスト実行skip省略
browser integration実行skip省略
live RLS / tenant isolation実行skip省略

canaryの分類結果は次でした。

text needs_code=false needs_browser=false needs_database=false

ただし、CI全体を飛ばしたわけではありません。

次のような静的検査は継続して実行しています。

  • 公開情報や契約表現の整合
  • workflow safety
  • deploy policy
  • CI coverage
  • Agent運用ルール
  • 静的なRLS coverage
  • その他、Markdown変更でも壊れうる検査

重要なのは、**docs-onlyだから安全だと決め打ちしたのではなく、今回の変更が影響しない実行基盤だけを省略した**ことです。

AIエージェント時代は、CIの前提が変わる

従来のCIは、人間の開発フローを前提に設計されていることが多くあります。

text 人間が実装 ↓ push ↓ CI ↓ 修正 ↓ push ↓ CI

一人のITエンジニアが数時間単位でpushするなら、毎回かなり広い検査をしても、実行回数は限定されます。

AIエージェントでは違います。

```text Planner ├─ Builder A → commit → push ├─ Builder B → commit → push └─ Builder C → commit → push

review修正 ├─ commit → push └─ commit → push ```

実装能力が増えた結果、CIへ流れ込むイベント数も増えます。

ここで「1回のテストを20%速くする」だけでは、十分な改善にならない場合があります。

たとえば、同じSHAに対して二つのworkflowがそれぞれnpm ci、lint、typecheck、全テスト、Chromium導入を実行していれば、内部のテストを高速化しても重複は残ります。

先に見るべきなのは次です。

  1. このworkflowは今、起動する必要があるか
  2. このjobは今、runnerを確保する必要があるか
  3. この変更にPostgresは必要か
  4. この変更にbrowserは必要か
  5. exact-headで必要なのは同一性確認か、full validationか
  6. full validationが証拠として必要になるのはどの段階か

つまり、**テスト速度より先に、ゲートの発火回数と重複を設計する**必要があります。

まずDraftのrunnerを止めた

最初の変更は単純です。

Draft Pull Requestでは、通常CIとexact-headのrunnerを起動しないようにしました。

理由は、Draftが作業中の状態だからです。

作業中のcommitに対してfull CIを実行しても、その結果は最終候補の証拠にはなりません。その後のcommitでSHAが変われば、最終判断には使えません。

従来は次のようになっていました。

text Draft PR ↓ push #1 → CI ↓ push #2 → CI ↓ push #3 → CI ↓ Ready → CI

変更後は次です。

text Draft PR ↓ push #1 → runnerなし ↓ push #2 → runnerなし ↓ push #3 → runnerなし ↓ Ready → CI

もちろん、作業中に検査をしないという意味ではありません。

エージェントはローカルまたは専用環境で、変更範囲に応じたlint、typecheck、関連テストを実行します。GitHub-hosted runnerを、作業途中のすべてのcommitへ自動投入しないという設計です。

Readyへ切り替えた時点では、必ず通常CIを再起動します。

exact-headは「full CIのコピー」ではなくした

もう一つ大きかったのが、exact-head検証です。

通常のPull Request CIは、GitHubが生成するmerge previewを検証することがあります。一方、特定のPR head SHAそのものを確認したい場面もあります。

この目的自体は残す価値があります。

問題は、exact-head workflowで通常CIと同じ重い検査をもう一度走らせていたことです。

text 同じPR head ├─ 通常CI │ ├─ npm ci │ ├─ lint │ ├─ typecheck │ ├─ Chromium │ └─ test │ └─ exact-head CI ├─ npm ci ├─ lint ├─ typecheck ├─ Chromium └─ test

これを分離しました。

Ready PRでは、exact-head側は**SHA同一性の確認**へ限定します。

full exact-SHA validationは、Final Candidateの段階へ移します。

```text Ready PR ├─ integration CI └─ exact-head identity

Final Candidate └─ exact-SHA full gate ```

これにより、同じ変更へ二つのfull suiteを自動投入しません。

変更分類をnpm ciより前へ移す

次の問題は、分類のタイミングでした。

以前もdocs-only変更ではlint、typecheck、全テストをskipできました。しかし、変更分類がCI jobの途中にありました。

つまり、その判定へ到達する前に次が発生していました。

  • runner起動
  • Postgres起動
  • checkout
  • Node setup
  • npm ci

「重い検査をskipできた」のに、重い準備はすでに終わっています。

そこで、依存導入をしない軽量のclassify jobを先頭へ置きました。

text Pull Request ↓ Classify CI execution ├─ needs_code ├─ needs_browser └─ needs_database ↓ 必要な実行基盤だけ起動

分類jobでは、PRの変更pathだけを取得します。

この時点ではnpm ciもPostgresもChromiumも必要ありません。

三つの軸に分けた

分類結果は一つのneeds_codeだけでは足りません。

コード変更であっても、すべての変更がbrowserやdatabaseを必要とするわけではないからです。

そこで三つに分けました。

三つの軸に分けた
出力意味代表的な処理
needs_codeコード検査が必要lint、typecheck、non-browser test
needs_browserbrowser実測が必要Chromium、browser integration
needs_databaselive DBが必要Postgres、RLS、tenant isolation

たとえば、UI変更は次のようになります。

text needs_code=true needs_browser=true needs_database=false

DB migrationやDB検査コードなら、次のような分類ができます。

text needs_code=true needs_browser=false needs_database=true

docs-onlyで、かつテストから参照されていないMarkdownだけなら次です。

text needs_code=false needs_browser=false needs_database=false

この分割により、「コード変更だから全部起動する」という粗い判断を避けられます。

browser testを全テストから分離した

Postgresはservice単位で条件起動できます。

一方、browser testは別の問題がありました。

実ブラウザを使うテストがtest:allの中に混在していると、全テストを実行するためにChromiumが必要になります。

そこで、browserを必要とするテストを登録制で分離しました。

text non-browser aggregate suite browser integration suite

CIでは、通常のコード変更ならnon-browser suiteを実行します。

browserが必要な変更だけ、Chromiumを導入してbrowser suiteを追加します。

ただし、登録制にすると「新しいbrowser testを登録し忘れる」という別の事故が起こりえます。

そのため、テストファイルを逆向きに走査し、Playwrightをimportしているテストとbrowser registryが一致しているかを機械検査しています。

最適化は、検査を減らすことだけでは成立しません。

**省略条件が正しいことを検査する仕組み**まで必要です。

分類器をPR側から実行しない

path-aware CIには、重要な攻撃面があります。

PRが分類器自身を書き換えられる場合です。

たとえば、変更側で次のような分類器を作れば、自分の重い検査を消せます。

text needs_code=false needs_browser=false needs_database=false

CIの最適化ロジックをPR headから実行すると、変更者自身がゲートを弱められます。

そこで、分類器はPR headではなく、**PR base SHA側の信頼済み版**を実行します。

text PR base SHA └─ trusted classifier ↓ changed paths ↓ execution plan

CIや分類器そのものを変更するPull Requestは、自己免除できないようfull pathへ倒します。

UNKNOWNはskipではなくfull pathへ倒す

CI最適化で最も危険なのは、分からない状態を「不要」と判定することです。

私たちは逆にしました。

次の場合は重い検査を省略しません。

  • 未知のpath
  • 変更一覧を取得できない
  • 分類結果が壊れている
  • CI workflow自体の変更
  • 分類器自体の変更
  • test discoveryの変更
  • package.jsonやlockfileの変更
  • Playwright設定の変更

原則は次です。

text SAFEと証明できる → skip可能 分からない → run

この設計は、CIを速くするために安全側のデフォルトを変えないことが目的です。

分類に失敗したらrequired jobをFAILにする

もう一つ見落としやすい点があります。

CIがclassify → validateというjob依存になった場合、classify jobが失敗すると、後続のrequired jobがskippedになることがあります。

branch protectionが見ているcontextとの組み合わせによっては、「分類できなかった」という重要な失敗が、期待した形で表面化しません。

そこでrequired job自体は起動し、最初に分類jobの結果を確認します。

```text classify success → validationへ進む

classify failure → required validation jobを明示FAIL ```

「判定不能だから何も走らなかった」を、合格扱いにしません。

skipはPASSではない

この設計で、技術的な最適化と同じくらい重要だったのが証拠の意味です。

browser suiteをskipしたPRについて、次のように記録してはいけません。

text browser: PASS

実行していないからです。

正しくは次です。

text browser: NOT_RUN reason: changed paths classified as browser-independent

同様に、Postgresを起動しなかったPRについて、DB検査が成功したとは言えません。

CIを効率化すると、「実行しなかったこと」と「成功したこと」を混同しやすくなります。

Final Candidateでは別のfull exact-SHA gateを持ち、必要な証拠を同じSHAへ揃えます。

**実行量の削減と、証拠の強度は別に管理する。**

これが、path-aware CIを安全に運用する条件の一つです。

なぜ単純なpaths-ignoreにしなかったのか

GitHub Actionsにはpath条件があります。

docs-onlyならworkflow自体を起動しない、という構成も考えられます。

しかし、私たちのリポジトリではMarkdown変更でも次を壊す可能性があります。

  • 公開している契約表現
  • 運用ルール
  • Agentへの指示
  • 証拠台帳
  • テストが直接読み込むMarkdown

そのため、docs/**を一律でworkflow対象外にはしませんでした。

静的な整合検査は残し、browser、database、lint、typecheck、コード全テストなど、影響しないと証明できる実行基盤だけを外します。

「ファイル拡張子が.mdだから安全」ではなく、**どの検査面に影響するか**で分類します。

失敗しやすい最適化

今回の実装を通じて、避けるべき形も明確になりました。

1. CI内部だけを高速化し続ける

テストランナーを高速化しても、二つのworkflowで同じsuiteを実行していれば二重化は残ります。

最初にworkflow、job、substrateの発火回数を数えます。

2. Draftでもfull CIを毎回回す

作業中SHAの証拠は、次のpushで古くなります。

ローカル検査とReady時の統合検査を分けます。

3. PR側の分類器を信頼する

分類器を変更するPRが、自分を安全と判定できます。

base側の信頼済み分類ロジックを使い、自己変更はfull pathへ倒します。

4. skipを成功と記録する

省略した検査は成功していません。

EvidenceではNOT_RUNとして扱い、なぜ省略できたかを別に記録します。

5. browser testを分離して登録漏れを放置する

高速化のために新しい手動台帳を作ると、台帳の更新漏れが次の欠陥になります。

実ファイルから逆向きにregistryを検証します。

6. required check名を最適化のたびに変える

branch protectionとの契約が崩れます。

内部構成を変えても、外から見えるrequired contextは安定させます。

AIエージェント開発では、実行予算も設計対象になる

AIエージェントを開発へ入れると、トークン、API、CI、Preview build、テスト環境など、複数の実行資源が自動的に消費されます。

人間が一つずつ操作しているときは、「不要な実行に気づいたらやめる」が成立します。

エージェントが自律的に動く場合は、実行予算自体をコードとpolicyへ落とす必要があります。

私たちはCIについて、次のライフサイクルへ整理しました。

AIエージェント開発では、実行予算も設計対象になる
状態通常CIBrowserDatabaseExact head
Draftrunnerなしなしなしrunnerなし
Ready・docs-only静的検査中心なしなしidentityのみ
Ready・UI変更コード検査あり原則なしidentityのみ
Ready・DB変更コード検査原則なしありidentityのみ
UNKNOWN / CI自己変更full pathありありidentityのみ
Final Candidatefull evidence gate必要必要exact-SHA full

この表を運用者の記憶に置かず、CI policyと回帰テストへ固定しています。

AIエージェントを増やすほど、こうした実行予算の明文化は重要になります。

次のボトルネックはnpm ciと常時静的検査

今回のdocs-only canaryは2分09秒まで短縮しました。

ここまで削ると、残る時間の中でnpm ciと常時実行している静的検査の比率が上がります。

次に考えられるのは次です。

  • dependency不要の検査を別の軽量jobへ寄せる
  • Node dependencyが必要な静的検査だけをまとめる
  • required statusを集約しつつ、内部jobを変更カテゴリで分ける
  • cacheを証拠の正本にはせず、再計算可能な高速化として使う
  • Final Candidateへだけ残すfull gateをさらに明確にする

ただし、最適化は一度で終わりません。

CIの構成を変えたら、次の数週間のrun数、job時間、cancel率、変更カテゴリ別の所要時間を見て、次の支配的コストを確認します。

速いCIより、走らないCIを設計する

今回の改善で変えたのは、テストの品質ではなく、検査を発火させる条件です。

  • DraftではGitHub-hosted runnerを起動しない
  • Readyで変更pathを先に分類する
  • code、browser、databaseを別軸にする
  • exact-headはidentity確認とfull validationを分離する
  • 未知の変更とCI自己変更はfull pathへ倒す
  • 分類失敗をrequired checkのFAILへ変える
  • skipをPASSとして扱わない
  • Final Candidateで必要なexact-SHA証拠を揃える

この結果、docs-onlyの実PRでは、通常CIを9分31秒から2分09秒へ短縮できました。

AIエージェントを増やすなら、先にCIの発火設計を変えるべきです。そうしなければ、増えた開発能力は成果ではなく、runner待ちと請求額に変わります。

これからのCIで最初に問うべきは、**「どう速く走らせるか」ではなく、「この検査は、いま本当に走るべきか」**です。

必要な証拠は、必要な瞬間にだけ完全に揃える。そこまで設計して初めて、AIエージェントの速度は事業の速度になります。

この記事の著者

飯田 友広

飯田 友広

代表取締役

Netsujo株式会社 代表取締役。京都発のWeb3・AI実装スタートアップを2023年6月に創業。Webサイトを営業基盤として捉え、経営・営業・検索・生成AI・コンバージョン・計測を横断して課題と改善優先順位を整理する「Netsujo SIGNAL」を設計・運営。京都ビッグデータ活用プラットフォーム参画(小規模企業会員・ベンチャー)、同プラットフォーム発のワーキンググループ「Chain Up KYOTO」参画(2026-03-10)、IVS2026サイドイベント「なぜ京都でWeb3.0ビジネスなのか」を京都府庁旧議場で開催(2026-07-02・Netsujoとして主催、企画・登壇・運営/京都府デジタル政策推進課は共催)。京都美術工芸大学での講義・龍谷大学でのセミナー実績、ITコミュニティ「みやこでIT」(connpassメンバー614名・イベント167件・2019年2月から運営)運営。NPO法人NEMTUS理事、BAR KRYPTO運営。ソーシャル企業認証「S認証」認証企業(2026年2月認証・2026年4月公表)。技術領域はWeb3/ブロックチェーン/DID/NFT/生成AI/コミュニティ運営。

プロフィールを見る

この記事が向いている方

  • Claude CodeやCodexなどのAIコーディングエージェントでPull Requestとpushの頻度が増えている開発責任者

  • GitHub Actionsの利用量を減らしたいが、required checkや品質ゲートを弱めたくないITエンジニア

  • 複数AIエージェントの開発フローを、トークン・CI・Previewを含む実行予算として設計したい方

— 壁打ち相談

読者のよくある相談

記事を読んだ後に「自分の状況だとどう判断すべきか」を整理するための壁打ち相談を受け付けています。下記のような相談例が当てはまる方は、お気軽にご連絡ください。

Q. AIエージェントを増やしたら、GitHub Actionsの実行回数まで急増した

テスト時間だけでなく、Draft・Ready・Final Candidateごとのworkflow発火回数と重複を先に確認します。

Q. docs-only変更でもPostgresやbrowser testまで毎回走っている

変更pathを依存導入前に分類し、code・browser・databaseを別軸で起動します。

Q. CIを省略すると品質が落ちそうで怖い

SAFEと証明できる範囲だけ省略し、UNKNOWNとCI自己変更はfull pathへ倒します。skipはPASS証拠にしません。

上記いずれかが該当する場合、初回30分の壁打ち相談で論点整理に対応します。記事に書ききれない個別事情を踏まえた判断材料が必要な段階こそ、壁打ちが活きやすいフェーズです。

AI導入・PoC・業務実装のご相談

AIエージェントの速度を、運用コストへ変えない

AIエージェントの役割分担、Git運用、品質ゲート、CI、最終判断者までを一つの運用として設計します。構想段階からのご相談も可能です。

AI導入について相談する