虎の穴開発室ブログ

虎の穴ラボ株式会社所属のエンジニアが書く技術ブログです

MENU

Rubyを2.7から3.0にアップデートした話

こんにちは、虎の穴ラボの浜田です。
先日の社内LT会でRubyのアップデートのお話をさせていただきました。
ミドルウェアのアップデートは定期的に行う作業ですのでスライド資料の補足も含めて、ブログにも作業内容を残しておこうと思います。
登壇した勉強会の詳細は以下になりますので、配信を見てみたいという方はぜひ確認してみてください。
yumenosora.connpass.com

1.アップデートの目的

今回のアップデートの目的は「利用バージョンのサポート終了」です。
Ruby2.7を利用したシステムが社内で稼働しており、サポート終了までの期間が短いため、早急にバージョンを上げる必要がありました。

2.事前調査とローカルでの動作確認

アップデートに伴う変更点の調査、修正、そしてローカルでの動作確認を行いました。

公式ページの確認

まずは公式ページのアップデートガイドを参照し、影響を受けそうな部分を把握しました。
https://www.ruby-lang.org/ja/news/2019/12/12/separation-of-positional-and-keyword-arguments-in-ruby-3-0/

今回のアップデートでは、「Ruby 3.0における位置引数とキーワード引数の分離」が主要なトピックとして取り上げられており、特に注意すべき点であることが明らかになりました。

社内の他チームの対応事例を確認

社内でRubyを利用している他のチームが既にアップデートを行っていたため、その対応内容をヒヤリングしました。
公式ページからは得られなかった注意点や対応方法を共有してもらい、アップデート前に確認すべき内容を具体的に理解することができました。

例えば、

  • 修正が必要な箇所を検索するために利用した正規表現パターンの共有
  • 引数の変更だけでなく、Kernel.openがURI.openに変更されているなど、修正が必要な具体的な箇所

といった情報を得ることができました。

RSpecを利用した警告表示の利用

アップデート対象のシステムはユニットテストが整備されており、カバレッジも90%を超えていました。
RSpecに以下のオプションを指定することで、バージョンアップ後に問題となりそうな部分を警告として表示できます。

実際にアップデート対象のシステムでオプションを指定して実行したところ、以下のような警告が表示されました。
それぞれの原因を調査し、修正を行いました。

  • /app/vendor/bundle/ruby/2.7.0/gems/capybara-2.18.0/lib/capybara/rspec/matcher_proxies.rb:14: warning: Capturing the given block using Proc.new is deprecated; use `&block` instead
    →Ruby 3.0に対応したバージョンにアップデートしました。

  • xxxxx_batch.rb:41: warning: Using the last argument as keyword parameters is deprecated; maybe ** should be added to the call
    →ハッシュをキーワード引数に変換しました。

  • yyyyy_batch.rb:8: warning: The called method `process' is defined here
    →継承元メソッド引数をprocess(*args)からprocess(**args)の形式に修正しました。

コンパイル環境の設定

Ruby3.0を導入しようとしたところ、コンパイルに必要なgccが提供されていないことがわかりました。
この問題に対応するために、devtoolset-11を導入しました。

以上の修正を行った後、Rubyのアップデートを行ってもシステムが正常に動作することをローカルで確認しました。

2.テスト環境での確認

ローカルでの動作確認が完了したため、次にテスト環境でアップデートの確認を行います。 今回アップデートを行ったシステムの環境は少し特殊で、テスト環境、ステージング環境、本番環境は「AWSとオンプレミスのハイブリッド」構成となっています。

構成はAnsibleで管理されていますが、サーバー間で異なるOSが利用されているため、インストールするパッケージに若干の違いが生じてしまいました。
その結果、Ansibleの設定が共通で利用できないという問題が発生しました。
この問題に対応するために、Ansibleのwhen構文を利用し、環境ごとにインストールするパッケージを切り替えるようにしました。

- name: Build ruby for None AWS.
  shell: |
    scl enable devtoolset-11 -- ./configure --enable-shared
    scl enable devtoolset-11 -- make
    make install
    chdir={{ workspace | quote}}/ruby-{{ ruby_version | quote}}
    creates=/usr/local/bin/ruby
  when: (ansible_os_family == 'RedHat') and inventory_hostname is not match("aws-*")

ステージング環境での確認

本番に近い環境であるステージング環境も準備されているため、こちらでもアップデートの確認を行ったところ、 gemの依存関係によるエラーが発生しました。

この問題はGemfileのみを更新し、自動更新されたGemfile.lockをコミット対象から外してしまったため、ステージング適用時に必要なGemファイルがインストールされずエラーが発生していました。
ステージングへ適用するファイルはGitHubのリポジトリから取得しているため、依存関係を解消したGemfile.lockファイルをコミット対象に含めることで問題を解決しました。

まとめ

今回はLT会で発表したRubyアップデート時の作業内容を再度紹介しました。 実際に作業を行った中で、特に以下の点が重要だと感じました。

・テストコードは大事!
RSpecの警告表示が大いに役立ちました。 テストコードも適切に整備されていたため、アップデート後でもテストが通ることでシステムに問題がないことを確認できました。

・ローカル環境、テスト環境、ステージング環境と段階的に確認する
ローカル環境、テスト環境、そしてステージング環境において、それぞれ特有の問題を発見し、修正することができました。
本番に近いステージング環境でのアップデート検証により、本番環境での作業を無事に行うことができました。

アップデート作業は今後も避けて通れないタスクとなります。そのためアップデートの作業が少しでもスムーズに進行できるよう、今回の作業内容を活用し続けるつもりです。

採用情報

虎の穴ラボでは一緒に働く仲間を募集中です!
この記事を読んで、興味を持っていただけた方はぜひ弊社の採用情報をご覧ください。
toranoana-lab.co.jp