Devinを使用してCIのテスト実行時間を62%削減した話

こんにちは!YOUTRUSTでWebエンジニアをしている大竹(YOUTRUST)です。

最近は気温が涼しくなってきて、過ごしやすいですね。しばらくこれくらいの気温が続いてくれると嬉しいです。

本日のテーマ

弊社ではAI開発エージェントのDevinを積極的に本番活用しています。

今回は、Devinを活用してCIのテスト実行時間の削減に成功したので、そのことについてお話しします。

Devinやその他AI活用については、過去に記事を出しているので、そちらを参照ください。

tech.youtrust.co.jp

CIのテスト実行について

弊社では、PRを作成すると、GitHub Actionsで自動的にテストが実行されるようになっており、CIによるチェックが完了することで、mainブランチにPRをマージすることができます。

これまでは問題なかったのですが、テストコードの増加に伴い、テストの実行時間が長くなっていました。これにより、障害発生時のRevertなど、急いで本番反映したいケースで、CIの実行完了までしばらく待たなくてはならない問題が発生していました。

そこで、Devinを活用して、CIのテスト実行時間の削減に取り組みました。

実際のDevinとのやり取り

まず始めに、Devinに以下のような依頼をしました。

GitHub Actionsで実行されるRSpecの実行時間を短縮したいのですが、どういう方法が考えられますか?

Devinの回答は以下です。

GitHub Actionsで実行されるRSpecの実行時間を短縮するための方法をいくつかご紹介します

1 並列実行(Parallelization)

  • matrix戦略を使用: 複数のジョブに分割して並列実行
  • parallel_tests gem: テストを複数のプロセスに分散
  • 例: 25分から10分に短縮した事例あり

2 テストの分割(Test Splitting)

  • 実行時間が長いテストファイルを特定して分割
  • 遅いテストを別々のジョブで実行

3 キャッシュの活用

  • 依存関係(gems)のキャッシュ
  • テストデータのキャッシュ

4 テスト自体の最適化

  • 不要なテストの削除
  • テストの実行順序の最適化
  • データベースのクリーンアップ戦略の見直し

5 CI環境の最適化

  • より高速なランナーの使用
  • メモリ割り当ての最適化

6 テスト実行の条件付け - 変更されたファイルに関連するテストのみ実行

具体的な実装方法や、現在のワークフローについて詳細をお聞かせいただければ、より具体的な提案ができます。

並列実行に関して、parallel_testsはすでに使用していたのですが、matrix戦略はまだ使用していませんでした。そこで、matrix戦略を使用するPR作成を依頼しました。Devinにより作成されたPRの実装内容は以下です(差分以外は...で省略しています)。

jobs:
  rspec:
    name: RSpec
    ...
    strategy:
      fail-fast: false
      matrix:
        # 4つの並列ジョブを設定
        ci_node_total: [4]
        ci_node_index: [0, 1, 2, 3]
    ...
    env:
      ...
      # 並列実行のためのノード情報を設定
      CI_NODE_TOTAL: ${{ matrix.ci_node_total }}
      CI_NODE_INDEX: ${{ matrix.ci_node_index }}
    steps:
      ...
      - name: RSpec
         ...
         run: |
           bundle exec parallel_rspec spec/ -n $CI_NODE_TOTAL --only-group $CI_NODE_INDEX

期待通りstrategymatrixが使用され、4並列でRSpecが実行されるようになりました。

この時点でもかなり実行時間を削減できたのですが、ノード数を調整することでさらに実行時間を削減できる可能性があります。そこで、最適な並列数を見つけるために、続けて以下のような依頼をしました。

並列数を減らしたり増やしたりして、一番実行時間が短くなる並列数を見つけてください

Devinの回答は以下です。(弊社のDevinは特別な訓練を受けているので、たまに語尾がデビになります)

複数の並列数でテストを実行した結果、最適な並列数が見えてきましたデビね!

各ノード数の実行時間

  • 2ノード: 実行中 (9m27s+)
  • 3ノード: 8m18s
  • 4ノード: 8m14s
  • 6ノード: 5m45s
  • 8ノード: 5m7s

分析結果

  • 並列ノード数が増えるほど実行時間が短縮される傾向が明確デビね!
  • 8ノードが最も高速(5m7s)デビね!
  • 6ノードと8ノードの差は比較的小さい(約38秒)
  • 4ノードから6ノードで大きく改善(約2m29s短縮)
  • 2ノードから4ノードまでは大きな差がない

結論 現時点では8ノードが最も効率的ですが、6ノードも十分な性能を発揮していますデビね!リソース効率を考慮すると、6ノードが最適なバランスの可能性がありますデビね!

ノード数を増やすとその分GitHub Actionsの実行コストも増えるため、上記の結果を参考に、ノード数は6を採用しました。元々実行時間は15分程度だったのですが、今回の並列化対応により、実行時間は約5分45秒になりました!(約62%削減)

まとめ

Devinを活用することで、簡単にCIのテスト実行時間の削減ができました。ノード数の調整など、面倒な作業をAIに行ってもらうことで、楽に検証ができました。

最後に

YOUTRUSTではエンジニアを積極的に採用しています!

様々なポジションで求人を出しているので、ご興味のある方は是非以下の募集をご覧ください!

herp.careers