この記事はユニファアドベントカレンダーの21日目の記事です。
adventar.org
こんにちは、サーバーサイドエンジニアの横山です。
今年は、フォトサービスのRuby/Railsの大幅なバージョンアップを実施しました! Ruby/Railsのバージョンアップは私にとって初めての経験だったので、どのような手順が必要で、どれだけ時間がかかるか未知数でした。
手探りで進めた部分も多かったため、(次回バージョンアップする際の自分のためにも^^;)今回は手順や気をつけるポイントをまとめておきたいと思います。
一昨年〜昨年に同じチームの方が書いた記事も参考にさせていただきました!
- Railsのプロダクションコードを約1万行削除しました - ユニファ開発者ブログ
- チームのKPTで振り返るRailsRubyバージョンアッププロジェクトのはなし - ユニファ開発者ブログ
- Ruby2.7/Rails6.1へのバージョンアップが完了しました - ユニファ開発者ブログ
バージョンアップ概要
最終的に、今回は以下のバージョンまでアップデートしました。
- Ruby: 2.5 → 3.3
- Rails: 5.2 → 7.0
当初は Rails 7.2(すでに Rails 8.0 もリリースされていますね)までアップデートする予定でしたが、ブロッカーがあったため 7.0 までとなっています。 また、変更量が多くなることや他の案件との兼ね合い等から、phase 1, 2 と段階を分けてリリースを実施しています。
バージョンアップ前 | phase 1 | phase 2 | |
---|---|---|---|
ruby | 2.5 | 3.1 | 3.3 |
Rails | 5.2 | 6.1 | 7.0 |
バージョンアップの流れ
ざっくりとした流れは以下になります。
RubyとRailsの各バージョンアップ内容の確認
アップグレードガイドやリリースノートを確認し、RubyRailsのバージョンアップに伴う変更点や新機能、廃止された機能などを確認します。開発環境でのRubyとRailsのバージョンアップ作業
実際の作業にあたる部分ですが、間のバージョンをスキップせずに RubyRailsのバージョンを 1つずつ アップデートして進めます。QA / ロールバックテスト
一通り目的のバージョンまでアップデートできたら、動作確認等のテストを実施します。 さらに旧バージョンへのロールバックを行っても問題がないか確認しておきます。リリース
次はRuby, Rails それぞれの手順になります。(順番は、個人やプロダクトによって異なるかと思います)
Rubyバージョンアップ手順
- 公式のリリースノートの確認
https://www.ruby-lang.org/ja/downloads/releases/ - Rubyバージョンを次のマイナーバージョンの最新パッチバージョンまでアップデート
RuboCop
を使用している場合はRuboCop
の対象Rubyバージョンもアップデート- テストコードや
RuboCop
がパスするかの確認(必要があれば修正) - (Ruby のみアップデートする場合は、Ruby 以外の gem もアップデートして良さそうです。今回は Rails アップデートに含めました。)
Railsバージョンアップ手順
- 公式のアップグレードガイドの確認
https://railsguides.jp/upgrading_ruby_on_rails.html - Railsバージョンを次のマイナーバージョンの最新パッチバージョンまでアップデート
- (ここで
bundle update
を実行し、他のgemを一気にアップデートすることも可能ですが、今回はマイナーバージョン 1つずつ アップデートしました(8. の作業)) rails app:update
を実行。生成されるconfigファイルの確認・修正new_framework_defaults_x_x.rb
の設定の確認・適用 =load_defaults
のバージョンを変更する- DEPRECATION WARNING の対応
- テストコードや
RuboCop
がパスするかの確認(必要があれば修正) - 他の gem のアップデート
気をつけるポイント!
以下はバージョンアップ作業で、リリース後にバグや不具合を起こさないために、地道ながらも手間をかける価値があると思ったポイントになります。
Ruby, Rails 以外の gem のアップデート
マイナーバージョンやパッチバージョンのアップデートのみであれば、bundle update
で一気にアップデートしても問題ないかもしれないですが、
今回はメジャーバージョンを2以上アップデートする gem もあり、各 gem に対して 1~5 の作業を行っていきました。
- CHANGELOG の breaking change がないかを確認する
- Gemfile にバージョン指定のない gem は
bundle update xxx
を実行し、一気にバージョンアップする - Gemfile にバージョン指定のある gem はマイナーバージョンを1つ上げて
bundle update xxx
- テストや DEPRECATION WARNING が発生しないか確認
- 最新まで上げられた場合はバージョン指定を外す、上げられない場合はその時点のバージョン指定を保持(コメント等で最新まで上げられない理由を残しておく)
上記を各 gem に繰り返していく。
バージョンを上げる度にコミットしていたので、合計を数えてみると・・ 100 コミット程でした!地道だった・・!
ただ、バージョンアップを行った時点でエラーが発生したり、Railsのバージョンに対して互換性のないgemが存在したため、1つずつ確認しながら進める必要性を感じました。
config ファイル および new_framework_defaults_x_x.rb
の設定の確認・適用
新しいRailsバージョンに合わせて、configファイルの設定や new_framework_defaults_x_x.rb
(load_defaults)の設定が自動的に生成されます。
設定については、各項目を確認し、デフォルト設定を優先しつつ必要に応じて変更を加える対応を行います。
例えば、デフォルト値から変更が必要な場合として、キャッシュ関連の設定があります。
# デフォルト値 config.active_support.cache_format_version = 7.0 # 変更後 config.active_support.cache_format_version = 6.1
こちらはキャッシュで使用するシリアライズ形式を指定する設定です。
6.1
を指定したキャッシュを 7.0
では読み込めますが、その反対は読み込むことができません。
もしデフォルト値のままに設定してしまうと、Rails のロールバックを行った場合、旧バージョンではキャッシュを正しく読み込むことができず、エラーを引き起こす可能性があります。
そのため、基本的には 6.1
の設定で安定稼働を確認し、その後に新しいデフォルトバージョン(7.0
)に切り替える方法が安全です。
こういった設定を見逃さないためにも、それぞれの変更内容を精査していく必要があります。
また、過去のブログ記事 Ruby2.7/Rails6.1へのバージョンアップが完了しました - ユニファ開発者ブログ でも書いていただいていた通り、config ファイルや new_framework_defaults_x_x.rb
の設定でデフォルト値から変更した場合は、コード内のコメントやcommitに変更内容を残しておくことが重要です。
次回のバージョンアップまでに時間が空いてしまうと、その間に状況や担当者が変わることがあり、「なぜこの設定にしたのかな?」と分かりづらくなってしまうためです。
まとめ
バージョンアップには多くの作業が伴いますが、ポイントをしっかりと押さえることで、重要な変更を見逃さず、後々のバグを防ぐことができます。 今回は手探り状態で時間をかけてしまったところも多かったので、次回以降はもっとサクサク対応していきたいと思います!
ユニファでは、一緒に働く仲間を募集中です!