使いたい gem の一部が https://rubygems.org 以外に置かれているとき,Gemfile で 複数のソース を指定することになるよね。(ブルドックソースとオタフクソースとか)
典型的な局面としては,自分用や社内用に開発した gem を自前の gem サーバーに設置しているとき。
で,Gemfile でのソースの指定の仕方によっては Sqale でハマることになるので(実際ハマった),その注意を。
複数ソースの指定の仕方
この節は Sqale に限らない一般論。
以前は,Gemfile に
source 'https://rubygems.org'
source 'https://my_server/gemsource'
gem 'sqlite3'
gem 'my_gem'
みたいに書いてたんだけど,最近の Bundler で bundle install
すると
Warning: this Gemfile contains multiple primary sources. Using `source` more than once without a block is a security risk, and may result in installing unexpected gems. To resolve
this warning, use a block to indicate which gems should come from the secondary source. To upgrade this warning to an error, run `bundle config disable_multisource true`.
と警告が出るようになった。(Bundler 1.8.5 で確認)
要するに,こういう source
の複数併記はよろしくないので,二つ目以降のソース指定はブロック付きにしろ,と。
正しい書き方は
source 'https://rubygems.org'
gem 'sqlite3'
source 'https://myserver/gemsource' do
gem 'my_gem'
end
となる。こう書けば各 gem がどこをソースとするのか明確になる。
あるいは
source 'https://rubygems.org'
gem 'sqlite3'
gem 'my_gem', source: 'https://myserver/gemsource'
と書いてもよいようだ。
Sqale について
Sqale(スケール)は Rails や Sinatra などの Rack ベースのウェブアプリや PHP アプリを簡単に設置(デプロイ)することができるクラウドホスティングサービス。
アプリ開発を Git で管理しているなら,ローカルでコミットしたあと,
git push sqale master
みたいなコマンドで Sqale に push するだけで,デプロイまでやってくれる。このとき,Gemfile に書いた gem のインストールなんかも行われる。
手許で修正したら,また push する。
※初回は SECRET_KEY_BASE の設定などが必要。またデータベースのマイグレーションは Sqale のダッシュボード(管理画面)から行う必要がある。PHP のことは知らん。
いくつか気をつけるところがあるけど,慣れれば超簡単にウェブアプリが公開できて,なかなかいい。
デプロイに失敗
ところが push したあと,「デプロイに失敗しました。」と言われることがある。(ダッシュボードにそう表示される)
デプロイに失敗する原因はいくつかある。とりあえず「デプロイに失敗しました。」の横にある「Log」ボタンでログを見よう。
先日は,Gemfile
に前述の方法
source 'https://myserver/gemsource' do
gem 'my_gem'
end
で指定した自前 gem が認識されなくて,コケた。Gemfile
には書いているのに,インストールされず,当然 Gemfile.lock
にも無い。
Bundler のせい
悩んだ末,どうやら Bundler のバージョンが古いのでは,と思い当たった。
実は,Gemfile
の source
メソッドにブロックを与えたり,gem
メソッドに source
オプションを付けたりできるようになったのは 2014.8.13 にリリースされた Bundler 1.7.0 からなのだ。
それ以前の Bundler だと,source
メソッドのブロックは単純に無視されるので,エラーも出ずにスルーされる。
なんで古い Bundler が?
Sqale に置いた他のアプリは問題なかったのに,どうしてこいつは? もしや Ruby のバージョンが違うのか。
Sqale は rbenv というものを使って Ruby のバージョンを切り替えている。
なので,アプリのルートに .ruby-version
というファイルを置いて,中身に
2.1.4
などと書いておけば,そのディレクトリーは Ruby 2.1.4 で実行される。このファイルは rbenv
コマンドで
rbenv local 2.1.4
と打って作ることもできるし,テキストエディターで書いてもいい。
果たして,Sqale では Ruby のバージョンによって Bundler のバージョンが変わるのか? 結果は次のとおり。コロンの左が Ruby のバージョン,右が Bundler のバージョン。
- 1.9.3-p550: 1.7.4
- 2.0.0-p594: 1.7.4
- 2.1.0: 1.5.1
- 2.1.1: 1.5.3
- 2.1.2: 1.6.2
- 2.1.3: 1.7.3
- 2.1.4: 1.7.4
調べたのは2015年3月16日。全ユーザーがこうなるのかどうかは分らない。
で,問題に遭遇したアプリは Ruby 2.1.2 を指定していたので,1.7.0 未満の Bundler を使っていたのだった。ようやく原因が分った。ふう。
なんで古い Ruby を使ったのかって? 最初に作ったとき,Sqale は Ruby 2.1.2 が最新だったのさ。
※そろそろ Ruby 2.2.0 を入れてくれないかな(ボソッ)。unicode_normalize
とか itself
とか使ってみたい。
追記(2015年3月19日)
Ruby の最新は 2.2.0 じゃなくて 2.2.1 だった。
で,Sqale が 2.1.5, 2.2.0, 2.2.1 に対応してくれました。ありがとう!
※2.2.x に初めて対応するんだから 2.2.0 は要らない(というか入れるべきでない)と思うけど。
感想
Bundler の箱を開けちまった。