Railsをメジャーアップデートするときの基本の「き」

TL;DR

最近は個人でも仕事でもRailsアップデートをやったので、色々ドキュメントをみていたのだけど、その中で自分の中で「こうすればいいんだな」というのが見えてきたので残しておく。

前準備

前準備として最低限以下を行なっておきたい。

  • rspec(テストスイートはなんでもいいがとりあえずテストを充実させておく)
  • rubocop(コードの静的解析)を通しておく
  • breakeman(セキュリティ精査)を実行しておく
  • CIを回す仕組みを作っておく(お金に余裕がない個人ならなくても仕方ない)

特にテストを充実させておくのは最低限やっておきたい。「とりあえずrspecが通れば全ての機能は動いているということにできる」という安心感は割と大きい。

公式のアップグレードガイドを読む

RailsGuideに「AのバージョンからBのバージョンにあげるとき」というものが書いてあるので、一通り目を通しておく。

7になるとzeitwerk対応が必須であるなど、ちゃんと大事なことが書かれているので、まずはここをみてから作業にはいるのがよいと思う。

アップデート対象の最新マイナーバージョンをチェックする

Railsって過去のバージョンも実は対応してくれていて、公式ブログでセキュリティfixのお知らせを流してくれている。

↑は先月でたCVE-2022-32224への対応PRなんだけど、5.2.8系、6.0.5系、6.1.6系も対応してくれていて良心的。(4系は流石におわっている)

つまり今5.2系を使っているなら、次のメジャーバージョンは6.0.5.1、6系を使っているなら6.1.6.1、6.1系を使っているなら7.0.3.1を指定すればいい。僕は雑に7.0.0とか6.1.0とか書いて「あ。あかんやん」って気づいてブランチを切り直すということをした。

公式のリリースノートを読む

RailsはメジャーバージョンごとにRailsGuideにリリースノートを書いてくれている。

リリースノートには「ActiveRecord」「ActionCable」 といった「Active***」「Action***」ごとに「削除されたもの」「非推奨化」「主な変更点」がまとめられている。

7系とかは準備中となってたりして頼りない部分もあるが、6.1から7系にあげるときの必須事項は別にまとめられているのでそちらを一緒に参照するのでいいかと思う。

先行調査ブランチを切る

僕が今関わっているプロジェクトでリードしてくれているエンジニアさんがやっていた手法なのだけど、いきなり本体に手を入れずにまずは「お試しアップデート」をする調査用ブランチをきって、そこで実際にアップデート&影響範囲を調査する、ということをしていた。

僕はこの手法ありだなーと思っていて、数年単位で作られてきたどでかいアプリケーションだといきなり手をいれても前に進まなくなることって往々にあるので、そうではなくてまずは問題点をあぶり出すということをしていくのは大事だと思う。個人アプリ程度だと雑にアップデートしたりもするが。

あと実際のアップデートブランチではないので、色々試せたりするのが大きい。

ここでテストが充実していれば、先行調査をするエンジニアを誰か一人アサインし、その人に調査作業を丸投げできると思うので、テストは大事。

Railsのバージョンを固定する

Gemfileにバージョンを書いてbundle updateする。最初のアップデート時は明確なバージョンを書いておくのがいいんじゃないかと個人的には思う。

gem 'rails', '7.0.3.1'

まあ個人だと雑に7以上とかしてもいいんだけどね。。。

bundleする際はRailsを指定であげると良い。

$ bundle update rails

app:update

Railsは設定ファイルを一式更新するタスクを用意してくれていて、それがapp:update。

実行結果とかは↓の記事に書いているので、良きときに見て欲しいやつ。

ターミナル上で全て上書きした上で、発生した差分とアップデートガイドと該当バージョンの変更点を見比べて、「何が変わったか」「変わったことで発生した挙動の変更」「削除された機能と代替で用意された機能」をあげていく。テストが充実していればここで実行して全部おちたりすると思う。

new_framework_default

Railsのapp:updateをするとconfig/initializers/new_framework_defaults_X.Y.rbというファイルが作成される。ここには各バージョンでデフォルトとなる設定がコメントアウトされた状態で書かれていて、作業をするときはここを一つ一つコメントアウトしながらCIが通過するかどうかを確認しながら進めていくことになる。

中には後方互換性がないものや一度変更すると元に戻せないものもある。5->6にするときのaction_dispatch.use_cookies_with_metadataaction_mailer.delivery_jobなどが代表例だとは思うが、Railsはこういった特に気をつけないとやばいものについては「アップデート後に安定稼働が確認されてから対応してくれよな」と書いてくれているので、その通りにするが吉。

その他調査しなければならないPR

メジャーバージョンのchangelogを注視するのをお勧めしたいかな。リリース上関係がなくても自分のアプリケーションではつかっていたみたいなのがあったりする。

Railsのコードを落としておく

これは先行調査を担当する人にお勧めしたいんだけど、Railsの最新バージョンのコードを手元に落としておくのをお勧めしたい。

Railsのバージョンアップはいきなり5->7とかではなく5->6->6.1->7といったやり方が定石なのだが、中にはnew_framework_defaultに記述されるが別に今有効にしなくてもバージョンアップされるものというのがあったりする。そういった設定はだいたいのちほど非推奨になり、削除される運命にあったりするが、Railsの最新コードでoffにできるかどうかを把握しておくと、「とにかくバージョンアップしたい!」ってなったときはまずは該当設定を変える作業の優先順位をさげるという判断ができる。し、周りのエンジニアや上司も「まあそれなら」と納得感を得やすいだろう。

アップデートとは関係ないが最近僕はActiveRecordとマルチDB、database.yml周りのコードを読んでいた。この辺は後で別途記事にしたい。

おわり

Railsアップデートはなかなか骨が折れる作業だが、きちんと一つ一つ向き合えば本体のサップデートはなんとかなる作業ではある。

各種Gemのアップデートがまた依存関係で苦しむが、それはまた別の話。

おまけ:宣伝

僕はフリーランスで活動しているので、Railsアップデートのお仕事も承ります。

Twitter / Facebook / メールとかで連絡ください。僕のスキルセットや連絡先は以下のページを参照してもらえると。