「最初からやりすぎない」CI改善活動
はじめに
組織で開発していくときに大事になってくるCI。
最初の方はシンプルでコード量も少ないのでそれほど時間はかかりませんが、対象コードや実施内容が増えてくるとどんどん遅くなっていくことがあります。
弊社も同様で、改善を進めています。
気をつけたのは 「最初からやりすぎない」 こと。
どのように考えて改善していったのか、そのプロセスを書いていきたいと思います。
おことわり
GitHub ActionsやStorybookなど、個別の技術の深堀りしません。
用語について
用語 | 意味 |
---|---|
CI | 継続的インテグレーションの略。GitHubにpushしたら、自動的にビルドやテストを実行してくれる仕組み。 |
VRT | Visual Regression Testの略。ブラウザで表示してスクリーンショットを撮影し、以前のスクリーンショットと比べる仕組み。 |
E2Eテスト | End to Endテストの略。本番環境やそれに似せたシステムに対して、ユーザーの利用環境を模倣してテストする手法。 |
改善結果
20分かかっていたCIが15分まで短縮できました!🎉
5分早くなりましたが、まだ15分もかかっているので、「改善した意味がないのでは?」と言う人もいると思います。
考え方は人それぞれですし、見方によっては正しいとも思います。
これは 「スピードは価値」、つまり 「改善した結果を素早く届け、しっかり価値を出す」 ことを目指した結果です。
以降の解説にて、詳しく書いていきます。
改善プロセス
実際に改善していった流れは以下のとおりです。
- 要求の把握
- 現状の把握
- 仮説を立てる
- 立てた仮説を検証
- 改善案の検討
- 懸念点の洗い出しと検証
- 改善案の適用
- 結果の確認
1. 要求の把握
エンジニアが困っていることは「CIが長い」ということでした。
PRを作るたび、CIのフィードバックを受けるまでの時間は開発が止まってしまいます。
また、revertしたいときも、デプロイするまでに時間がかかっています。
深堀りしたわけではありませんが、今の仕組み上CIが長いために不都合が起こっているのは間違いないため、ここを改善するというのは間違ってなさそうでした。
2. 現状の把握
CIの長さを改善することが決まったので、「どこで」「どのくらいの時間がかかっているのか」の把握をしました。
GitHub Actionsの実行時間を見てみると、およそ20分ほどでした。
内訳としてはおおよそ以下を実施しています。
CIが開始した後に3つに分かれて、
- Linter/Formatter
- 本番ビルド→E2Eテスト&同時にスクリーンショット撮影
- Storybookビルド→Storybookでのスクリーンショット撮影
下2つのスクリーンショット撮影が終わったら、スクリーンショットすべてに対してVRTを実行します。
すべて終了すると、PRがマージできるようになります。
なお、VRTは高い確率で何らかのテストが失敗するため、これが失敗してもCI全体は落とさない(PRはマージできる)ようになっています。
時間がかかっている場所を特定する
GitHub Actionsでは各ジョブがどれくらいの時間で終わったのかが分かります。
確認してみると、一番時間がかかっているのはStorybookでのスクリーンショット撮影の部分でした。
ブラウザを操作してスクリーンショットを撮影するという処理のコストが高く、Storybookのビルドを含めて17分ほどかかっていました。
その後に実行するVRTの実行時間が3分なので合計で20分、CI全体の時間と同じなのでここがクリティカルパスであることが分かりました。
ちなみに二番目に時間がかかっていたのは「本番ビルド→E2Eテスト→VRT」という一連の流れで、合計12分でした。
3. 仮説を立てる
このことから、Storybookでのスクリーンショット撮影を短縮すれば、最大で9分ほど短縮できるはずです。
短縮する方法として思いついたのが、スクリーンショット撮影の並列化です。
以前にそのような機能があると聞いたことがありましたし、時間がかかるものなのだからそういったオプションが存在しているだろうという推測もありました。
4. 立てた仮説を検証
仮説が実現可能かどうか、本当に短縮できるかどうかを調べ、以下のことが分かりました。
- GitHub Actionsではマトリックスという機能を使って、カスタムアクションを並列に実行できる
- Storybookのスクリーンショット撮影に使っている
@storybook/test-runner
にはshard
というオプションがあり、それで簡単に並列化できる
理論上はできそうだと分かったので、これらを使って実際に並列実行を試してみることにしました。
このタイミングでは「本当に実現できるか」を調べたかったので、効率や正確さは度外視しました。
2つに分割して並列実行したところ、実際に実行時間が短縮できることが分かりました。
5. 改善案の検討
これまで並列実行する前提で考えてきましたが、CIを短縮する手段は他にもあるはずです。
比較検討するために3案考えました。
- スクリーンショット撮影を並列化
- VRTの実行タイミングを減らす(特定条件のPR作成時にのみ実行するなど)
- CIではVRTを実施しない(手動で行うなど)
結果的に「スクリーンショット撮影を並列化」にしたのですが、ここでの判断は「改善のポイント」にて。
6. 懸念点の洗い出しと検証
実際に適用するうえでの懸念を考えます。
早くなることは分かっていますが、むやみやたらに並列数を増やしすぎると、逆に無駄なコスト(=課金対象となる時間)がかかってしまいます。
ここでは並列化したときの固定時間(ライブラリのインストールやビルド)と変動時間(テストの実行)を分けて考え、コストと実行時間のバランスが取れる5並列にしました。
7. 改善案の適用
しっかりと調査・検証をしてきたので、実装自体は時間がかからずサクッと終わりました。
やるだけですからね。
8. 結果の確認
実際に適用したCIの実行時間を見てみると、15分!
今回の施策では、約5分(25%)の短縮に成功しました🎉
改善のポイント
ここまでは全体の流れを書いてきましたが、特に重要だと思ったポイントを解説します。
「改善案の検討」で案を決めるときに、「早くなればいい」「ぼくのかんがえたさいきょうのCIにする」とせず、品質担保の面・価値提供スピードの面を検討しました。
- 品質担保の面
- 「実行タイミングを減らす」「CIではVRTを実施しない」では品質担保が不十分になるおそれがある
- 品質担保のクオリティを落としてもいいのか検討できていない
- 価値提供スピードの面
- 上記の品質担保などについて考えるのには時間がかかる
- 理想を追い求めると再現がない
ここで大事にしたいのは、今の課題は「CIが遅い」であって、「自動テストのあり方を決めたい」ではないということです。
課題に寄り添った解決策を、いち早く適用して価値を提供することで、その価値を複利的に高めていけると思っています。
これが自分の「スピードは価値」です。
目の前のことに取り組んでいると忘れがちですが、大事にしていきたいポイントです。
今後について
これまでやってきたことを書きましたが、まだ終わりではありません。
オレたちはようやくのぼりはじめたばかりだからな、このはてしなく遠い改善坂をよ……
改善をしていくなかで(特に「改善案の検討」のタイミングで)、もっと改善できる部分が見えてきました。
引き続き改善を進めていこうと思います!
- 自動テストはしているが、本当に必要な自動テストなのか精査できていない
- テストしたいことがテストできているか分からない
まとめ
- VRTのスクリーンショット撮影を並列化することで、CIの実行時間を短くした
- ユーザーが困っていることにフォーカスして、早く改善できる手段を取った
- 「スピードは価値」
- CIは今後も改善していく予定💪
弊社について
ちょっと宣伝させてください🙏
実は先日転職したのですが。
「改善がやりたーい!」と駄々をこねていたら言っていたら、なんとありがたいことに入社直後から改善をやらせてもらえました!
これは、各々が「プロダクトを良くしていきたい」という気持ちを持って進んでいるからできることだと思っています。
そんな弊社SocialDogは、「あらゆる人がSNSを活用できる世界を創る」をミッションとし、SNSマーケティングのためのオールインワンツールを提供しています。
今回の記事で取り扱った「スピードは価値」という言葉は、SocialDogのバリューの一つ「User Happy」としても掲げられています。
ミッション・バリューは情報ポータルにて公開中です!
エンジニア募集中ですので、興味があればぜひお話ししましょう!
Discussion