🚞

新卒だけどいきなりRailsを6系から7系にメジャーバージョンアップしてみた話

2024/10/08に公開

はじめまして!24卒でハコベル株式会社のサーバーサイドエンジニアをしている磯貝です!

ハコベルでは、『ハコベル配車管理』というサービスでRuby on Railsが使われています。
この記事は内定者インターン〜入社後数ヶ月の僕がビビりながらもRuby on Railsのバージョンを6系から7系にアップデートした記録です。
Railsのアップデートに関心がある方や、同じような課題に直面している方の参考になれば幸いです。

大まかな流れ

今回は以下のような流れで行いました。

  1. Railsのパッチバージョンを最新に更新
  2. Railsのload_defaultsを6.1までアップデート
  3. Rails以外のgemを可能な限りアップデート
  4. Railsのメジャーバージョンアップ

それでは順に見ていきます。

1. Railsのパッチバージョンを最新まで上げる

まずはRailsのバージョンを6.1.7から6.1.7.6まで上げました。
これは最初に行う必要はないのですが、以下の3つの理由から先に少しだけRailsをアップデートしました。

  • セキュリティアップデートを早めに適用するため
  • このバージョンアップを先にリリースして、v7リリースの影響範囲を最小限にするため
  • 私がアップデートからリリースまでの流れを把握するため

パッチバージョンのアップデート

ということで、Railsをちょこっとアップデートしていきます。
まずは概要を把握するために、公式のリリースノートをチェックします。

https://rubyonrails.org/category/releases

6.1.7から6.1.7.6のリリースノートを見ましたが、更新はセキュリティパッチの更新だけのようです。

コードベースで確認するのであれば、 railsdiff が便利です。
このサイトではrails newしたときのファイルの差分を確認することができます。

6.1.7と6.1.7.6の差分を確認してみましたが、問題なさそうですね。

ここまでくれば、あとやることはGemfileのRailsバージョンを固定して、

Gemfile
- gem 'rails', '6.1.7'
+ gem 'rails', '6.1.7.6'

このコマンドを実行するだけです。

bundle update --conservative rails

--conservativeオプションは、他のgemのアップデートを抑制できます。)

https://bundler.io/v2.5/man/bundle-update.1.html

これではじめてのRailsアップデートが完了しました。めでたしめでたし。

2. Railsのload_defaultsを6.1までアップデート

次に、Railsアプリケーションのデフォルト設定を管理する仕組みであるload_defaultsのバージョンを6.1まで上げていきます。

もともとハコベルのRailsアプリケーションはload_defaults 6.0で、しかも6.0の設定値の中でもoverrideしている値が存在するという状況でした。

なるべくload_defaultsを適用させておかないと、新機能の恩恵に与れなかったり、アップデートがしづらかったりするのでここでできるだけ上げておきます。

load_defaults 6.1にするには少なくとも以下のようなステップが必要になります。

  1. load_defaults 6.0の設定値をできるだけ適用する
  2. load_defaults 6.1の中で、可逆的な変更を適用する
  3. アプリケーションが安定した段階で、load_defaults 6.1の不可逆な変更を順次適用する

load_defaultsのアップデートはコードの変更量こそ多くありませんが、リリース手順には注意が必要です。

もしload_defaultsが最新でない場合には、Railsガイドの設定項目を参照して忘れずにアップデートしておきましょう。

https://guides.rubyonrails.org/configuring.html#versioned-default-values

3. Rails以外のgemを可能な限りアップデート

続いて、Railsをアップデートする前に、Rails以外のgemをできるだけアップデートしておきます。
Railsを先にアップデートしてしまうと、その他のgemがRailsに対応していない可能性があるからです。

まずはbundle outdatedコマンドを実行して最新ではないgemの一覧を出力します。
私は先輩を参考にしてこんな感じでNotionに移して、gemがどのバージョンからどのバージョンに上がったのかを一覧で見れるようにしておきました。


bundle outdated の結果をコピペすればこのテーブルが作られる…かと思ったのですが、さすがにうまくいかなかったので GPT を使って Markdown の Table に変換しました。

どのgemをアップデートするかはわかったので、

「よっしゃ上からじゃんじゃんアップデートしていくぜぇ!」

と言いたいところですが、全部で197個あったgemのChangeLogをひとつひとつ見ていては時間がいくらあっても足りません。

そこで、以下の3つに分類してから着手することにしました。

  1. とりあえずまとめてアップデートしてしまうgem
  2. ひとつひとつアップデートするgem
  3. 詳細な影響範囲の調査をしてひとつひとつアップデートするgem

順に見ていきます。

とりあえずまとめてアップデートしてしまうgem

影響範囲が限定的なgemのマイナーアップデートなどを含みます。

バージョンを上げてみてテストが通ればOK、バージョンを上げて問題が起きたときの対処はそのとき考える、という類のgemです。

ただし、例えば10個のgemをまとめてアップデートすると、後でテストが落ちたときなどにどのgemが原因なのかわからなくなるので、影響範囲が被らないように何個か選んでアップデートすることを繰り返しました。(dependabotなどを利用して普段からできるだけgemを最新に保って、そもそもまとめてのアップデートは避けたいところです)

ひとつひとつアップデートするgem

影響範囲が広いgemのマイナーアップデート、development, test環境で利用するgemのメジャーアップデートなどを含みます。

本番影響がないとはいえ、rspecやrubocopのメジャーアップデートなどはそこそこ時間がかかりました。(致し方なく、最後は断腸の思いで.rubocop_todo.ymlに規約違反を無視したいファイルを追加しました)

詳細な影響範囲の調査をしてひとつひとつアップデートするgem

最後に、メジャーアップデートするgemは影響範囲をしっかりと調査してからアップデートしました。

広く使われているgemだと、GitHubなどにアップグレードガイドが存在している場合も多いです。積極的に活用しましょう。
まずはエイヤでバージョンを上げてみて挙動を確認するのもひとつの手です。


本来はすべてのgemのバージョンアップデートについて影響範囲を把握するべきですが、今回のRailsアップデートでは一気に更新を行うことになり、少々手荒な方法を取ってしまったと感じています。

一方で、このRailsアップデートの少し前にdependabotでの管理を始めたり、定期的なgemのアップデートの体制が整いつつあります。

今後は持続可能な開発のために日頃からアップデートを心がけたいです。

4. Railsのメジャーバージョンアップ

ここまできて、やっとこさRailsをアップデートできます。

Gemfileを書き換えて

Gemfile
- gem 'rails', '6.1.7.6'
+ gem 'rails', '7.0.8.1'

bundle installしたら、rails app:updateを実行します。

するとアップデートに必要なファイルの作成と更新を、対話形式で行うことができます。

重要な設定項目が多く含まれるので、load_defaultsの変更と同様に、慎重に行いましょう。

ここからは公式のアップグレードガイドが参考になります。

https://guides.rubyonrails.org/upgrading_ruby_on_rails.html#upgrading-from-rails-6-1-to-rails-7-0

YassLab社の提供している日本語版もあります。

https://railsguides.jp/upgrading_ruby_on_rails.html#rails-6-1からrails-7-0へのアップグレード

動作確認ができればアップデートは完了です。

(実際はここから各アプリケーション固有の問題が出てきたりして大変だったりすると思いますが…)

あと、deprecation warningが出ているものはこのタイミングで解消しておきましょう。

packageのアップデート方法まとめ

一連の作業の中で、Railsをはじめとしてたくさんのgemをアップデートしたので、一般的なpackageのアップデート方法についてまとめておきます。

基本は以下の図のような流れに沿って行いました。

重要なことは、「アップデートがシステムに与える影響」を調査し、そのうえで「アップデートを受け入れるべきか」を判断することです。

今回はRailsを7系にアップデートすることが目的であり、他のgemのアップデートはあくまでRailsのアップデートを阻害する場合においてのみ必須でした。

実際今回のアップデートではいくつかのgemはアップデートを後回しにしました。このあたりの調査や意思決定を経験できたのはとても良い学びになりました。

Railsアップデートに役立つ資料

最後に、アップデートするにあたってたくさんの記事を参考にしたので一覧で載せておきます。

https://scrapbox.io/ruby-jp/Railsアップグレードガイド

https://scrapbox.io/ruby-jp/Rails_7.0_Upgrade_Knowledge

ruby-jpさんがまとめてくださっている、Railsアップデートに関するリンク集です。
私はアップデートが終わりかけのタイミングで存在を知りました(悔しい)。
これを見ておけば間違いなし!

さらに上のリンク集から抜粋します。

https://qiita.com/jnchito/items/0ee47108972a0e302caf

これがあればほとんど困らない、というレベルにまとまっています

https://inside.pixiv.blog/sue445/4751

bundle updateのconservativeオプションの存在はこれで知りました


https://my.diffend.io/

イスラエル発のセキュリティソフトウェア会社であるMend.ioが公開しているサイトで、gemのバージョン間の差分を見ることができます。

gemを検索すると上の方に出てくるrubygems.orgの「差分をレビュー」のリンク先もこれです

リリースノートを見てアップデートしたけどテストが落ちて、「あれ、私なんかやっちゃいました?」ってときにアップデートの変更内容を確認するのに便利です。

Hacobell Developers Blog

Discussion