はじめに
こんにちは、プロダクト開発エンジニアの梶山(@h__kajiyama)です。
ライブラリのバージョンアップデートはサービスを提供し続ける上で必要です。しかし、機能開発の速度を求めるあまり疎かになりがちでもあります。そこで、開発速度を維持しつつ、必要なバージョンアップ作業を行う仕組みが大切です。
この記事では私たち開発チームがライブラリアップデートに対してどのように向き合い、開発速度を維持しながらバージョンアップ作業を行っているかを紹介します。
ライブラリアップデートを継続的に行う仕組み
一口にライブラリと言っても、様々な種類があります。私たちのチームは、「主要ライブラリ」「脆弱性対応」「その他のアップデート」の3種類に分けて考えています。具体例を出しながらそれぞれに対してどのようなアプローチをしているのかを説明します。
1. 主要ライブラリ
1つ目は「主要ライブラリ」です。これはRuby, Node.jsなどの言語自体やRails, React, Next.jsなどのフレームワークを指します。影響範囲が広大で、バージョンアップによって破壊的変更や全く新しい機能などが追加されることが多いです。そのため実装の変更やテスト、動作確認にとても時間がかかります。また、影響範囲が広く時間がかかるため、並行して動いている他のPRとコンフリクトを頻繁に起こすリスクが高いです。さらに、依存ライブラリのバージョンアップが必要になり本題に取り組むのが後手後手になることもあるでしょう。
このように大変になることが多い主要ライブラリのアップデートですが、私たちはチームの目標として持ち、計画的かつ高速に進めています。影響箇所、変更必要箇所の調査を行い、アップデート作業のタイムラインを引きます。チーム全員がどの作業をいつ行うかを把握することで、機能開発の空白を限りなく小さくし、作業を分担・協力して行い素早く完了まで持っていけます。
2. 脆弱性対応
2つ目は「脆弱性対応」です。利用しているライブラリに脆弱性があり、そのパッチバージョンが出た場合はすぐにアップデートしなければなりません。
GitHubのDependabot alerts (https://docs.github.com/ja/code-security/dependabot/dependabot-alerts/about-dependabot-alerts) を利用して、脆弱性を含むバージョンを利用しているかどうか検知しています。作成されたPRを確認し、パッチバージョンであるか影響のない変更のみのバージョンアップである場合は動作確認をしてすぐにmerge, releaseを行っています。
対応をする過程で、依存関係があるライブラリも合わせてバージョンアップを行わなければならないことがあります。このようなことが起こらないよう、次に示す「その他のアップデート」が大切です。
3. その他のアップデート
最後に「その他のアップデート」です。基本ですが一番大事なのがアップデート作業を継続することです。Dependabotを利用し、継続しやすい環境を作っています。パッケージ管理ツール毎に最大3件バージョンアップのPRが自動作成されるようにしています。パッチバージョンやChangeLogを見て影響がないPRであれば動作確認をしてどんどんmergeしていきます。メジャーバージョンを含むアップデートの場合は、少し優先度を上げ早めに着手するように意識しています。日々の継続的アップデートでどれだけ新しい状態を維持できるかで1,2のアップデート作業が発生したときのコストが変わります。もちろん全て最新のバージョンにはできませんが、機能開発速度を維持しつつライブラリアップデートも行えるようにしています。
よかったこと
このようにライブラリのバージョンアップデートに取り組んできたことで、以下に示すような様々な良い影響がありました。
新機能の活用とパフォーマンスの向上
主要ライブラリのバージョンを最新に保つことで、新機能の活用や応答速度の向上やメモリ消費量の削減など、サービス全体のパフォーマンスが改善されました。また、Experimentalな機能に対してチームメンバーがより当事者意識を持ち、実際の利用や移行を念頭に置いた開発が行えるようになりました。
脆弱性対応の迅速化
ライブラリアップデートのサイクルを効率的に回すことで、脆弱性対応のリードタイムが大幅に短縮されました。これは、セキュリティリスクの低減に直結します。依存ライブラリのバージョンアップが必要な場合、時間がかかることが多いです。常に少しずつアップデートを行うことで、大規模な作業が必要になることが無くなり、定常業務の中で回せるようになりました。
ライブラリの見直しと最適化
バージョンアップの過程で、現在は使用されていない、または不要であるライブラリを見つけ出すことができます。これにより、実質的なライブラリの見直しを継続的に行い、依存先を減らすことが可能になりました。これによりシステムの複雑性を低減し、メンテナンスの効率を向上させることができています。
今後やりたいこと
今回紹介したバージョンアップの定常運用の仕組みについては、まだ改善点があると考えています。例えば、理想的にはバージョンアップによる影響のないパッチバージョンは自動でアップデートされるようにする、といった運用も考えられますが、”影響がないこと”をどのように保証するのか、といった課題はあるため、検討が必要です。また、理想としてはは全てのライブラリのバージョンが最新になっていることが望ましいですが、現時点での目標とはしていません。理由としては、機能開発の速度も重視し、その中で継続的にアップデートを行うことが重要であり、”常にライブラリを最新バージョンにすること”が目的ではないからです。
最後に
ライブラリアップデートの話をここまでしてきましたが、我々開発チームはユーザーに価値あるサービスを最速でお届けするために日々努力しています。開発速度やサービスの質を維持する一環としてライブラリアップデートや負債解消を継続的に行うことを大事にしています。ユーザーファーストでありながら、技術に真摯に向き合うチームに魅力を感じられましたらぜひお話させてください。