はのちゃ爆発

はのちゃが技術ネタとか日常のこととかを書いてます。

自作 gem に Dependabot を入れたら Unknown Error で更新失敗した話

現象は上述の通り。自作 gem に Dependabot を入れて継続的 Bundle Update 環境を整えようとしたらなんかエラーになった。

TL;DR

  • gemspec 内の required_ruby_versionRuby バージョンが新しすぎると更新でエラーが出る
  • ついでに gemspec に書く required_ruby_version は文字列で指定しておいてもよいかも

エラーの内容

f:id:hano_tea:20200506205019p:plain
管理画面で見るとこんな感じのエラーで原因不明。

上記のように Unknown Error が発生してしまった。

偶発的なものかと思って再実行しても直らなかったのでログを見て原因調査。

エラーログ

以下のようなログが出ていた(一部抜粋)。

(前略)
updater | INFO <job_32200727> Starting job processing
updater | INFO <job_32200727> Starting update job for hanocha/rubocop-google_ads
updater | fatal: not a git repository (or any of the parent directories): .git
updater | fatal: not a git repository (or any of the parent directories): .git
updater | INFO <job_32200727> Checking if rake 13.0.1 needs updating
updater | I, [2020-05-06T11:39:13.485356 #71]  INFO -- sentry: ** [Raven] Sending event 3705176a67f44060aa3b9a424ff6eb82 to Sentry
  proxy | 2020/05/06 11:39:33 POST https://sentry.io:443/api/1425239/store/
  proxy | 2020/05/06 11:39:34 200 https://sentry.io:443/api/1425239/store/
updater | ERROR <job_32200727> Error processing rake (RuntimeError)
updater | ERROR <job_32200727> Couldn't find Ruby version!
updater | ERROR <job_32200727> /home/dependabot/dependabot-updater/vendor/ruby/2.6.0/gems/dependabot-bundler-0.117.7/lib/dependabot/bundler/file_updater/ruby_requirement_setter.rb:56:in `ruby_version'
updater | ERROR <job_32200727> /home/dependabot/dependabot-updater/vendor/ruby/2.6.0/gems/dependabot-bundler-0.117.7/lib/dependabot/bundler/file_updater/ruby_requirement_setter.rb:31:in `rewrite'
updater | ERROR <job_32200727> /home/dependabot/dependabot-updater/vendor/ruby/2.6.0/gems/dependabot-bundler-0.117.7/lib/dependabot/bundler/update_checker/file_preparer.rb:254:in `block in lock_ruby_version'
updater | ERROR <job_32200727> /home/dependabot/dependabot-updater/vendor/ruby/2.6.0/gems/dependabot-bundler-0.117.7/lib/dependabot/bundler/update_checker/file_preparer.rb:252:in `each'
updater | ERROR <job_32200727> /home/dependabot/dependabot-updater/vendor/ruby/2.6.0/gems/dependabot-bundler-0.117.7/lib/dependabot/bundler/update_checker/file_preparer.rb:252:in `lock_ruby_version'
updater | ERROR <job_32200727> /home/dependabot/dependabot-updater/vendor/ruby/2.6.0/gems/dependabot-bundler-0.117.7/lib/dependabot/bundler/update_checker/file_preparer.rb:170:in `gemfile_content_for_update_check'
updater | ERROR <job_32200727> /home/dependabot/dependabot-updater/vendor/ruby/2.6.0/gems/dependabot-bundler-0.117.7/lib/dependabot/bundler/update_checker/file_preparer.rb:61:in `prepared_dependency_files'
updater | ERROR <job_32200727> /home/dependabot/dependabot-updater/vendor/ruby/2.6.0/gems/dependabot-bundler-0.117.7/lib/dependabot/bundler/update_checker.rb:385:in `prepared_dependency_files'
updater | ERROR <job_32200727> /home/dependabot/dependabot-updater/vendor/ruby/2.6.0/gems/dependabot-bundler-0.117.7/lib/dependabot/bundler/update_checker.rb:362:in `latest_version_finder'
updater | ERROR <job_32200727> /home/dependabot/dependabot-updater/vendor/ruby/2.6.0/gems/dependabot-bundler-0.117.7/lib/dependabot/bundler/update_checker.rb:181:in `latest_version_details'
updater | ERROR <job_32200727> /home/dependabot/dependabot-updater/vendor/ruby/2.6.0/gems/dependabot-bundler-0.117.7/lib/dependabot/bundler/update_checker.rb:20:in `latest_version'
updater | ERROR <job_32200727> /home/dependabot/dependabot-updater/lib/dependabot/updater.rb:266:in `log_checking_for_update'
updater | ERROR <job_32200727> /home/dependabot/dependabot-updater/lib/dependabot/updater.rb:163:in `check_and_create_pull_request'
updater | ERROR <job_32200727> /home/dependabot/dependabot-updater/lib/dependabot/updater.rb:64:in `check_and_create_pr_with_error_handling'
updater | ERROR <job_32200727> /home/dependabot/dependabot-updater/lib/dependabot/updater.rb:50:in `block in run'
updater | ERROR <job_32200727> /home/dependabot/dependabot-updater/lib/dependabot/updater.rb:50:in `each'
updater | ERROR <job_32200727> /home/dependabot/dependabot-updater/lib/dependabot/updater.rb:50:in `run'
updater | ERROR <job_32200727> /home/dependabot/dependabot-updater/lib/dependabot/update_files_job.rb:16:in `perform_job'
updater | ERROR <job_32200727> /home/dependabot/dependabot-updater/lib/dependabot/base_job.rb:29:in `run'
updater | ERROR <job_32200727> bin/update_files.rb:21:in `<main>'
(後略)

Couldn't find Ruby version! と言われている。

言われているのだが、 Ruby のバージョンを指定したいタイプのものでもない(普通の Rails アプリとかだったら .ruby-version とか書くけど gem でそういうの書くイメージが無い)のでこの時点で ? となる。

コードを追ってみる

よくわからないのでとりあえずエラー吐いてる Dependabot のコードをちょっと見てみる。

dependabot-bundler-0.117.7/lib/dependabot/bundler/file_updater/ruby_requirement_setter.rb:56:inruby_version'`

スタックトレースの最後が上記なのでここから見てみる。これ

ruby_version 変数がうまく入っていない(多分 nil)のでエラーが出ている模様。

ruby_version 内で呼ばれている ruby_requirement メソッド内の処理も見ないと原因がイマイチ特定できない。こっち

もうちょっと掘れなくもなさそうだが、とりあえず ast = Parser::CurrentRuby.parse(gemspec.content) という記述があり、 gemspec ファイル内の Ruby バージョンに関する記述を読んでいそうな雰囲気。

あれ、 gemspecRuby のバージョン周りのことなんも書いてなかったか…と思ったがそんなことはなく、

spec.required_ruby_version = Gem::Requirement.new('>= 2.6.5')

という行を書いていた。指定しているのに怒られている :thinking:

ふとファイルの上の方の定数を見ると、

        RUBY_VERSIONS =
          %w(1.8.7 1.9.3 2.0.0 2.1.10 2.2.10 2.3.8 2.4.7 2.5.6 2.6.4).freeze

とある。 2.6.4 までしか使えない…?

Ruby のバージョンを下げる

というわけで、 Rubocop 本家の記述に合わせて Ruby のバージョンを落としてみたらいけました。なるほど。

gemspec の書き方を確認してみる

ついでに required_ruby_version の記述も気になったのでちょっと確認。

とはいえこの辺の書き方をなんか自分で色々イジった記憶はないので、ジェネレータで作られたのと同じ記述でやっていただけ…だと思われる。

rubygems.org 内のドキュメントを見てみる。

guides.rubygems.org

Usage には以下のように書いてある。

# This gem will work with 1.8.6 or greater...
spec.required_ruby_version = '>= 1.8.6'

# Only with ruby 2.0.x
spec.required_ruby_version = '~> 2.0'

# Only prereleases or final releases after 2.6.0.preview2
spec.required_ruby_version = '> 2.6.0.preview2'

どうも文字列で指定するのが良さそうだ。 Gem::Requirement.new をする必要はないっぽい。

一応 Cop なので Rubocop 本体の gemspec も見てみたが、そちらも文字列で指定されていた。

今回の件とは直接関係なさそうだけど一応。