AIToday

AI生成コードに対応、CI パイプラインの高速化が急務

Hacker News10時間前LINEで送る
AI生成コードに対応、CI パイプラインの高速化が急務

要点

AI がほぼすべての新規コードを生成する現在、フロントエンド CI/CD パイプラインがドラスティックに遅くなっている。理由は、すべてのプルリクエストで全テストとチェックを実行しているからだ。開発者がインポート依存関係を分析して特定のファイル変更に影響を受けたチェックのみを実行する方法を実演したところ、ボタンコンポーネント一つ変更する場合、25 分のフル実行が数秒に短縮された。Google はすでにこの戦略を適用しており、検証を低コスト化しロールアウトを可逆的にすることで、チーム全体がより迅速にコードをマージできることを実証している。

こういう要約が、毎朝あなたのメールに届きます。

無料で登録 →

3つのポイント

  • 何が起きたか

    開発者が、AI がコードとテストを生成することで フロントエンド CI/CD パイプラインが指数関数的に遅くなっていることを指摘し、特定のコード変更に影響を受けたリント、型チェック、テストのみを実行する方法を実演した。全テストスイートを毎回実行する必要がなくなる。

  • なぜ重要か

    AI が大部分の新規コードを生成し、特にテスト生成を優先する現在、全テストとビルドスイートをすべてのプルリクエストで実行する CI パイプラインは、開発者に 25 分以上のフィードバック待機を強いている。Google は検証を低コスト化し、ロールアウトを可逆的にすることで先行事例を示しており、影響を受けたチェックのみを実行すれば、フィードバックループが小さく高速になり、ボトルネックが減少し、開発者は待機キューに並ぶ代わりに迅速に PR をマージできる。

  • 注目点

    このアプローチは変更されたファイルからインポート依存関係を逆方向にたどることで、実行するべきテスト、リントチェック、型チェックを特定する。dependency-cruiser のようなツールでこれを自動化できるが、CI ランナーで適切な git 履歴(fetch-depth: 0)を用意し、ベースブランチとの比較を正確に行う必要がある。

詳細

継続的インテグレーションと継続的デプロイメントはしばしば単一パイプラインに混同されるが、異なる問題に答える。CI は「この変更は正しいか?」をリント、型チェック、ユニットテスト、エンドツーエンドテストで PR マージ前に実行することで答える。CD は「この変更は本番環境で安全か?」と問い、マージ後にデプロイメント、ロールアウト、ロールバックを処理する。本記事は第 1 部に焦点を当てている。フロントエンドプロジェクト向けの高速 CI パイプラインの構築だ。

従来のアプローチはすべてのプルリクエストでテストスイート全体とビルドを実行する。Dashboard、Settings ページ、Billing ページ、共有コンポーネントを備えた典型的なモノレポアプリでは、Button.tsx の 1 行を変更すると、すべてのファイルのリント、プロジェクト全体の型チェック、全 340 ユニットテストの実行、アプリのビルドが トリガーされ――25 分の待機が、あなたの後ろで待機しているすべての開発者にカスケードする。AI が現在ほぼすべてのコードを生成し、テスト生成を優先する現在、この指数関数的遅延は重大になりつつある。

筆者は、インポートグラフから PR に実際に影響を受けるファイルを計算することを提案している。Button.tsx が変更される場合、Button 自体のテストと Button をインポートするファイルのテストのみが実行されるべき。Billing は Button をインポートしないため、触れるべきではない。これには 3 つのステップが必要だ。第一に、git に変更ファイルを問い合わせる(git diff --name-only origin/main...HEAD)。第二に、インポートグラフを逆方向にたどって、変更ファイルを直接的または間接的にインポートするすべてのファイルを見つける。第三に、そのリストをリント、型チェック、テストランナーに、3 つのケース(すべて変更、何も変更されない、または特定リスト)を処理するラッパースクリプト付きで手渡す。

重要な実装詳細として、GitHub Actions パスフィルター(ワークフローを特定フォルダに制限)はスケールしない――すべての機能に新しいワークフローファイルが必要で、すべてのリネームは古い参照を探し回る必要がある。さらに悪いことに、ワークフローが開始されない場合、GitHub のブランチ保護の必須チェックは永遠に待機し、それらのパスに触れないプルリクエストでマージをブロックする。修正は、すべてのプルリクエストですべてのワークフローを実行し、ワークフロー内でジョブを条件付きでスキップすることだ。

このメソッドはラップトップでは機能するが、CI ランナーで失敗する。actions/checkout はデフォルトで fetch-depth: 1 を使用し、1 つのコミットと origin/main との比較先を残す。解決策は fetch-depth: 0 を設定して完全な履歴をダウンロードし、filter: blob:none を設定してチェックアウトしないコミットのファイル内容をスキップすることだ(必要に応じて git が要求時にそれらをフェッチする)。BASE_REF 環境変数もハードコードではなく origin/${{ github.base_ref }} に動的に設定されるべきで、各プルリクエストが相互にターゲットしている場合でも正しく機能する。

これらの変更により、ボタンコンポーネント変更は影響を受けた 4 ファイルのリントと型チェック、および 2 つのテストファイルのテストを数秒で実行する。README 変更はすべての 3 つのジョブを npm 依存関係インストール完了前に終了させる。すべての必須チェックはすべてのプルリクエストでステータスを報告するため、欠落チェックがマージをブロックすることがない。この記事は dependency-cruiser がインポートグラフウォークを自動化できることに注目し、TypeScript をパースし、tsconfig パスを読み、動的インポートをフォローし、手書きスクリプトを 1 つのフラグで置き換える:npx depcruise src --affected origin/main --output-type json。シリーズの第 2 部は CD――可逆的ロールアウト――に取り組む。

背景と解説

この記事が指摘する実際のボトルネックは以下の通りだ。AI がコードを生成し、特にテスト生成を優先する現在、すべてのプルリクエストですべてのチェックを実行する CI パイプラインが指数関数的な遅延を招いている。この問題は、大多数の CI ワークフローの構造によってさらに増幅される。ワークフローはパスフィルター(例えば、src/features/settings/* が変更された場合のみ Settings CI を実行)で トリガーされるが、このアプローチはスケール時に失敗する。理由は、すべての機能に対してワークフローファイルを手動で保守する必要があり、インポート関係を理解せず、トリガーされないワークフローの必須チェックが永遠に「待機」状態に陥るからだ。

筆者の解決策は問題を反転させる。コード検査前にどのパスがどのチェックをトリガーするかを宣言する代わりに、すべてのプルリクエストですべてのワークフローを実行し、各ジョブ内でスクリプトが git diff を分析して変更ファイルを見つけ、インポートグラフを逆方向にたどって、それらの変更に依存する他のファイルを計算する。影響を受けたファイルのみがリント、型チェック、テストされる。単一のボタンコンポーネントが変更された場合、スクリプトはボタンのインポーター 2 つとそれをカバーするテストを特定し、合計 4 ファイル――340 以上のテストスイート全体ではなく――テストする。README が変更された場合、3 つのジョブすべてが npm の依存関係インストール完了前に終了する。

Google はすでに同様の戦略を実装しており、同社の新規コードの大多数は AI 生成で、エンジニアが承認している。この記事は「検証を低コスト化しロールアウトを可逆的にする」というフレーミングを採用しており、これは CI/CD の 2 つの半分にマッピングされる。ここでの低コスト検証(重要なものだけをテスト)と、その後の可逆的ロールアウト(マージされた変更が本番環境で障害を起こした場合、迅速なロールバック)。

よくある質問

コード変更時に実行すべきテストをどのように特定するのか?
変更されたファイルからインポートグラフを逆方向にたどり、直接的または間接的にそれをインポートするすべてのファイルを見つけ、それらのファイルと依存ファイルについてのみリント、型チェック、テストのチェックを実行する。dependency-cruiser のようなツールで git diff 経由でこれを自動化できる。
必須 CI チェックが一部のワークフローで実行されない場合でも、マージをブロックするのはなぜか?
GitHub のブランチ保護では、リストに記載されたすべてのチェックがステータスを報告する必要がある。ワークフローが開始されないと報告がなく、GitHub は沈黙を成功ではなく欠落チェックとして扱う。修正は、すべてのプルリクエストですべてのワークフローを実行し、変更内容に基づいてワークフロー内のジョブを条件付きでスキップすることだ。
CI ランナーに必要な git 設定は何か?
fetch-depth: 0 を設定して完全なコミット履歴をダウンロードし、filter: blob:none を設定してチェックアウトしないコミットのファイル内容をスキップして、ランナーが「未知のリビジョン」で失敗することなく origin/main との比較ができるようにする。

「AIコーディング」の最新ニュースを、毎朝7時にお届けします

AIが要約して、あなたの選んだトピックだけを1日1通。LINE・Email・Slackで届きます。

登録無料・30秒で完了・いつでも解除できます

ディスカッション

まだコメントがありません。最初のコメントを投稿しましょう!

ログインして議論に参加

関連記事

AIニュースを毎日お届け

200以上のソースから厳選したAIニュースを毎日無料でお届けします。

無料で始める

登録無料・30秒で完了・いつでも解除できます