こちらはエムスリー Advent Calendar 2024 12日目の記事です。
こんにちは。エムスリーエンジニアリンググループ、コンシューマチームの園田です。
今年になって、かなり古い Rails を最新バージョンまでアップグレードしました。そのときの話です。かなりポエムに近い内容になっていますがご容赦ください。
特に何か変わったことをやっているわけではありませんが、あるあるを共感したもらったり、こんなことやってますという紹介だと思っていただければ幸いです。
システムの特性
社員だけが使える管理画面のサービスで、IP 制限と LDAP 認証がかかっています。 利用頻度はそれなりに高く、毎日オペレータが作業しています。また、Rails で実装されたバッチも多数あります。
なぜ古かったか
- 一部の機能で PostgreSQL 8.x を直接参照している処理があり、Rails 5 以上だと
pg
gem のバージョンが対応していませんでした。 - 別のサブシステムのバッチ処理でその PostgreSQL 8.x に書き込みをしていて、アップグレードするにはそちらのバッチの QA が必要ですが、あまりにも古すぎるバッチのため、誰も仕様がわからずアンタッチャブルになっていました。
- サブシステム側のバッチの解析と、それらの QA を行うためのコストが ROI に見合わず、ずっと先送りにされていました。
- 管理画面側の依存処理だけを切り出せばよかったのですが、古いシステムに触りたくない、きっと複雑に違いないという心理作用が強く働いていたためか、誰もそのことに気づきませんでした。
どうやったか
まずは、サブシステム側のバッチには手を触れず、PostgreSQL 8.x に依存している箇所を API に切り出しました。 試しに Node.js の Prisma を使ってみたら PostgreSQL 8.x に対応していたので、API は Node.js で実装しました。
pg
gem さえ最新化できるようになればあとはこっちのもんです。Rails のマイナーバージョンを 1 つずつ上げていきました。
以下はそのときのマージリクエストです。Rails が要求する Ruby のバージョンも上がるため、Ruby のアップグレードも含まれています。
なぜ一気にやったか
他のサービスなどでは 1 つずつバージョンあげて、そのたびに QA を実施して、1 つずつリリースする、という手順を踏むことが多いのですが、今回は一気にあげました。 理由としては、QA するのが大変な定期実行のバッチ処理がたくさん(50 個以上)実装されていたためです。定期バッチは E2E テストに組み込みづらいため、手作業での QA がメインです。 毎バージョンごとに全バッチのフルリグレッション QA を実施していたのではとてもじゃないですが進みません。なので、本システムでは一気にバージョンアップを実施しました。
大変だったこと
実装自体はそこまで大変ではなく、rails app:update
と、ワーニングを潰していくことでほとんどのアップグレード対応ができました。
ただ、ClassLoader が zeitwerk
に変更されたことによる対応はかなり大変でした。とはいえ zeitwerk:check
コマンドなど、移行用のコマンドが用意されているので Rails はそのあたり親切ですね。
全体的に大変だったのは QA です。アップグレード対応の QA のためにバッチの一覧を作成しなおし、Confluence に書いてあった各バッチごとの QA 手順をまとめたりしました。 実際の QA 作業もかなり(2週間くらい?)時間がかかりました。
そして個人的に一番大変だったのは Git の rebase です。実装中や、QA 実施中などでも、日々の開発は進んでいくため、そのたびにメインブランチの変更内容を rebase ないしは merge します。 先ほどのスクショ画像からもわかるとおり、100 を超えるコミットをしている中でメインブランチに変更が入ると、rebase 時のコンフリクト解消がとても大変です。 かつ、作業内容的に全体に影響のある変更が多いので、他の人の修正とがんがんコンフリクトしますw
また私のチーム開発スタイルとして、レビューしやすいようにコミットを意味のある変更の単位で整理しています。
特に rebase で取り込む場合、それを再整理する手間が非常に面倒で、かといってそこをおろそかにするとレビュー品質が下がり、全体品質の低下や事故につながるので、全体における実に 8 割くらいの時間はコミットの整理に費やしていました。
ちなみに本対応中にもっとも多く利用したコマンド。
git checkout --ours Gemfile.lock bundle install git add Gemfile.lock git rebase --continue
やらなくてすんだこと
今回、Rails 5 から 7 ではなく、4 から 7 だったので、比較的大変な webpacker
の shakapacker
移行をやらなくてすみました。
古すぎる Rails を使っていたための予想外の恩恵(?)でした。
アップグレードその後
アップグレードしたことにより最新の gem が使えるようになったり、機能追加などのコストが若干減りました。 例えば、PUSH 通知を配信するバッチのライブラリが古くて使えなくなっていたのが、アップグレード後に 1 人日程度の対応で改修できました。
また、バッチが一覧化されて整理されたのも良かったです。
以上です。小学生の読書感想文みたいな内容にお付き合いいただきありがとうございました。
We are hiring
これを読んでいただいて共感された方もされなかった方も、良かったら一緒に働きませんか。軽く話を聞いてみるだけでも OK ですので、ぜひともカジュアル面談をお申し込みください!