はじめに
こんばんは。
今回は、circleCIの実行時間を短縮した備忘録です。
テストコードが多くなると、ciでテストを回すのにかなりの時間がかかります。
ぼくがお仕事を頂いている企業様でも12〜15分(テストのjobは8〜10分)程度の実行時間でした。
ここに課題を感じていたので、ciの並列実行を行い、実行時間の短縮を目指しました。
参考サイト
- https://circleci.com/docs/ja/2.0/parallelism-faster-jobs/
- https://qiita.com/takasp/items/1b14970bdf5633dbbd70
本題
キモとなるのは parallelism
になります。
今回 parallelism
で指定した数分、コンテナが並列で実行されます。
こちらを6に指定して、並列で6台が実行されるように変更しました。
並列で実行されるにあたり、各コンテナで実行されるテストを指定してあげる必要がありました。
それを可能にするのが circleci tests glob
と circleci tests split
になります。
glob
で実行したいテストのパスを取得し、 split
でコンテナ毎に振り分けます。
以下のような感じです。
circleci tests glob "./tests/TestCase/**/*Test.php" | circleci tests split
また、 split
によってコンテナ毎に実行してほしいテストのパスが振り分けられますが、これを phpunitで実行するために、 phpunitのxmlをつくってあげます。
circleci tests glob "./tests/TestCase/**/*Test.php" | circleci tests split | xargs php ./generateXml.php
generateXml.php
<?php $basePath = '/home/circleci/project'; $files = array_slice($argv, 1); $xmlFileStringData = []; foreach ($files as $file) { $xmlFileStringData[] = "<file>{$basePath}/{$file}</file>"; } $testFileString = implode("\n", $xmlFileStringData); $template = <<<XML <?xml version="1.0" encoding="UTF-8"?> <phpunit bootstrap="{$basePath}/tests/bootstrap.php"> <testsuites> <testsuite name="Test Suite"> {$testFileString} </testsuite> </testsuites> </phpunit> XML; file_put_contents("/tmp/ci_phpunit.xml", $template);
generateXml.php
で作成したxmlファイルを指定して、phpunitを実行します
./vendor/bin/phpunit --configuration /tmp/ci_phpunit.xml
これで、コンテナ毎に割り当てられたテストをphpunitが実行してくれます。
実行すると、こんな感じで、コンテナが parallelism
の数分実行してくれます。
つなげて書くと以下みたいな感じです。
- run: name: Execute UnitTest command: | circleci tests glob "./tests/TestCase/**/*Test.php" | circleci tests split | xargs php ./generateXml.php ./vendor/bin/phpunit --configuration /tmp/ci_phpunit.xml - store_artifacts: name: Store Artifact path: logs/cli-error.log
テスト実行時にエラーログを artifactに登録されるようにしているのですが、そちらも複数のコンテナ毎に登録されます。
今回の対応で、実行時間を大体5〜6分に抑えることができました。
また、resource classをデフォルトの mediumからsmallに落とすことで、並列実行しつつ消費クレジットも落とすことができました。
終わりに
結果的には大成功という感じでした。
他にも 歴史のあるレポジトリのため chckoutに1分程度時間がかかっているので、そこを shallow cloneなどを用いてあげれば、更に短縮が見込めそうです。
現場からは以上です。