Bundler の動作が不可解な点について。
再現条件がよく分からないが,一つはっきりしている条件は,Gemfile で指定する gem の中に「rubygems.org 以外のサーバーで提供するもの」が含まれる,という点だ。
以下の例では,my_awesome_gem という自作 gem が https://example.net/gemsource という URL で提供されている,と想定する。
この場合,Gemfile に
source "https://example.net/gemsource" do
gem "my_awesome_gem"
end
と書けばよい。
なお,Ruby バージョン
ruby 3.3.1 (2024-04-23 revision c56cd86388) [arm64-darwin23]
で動作を確認した。
再現実験
まず Gemfile を以下のように書く。
source "https://rubygems.org"
source "https://example.net/gemsource" do
gem "my_awesome_gem"
end
gem "debug"
そして,my_awesome_gem は
gem install my_awesome_gem --source https://example.net/gemsource
でインストールしておき,逆に debug はインストールされていない状態にする1。
この状態で,
bundle check
とすると,debug がインストールされていないので,当然チェックは通らない。
ただ,
Bundler can't satisfy your Gemfile's dependencies.
Install missing gems with `bundle install`.
のようなメッセージになっていて,何の gem が足りないのかが分からない。
Gemfile.lock が存在する場合は,それに照らして
The following gems are missing
* debug (1.9.2)
Install missing gems with `bundle install`
などと教えてくれるが,まだ Gemfile.lock が作られていないので不足 gem についての情報は得られないのだ2。
そこで,この状態で Bundler.require
を強行してみることにする。これで不足 gem が判明するはずだ。
この実験のためにスクリプトを書いてもいいが,以下のようなワンライナーで確認できる。
ruby -r bundler -e "Bundler.require"
これを実行すると「Could not find gem 云々」というエラーメッセージが出るはずだ。
やってみると,
/Users/XXXXX/.rbenv/versions/3.3.1/lib/ruby/site_ruby/3.3.0/bundler/resolver.rb:336:in `raise_not_found!': Could not find gem 'my_awesome_gem' in locally installed gems. (Bundler::GemNotFound)
from /Users/XXXXX/.rbenv/versions/3.3.1/lib/ruby/site_ruby/3.3.0/bundler/resolver.rb:414:in `block in prepare_dependencies'
のようになった。
たいへん奇妙なことに「my_awesome_gem が見つからない」と言っている。
実際には my_awesome_gem はインストールされていて,足りないのは debug なのに!
試しに Gemfile の
source "https://example.net/gemsource" do
gem "my_awesome_gem"
end
の部分をコメントアウトして bundler check
すると,ちゃんと「debug が見つからない」と言ってくる。
つまり,この部分が何か悪さをしているのだ。
それ以上のことは分からなかった。
メモ:自前サーバーで gem を提供する方法
自作 gem を rubygems.org 以外で提供するのはとても簡単。
rubygems-generate_index という gem を使うので,これをあらかじめインストールしておく。
ウェブサーバーを用意し,公開するディレクトリーの下に gems
というディレクトリーを置き,そこに自分で build してできた *.gem
ファイルをためる。
そして,
gem generate_index
とやるだけ3。
これで必要なファイル一式が作られる。gems
ディレクトリーの中身を加除するたびにこのコマンドを実行すればいい。
自前サーバーを使えば,IP アドレス制限を付けて,公開範囲を「自社内」などに制限することができる。
追記 2025-03-23
この記事に記述した再現実験をもう一度やってみた。
今回の環境は以下のとおり:
- ruby 3.4.2 (2025-02-15 revision d2930f8e7a) +PRISM [arm64-darwin24]
- Bundler version 2.6.6
まず,
bundle check
で「何の gem が足りないのかが分からない」問題は解消されていた。
メッセージは
The following gems are missing
* debug (1.10.0)
Install missing gems with `bundle install`
となっており,debug gem が足りないのだと分かるようになった。
たいへんありがたい。
Gemfile にはバージョンを書いていないのに「debug (1.10.0) が足りない」と言ってくるのは,いつ頃からか分からないけど,bundle check
で Gem source を見にいくようになったからだろう(昔の Bundler はそうではなかったはず)。
bundler install
したときにインストールされるはずのバージョンをこのように表示しているのだと思う。
Bundler.require
したとき,無いのは debug gem なのに「my_awesome_gem が見つからない」と言ってくるバグは直っていなかった。残念。