なぜそれが起こってしまったのかの詳細は分からないけど、忘れないうちに事実だけメモ。改めて情報整理できたら会社のテックブログに展開する。
環境
- Ruby
2.7.6
- Rails
6.1.5
- capistrano
3.7.0
起こったこと
検証用の環境(以後、QA環境と呼ぶ)にて、特定のfeatureブランチをデプロイすると、scssファイルがないよーと怒られる。他のブランチでは起こらない。
could not find file: /home/{app_root}/releases/20221209000001/app/assets/stylesheets/hoge.scss
デプロイにはcapistranoを使用しています。
capistranoのデフォルト仕様で、デプロイするごとに releases/
配下にリポジトリのソースコードをまるっと置きます。上記で言う20221209000001
ディレクトリ内に、とあるデプロイ時のソースが入っています。
そして、最新のrelease
に、{app_root}/current
とのシンボリックリンクが貼られます。
さらに、デプロイ時にcleanup
というタスクが走り、最新の5つを残して他を削除します。
実際のcapistranoログはこんな感じ。
00:12 deploy:cleanup Keeping 5 of 6 deployed releases on {app名} 01 rm -rf /home/{app_root}/releases/20221209000001
とりあえず、ないよーと怒られているreleases
を確認すると、すでにcapistranoのdeploy:cleanup
タスクによって削除されており、存在していないではないか、、!
cd /home/{app_root}/releases/ ls -a → 20221209000004 20221209000005 20221209000006 20221209000007 20221209000008 # 20221209000001は存在しない
(※ releases配下のディレクトリ名は、実際にはタイムスタンプぽい命名になります。分かりやすくデプロイごとにインクリメントするテイにしています。)
すでに存在しないreleasesを参照するとはどういうことだ・・・!?
QA環境以外にも、同じインフラ構成の別の検証環境があるのでそちらにも問題のブランチをデプロイしてみます。別環境では問題なくブラウザからアクセスできる。これで、ソースコード起因ではなく、環境依存であることが確定しました。
キャッシュを疑う
詳しい仕組みは知りませんが、「このブランチではこのreleasesを見に行くよ」みたいなキャッシュが残ってるのかな?という仮説から、home/{app_root}
ディレクトリ内で、存在しないreleaseディレクトリ名20221209000001
の文字列をファイル内に含むファイルを検索かけてみる。
cd home/{app_root} grep 20221209000001 -rl . → ./shared/log/qa.log ./shared/tmp/cache/bootsnap/load-path-cache ./shared/tmp/cache/bootsnap/compile-cache-iseq/xx/xxxxxxxxxxxxxx ./shared/tmp/cache/bootsnap/compile-cache-iseq/xx/xxxxxxxxxxxxxx ./shared/tmp/cache/bootsnap/compile-cache-iseq/xx/xxxxxxxxxxxxxx ./shared/tmp/cache/bootsnap/compile-cache-iseq/xx/xxxxxxxxxxxxxx ./shared/tmp/cache/bootsnap/compile-cache-iseq/xx/xxxxxxxxxxxxxx ./shared/tmp/cache/bootsnap/compile-cache-iseq/xx/xxxxxxxxxxxxxx ./shared/tmp/cache/bootsnap/compile-cache-iseq/xx/xxxxxxxxxxxxxx ./shared/tmp/cache/bootsnap/compile-cache-iseq/xx/xxxxxxxxxxxxxx ./shared/tmp/cache/bootsnap/compile-cache-iseq/xx/xxxxxxxxxxxxxx ./shared/tmp/cache/bootsnap/compile-cache-iseq/xx/xxxxxxxxxxxxxx ./shared/tmp/cache/bootsnap/compile-cache-iseq/xx/xxxxxxxxxxxxxx (他にも ./shared/tmp/cache/bootsnap/compile-cache-iseq 配下のファイルがたくさん。この辺で出力を停止してしまった)
なんかいっぱい出てきた!!!
一番上の ./shared/log/qa.log
はアプリのログなので無視。
それ以降は ./shared/tmp/cache/
という、明らかにキャッシュと思われるディレクトリにいる。
bootsnap
bootsnap とやらを調べてみる。
何やら、キャッシュによってrailsの起動時間を短くしてくれるらしい。よし、とりあえず深くは考えずキャッシュ消しちゃおう!
cd ./shared/tmp/cache/bootsnap/ rm load-path-cache rm -r compile-cache-iseq rm -r compile-cache-yaml
ちなみに、compile-cache-iseq
と compile-cache-yaml
のディレクトリ削除、めっちゃ時間かかりました(体感では5分以上)。
bootsnapのキャッシュを消したので、問題のfeatureブランチのデプロイ再チャレンジ!
could not find file: /home/{app_root}/releases/20221209000001/app/assets/stylesheets/hoge.scss
同じエラー😱😱😱
Sprockets
他にもキャッシュはないかとshared/tmp/cache
ディレクトリ内を探すと、なんかいました。
cd /home/{app_root} ls -a → bootsnap assets
assets 配下には、こんなやつがいました
shared/tmp/cache/assets/sprockets/v3.0
Sprocketsを調べてみる
アセットパイプラインの技術の根幹っぽいことと、キャッシュしていることは分かった。よし、とりあえず深くは考えずキャッシュ消しちゃおう!(2回目)
rm -r shared/tmp/cache/assets/sprockets/v3.0/* #v3.0配下にたくさんキャッシュがある
キャッシュを消したので、再チャレンジ!
、、、いけた!!!!!!
というわけで、今回は Sprocketsのキャッシュを消すことでうまくいきましたとさ。
補足
ちなみに、Sprockets キャッシュ削除後のデプロイでrails起動時、ブラウザでアクセスすると504エラーになりました。15分ほど放置していたら勝手にrails起動して復活。キャッシュの偉大さを身をもって感じました。