CircleCIの実行時間を3分の1に短縮した話

こんにちは、広告運用製品エンジニアの甲斐です。今回はCircleCIの実行時間を短くしたお話をしようと思います。

自動テスト

トーチライトの開発では自動テストにCircleCIを導入しています。Githubのリポジトリへのプッシュをトリガーに、CircleCIで自動テストが走る仕組みとなっています。プルリクエストのレビューはこのテストを全てクリアした状態で行われます。

問題

自動テストが走ってくれるのは嬉しいのですが、時間がかかり過ぎていました。テストの終了を待たないとレビューが始まらないため、開発スピードに影響が出ていました。平均して15分程度、ひどい時は22分かかっていました。。

それが今は8分以内!!!

どのようにこの時短を実現させたかをご紹介します。

時短へのみち

そもそも何が実行されていたのか

以下が実行されている処理の一部です。

  • ブランチチェックアウト
  • bundleインストール
  • yarnインストール
  • save_cache
  • Rspec
  • Reek
  • Rubocop
  • Brakeman
  • vueテスト
  • railsサーバ起動
  • railsサーバへの疎通
  • MySQL起動
  • DBマイグレーション

などなど全部で 37個 の処理が走るようになっていました。

何に時間がかかっていたの?

bundle install

目を引いたのはRailsでは欠かせない bundle installでした。

長い時で4分弱かかっていました。これは長い! その後にsave_cacheが走るので2回目以降のプッシュではキャッシュが利くのですが、初回に bundle installで4分かかるのは痛い。ということで以下のように工夫することにしました。

  • 作業ブランチごとに作っていた bundleのキャッシュをやめる
  • キャッシュは developmentブランチのみで作成する
  • 作業ブランチでは developmentブランチのキャッシュを使用する

上記のようにすることで、developmentブランチとの差分だけがインストール対象になるので初回の処理時間が大幅に短縮できました(^^)

curl http://localhost:3000

railsサーバへの疎通確認をするこのコマンドです。一見そんな時間かからない印象ですが、45秒前後かかっていたのと、これはそもそも必要なのか?という意見があり、 developmentmasterのみで実行するように修正しました。


その他諸々も developmentmasterのみで実行するようにして、最終的に作業ブランチプッシュ時の処理を26個に減らすことができました。

ブランチでの処理の分け方

コマンド

通常、CircleCIの設定ファイルにこのように書くことでコマンドが実行されます。

ここを下記のようにしてブランチ判定を入れてあげます

CircleCIでは $CIRCLE_BRANCHという変数が用意されており、これを使ってブランチの判定を行うことができます。他にも色々な環境変数があるので、試してみてください。

Workflow

Workflow公式

CircleCIの jobそのものを実行するかどうかをブランチで判定するよう workflowを取り入れました。まずは workflowの設定を見てみましょう。

この workflowには3つの jobが設定されています。

  • save_cache
  • test
  • rubycritic

です。 save_cacherubycriticfiltersというのが入っているがわかります。ここでどのブランチでjobを実行するかを判定する設定ができます。 (circleci + rubycriticについてはこちらの記事をご参照ください)

全体的な構成

ここで全体的な構成を書き出してみます。

workflowsのところで「実際に実行するのはこのジョブですよ」というのが見えやすく、またそのジョブもどのような条件で実行するかがわかりやすいと思いました。

感想

自動テストはとても便利です。しかしプロジェクトが進んでいくうちにどんどんテストが増えていき開発スピードに影響するようになると技術負債と同義になります。プロジェクトのソースコードの見直しと同様に、CircleCIで何を実行すべきかを定期的に見直す機会を設けることが大切だなと思いました。また、CircleCIの環境変数について知ることができたので色々を制御する時に使えるなと思いました。

アバター

甲斐貴彦

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

コメントする