Macなどのローカル環境ではきちんと動作するしテストもちゃんと通るのに、CI ではなぜかコケるってこと、あると思います。
原因はいくつかあると思いますが、私の場合ディレクトリ名が原因で発生していました。
OS ごとの大文字小文字の扱いの違い
OS (厳密にはファイルシステム)によって、ディレクトリ名やファイル名の取り扱いって結構違います。
使える文字や文字列長の違いもそうですが、大文字小文字の取り扱いも違います。
サーバ OS としてよく利用される Linux ではアルファベットの大文字と小文字を区別します。abc
というディレクトリと ABC
というディレクトリは別物として扱われるので、ひとつのディレクトリ内に同時に存在することが可能です。
対して Windows や Mac では、大文字と小文字を区別しません。abc
というディレクトリと ABC
というディレクトリは同じものとして扱われるので、ひとつのディレクトリ内に同時に存在することができません。ただし表示上は大文字小文字を区別しているので、ABC
という名前で作ったディレクトリはちゃんと大文字で表示されます。
Rails の規約
Rails は設定ファイルを持たない代わりに決まり事が明確に決められているフレームワークです。
今回私がハマった例では app/services
を新しく作り、V3::HogehogeExecuteService
というサービスオブジェクトを実装していました。
このとき、Rails の規約に従ってクラス名はキャメルケース、ディレクトリ名やファイル名はスネークケースで作成する必要があります。
なので app/service/v3/hogehoge_execute_service.rb
がソースファイル名になります。
しかしうっかりディレクトリ名を大文字にしちゃったんですね。app/service/V3/hogehoge_execute_service.rb
で作っちゃったんです。
V って大文字でも小文字でも形が同じなので、間違えていることに長いこと気づきませんでした。
このサービスは、コントローラでこんな感じで呼ばれます。
hogehoge = V3::HogehogeExecuteService.new(user_id)
このとき、Rails は app/service/v3/hogehoge_execute_service.rb
を探しに行く訳ですが、Win/Mac のように大文字小文字を区別しない OS だと、 app/service/V3/hogehoge_execute_service.rb
を見つけることができます。でも、Linux のように大文字小文字を区別しない OS だと、そんなファイルねーよって例外に繋がる訳です。
CI はたいてい Linux でしょうから、ローカルじゃ通るのに CI だとコケるバグが発生するようになります。本番環境もたいてい Linux でしょうから、CI のお陰でローカルでは見つけられないバグを事前に発見できたことになります。
CircleCI での原因追及
CI がバグを見つけてくれるのはありがたいのですが、この例外、そのままでは CecleCI では表示してくれませんでした。
単純に Rspec の Failure が表示されているだけで、どこでコケているかは分かるけどなんでコケてるかは分からないんですね。
今回のように CI だけでコケるようなバグはなかなか当たりを付けるのも難しいものです。
こんな時はログを見るのが一番。
CircleCI では ssh で接続できるようになっているので、この機能を使ってテスト結果のログを見ると良いです。
こちらのタブを開くと Retry this build with SSH enabled
というボタンが表示されるので、このボタンを押して、SSH 接続可能な状態でもう一度テストを実施します。
テスト実施後ふたたび Debug via SSH タブを開くと SSH 接続するためのコマンドがそのまま表示されているので、コピペしてそのままターミナル上にペースとして実行すると良いです。
詳しくは こちら から。
ssh で入ったら、app_name/log/test.log を vi で開くとログを確認できます。
コケているテストを呼び出しているコントーラ名などで検索してみると、LoadError! ...
って感じでファイルが見つからないことを示すログが記録されていたので、原因を特定することができました。
git でのディレクトリ名の修正
ディレクトリ名の大文字小文字の修正そのものは当然簡単なのですが、Win/Mac だと大文字小文字を区別しないせいか、そのままでは git がディレクトリ名の変更を認識してくれません。
私はこちらの記事のコメントの内容で解決しました。
Gitでファイル名&ディレクトリ名の大文字/小文字を変更方法
git status
の表示結果にディレクトリ名の変更結果が表示されるようになれば成功です。
おそらくディレクトリ名の変更という形ではなく、ディレクトリ配下のファイルの移動という形で表示されると思います。こんな感じで。
app/service/V3/hogehoge_execute_service.rb --> app/service/v3/hogehoge_execute_service.rb
こういう風にきちんと認識してくれたら、あとは commit して push してしまえば良いです。
バグが修正され、CI でもテストが通るようになります。
めでたしめでたし。