Gemのアップデート方法
エンジニアとして働き始めると、学生時代には意識しない問題に取り組むことが多くなります。
ライブラリのアップデートもその中の一つでしょう。RubyのライブラリであるGemをアップデートする方法を学んだので忘れないうちにアウトプットしようと思います。
なぜ、Gemをアップデートする必要があるのか
なぜライブラリをアップデートし続ける必要があるのでしょうか?その理由は、以下のように様々ですが個人としては、最新バージョンはワクワクしながら仕事ができる
からだと思います。
- インシデントが起こり得るセキュリティエラーへの対応
- 新機能が実装されることで生産性の向上
- Rubyのバージョンを上げる必要がある
Gemをアップデートする前に
いきなりアップデートをしようとすると失敗しやすいので、事前に考えることを紹介します。
Dependabotで可視化
GitHubでDependabotを利用するとGemアップデートのPullRequest(以降、PRと呼ぶ)を自動で作成してくれます。
利用するGemを限定する
誰も利用していないGemを苦労してアップデートしたくはありません。
Gemfileに追加したGemが本当に必要なのかを洗い出します。
開発やテスト環境のみで利用されるGemのうち、チームが使用していないものから手をつけると良いのではないかと思います。
アップデートする時に考えること
Dependabotで可視化されたアップデートで優先度を決めましょう。
優先度は、多くの要因から総合的な判断で決定します。
深刻度
- セキュリテイ
- バグの修正
- 機能改善
依存の深さ
- 依存しているGemが少ないほどアップデートはしやすい
差分量
- メジャー、マイナー、パッチバージョンとバージョンの上がり幅が大きいほど難しい
互換性はあるか
- deprecatedとなっていたメソッドは要注意
優先度が決まったら、工数を見積もります。
見積もりの判断材料は、以下の通りです。
- リポジトリの活発さ
- CHANGELOGの内容
- 差分コード、該当PRの内容
- PRを詳細に書く文化があるか
- アップデートのトリガーとなったPR/issueの内容
- ユーザーベースの多さ・メジャー度(記事があるかどうか)
実際にアップデートをしてみる
pry-docを0.13.4から1.0.0にアップデートする手順を例に説明します。
GitHubと連携しているCircleCIのRSpecが落ちているので確認すると下記のようなエラーが出力されていました。
NoMethodError: undefined method `before_command' for #<Pry::CommandSet:xxxxxxx>
Pry::CommandSetモジュールのbefore_command
メソッドがないようです。
pry-docにbefore_command
があるを確認すると全ての項目で存在しないことがわかりました。
次に、依存Gemを知るためにgemspecを確認します。
ここで、add_development_dependency
はpry-docを開発する際に必要になるGemなのでadd_dependency
が重要です。s.add_dependency 'pry', "~> 0.11"
から、pryというGemが原因のようです。
require './lib/pry-doc/version.rb' Gem::Specification.new do |s| # ... s.required_ruby_version = '>= 2.0' s.add_dependency 'yard', "~> 0.9.11" s.add_dependency 'pry', "~> 0.11" s.add_development_dependency 'latest_ruby', '~> 1.0.0' s.add_development_dependency 'rspec', '~> 3.5' s.add_development_dependency 'rake', "~> 10.0" end
pryをGitHubページでbefore_commandを確認するとCHANGELOG.mdからDelete Pry::CommandSet#{before,after}_command #1838のPRでRemoveされたことがわかりました。
pry-doc
とpry
を同時にアップデートすることが必要そうだとわかりました。
しかし、GitHub上でFiles changedを確認するとpry
のバージョンはpry-doc
と一緒に上がっていることがわかりました。
問題の切り分けを行うために、CircleCIのキャッシュが原因であるかを調べます。
CircleCIのClearing Cacheから、.circleci/config.yml
に記載されているrestore_cacheのkeyオプション
のprefixをv1からv2に変更しPushします。
依然として、エラーが出力されました。
NoMethodError: undefined method `before_command' for #<Pry::CommandSet:xxxxxxx>
次に、pry
に依存している別GemのPRがDependabotにて通知されていたので、該当コミットをgit cherry-pick
で取り込んだ後に、RSpecを走らせるとテストが通ることが確認できました。
アップデート作業は終了です。
まとめ
- Gemのアップデートも普段の業務のようにタスク分解し、PDCAサイクルを回すことで臆せずできる
- ライブラリのアップデートは、ドキュメントを読み込むので勉強になる
- 最新のGemに追従しよう