Deploy Rails 5.1 / Webpacker app with Capistrano
The error tells you pretty much what's wrong. Neither Yarn or Node can be found on the server. Your installation might be incorrect.
Follow instructions to install both here:
https://nodejs.org/en/download/package-manager/#debian-and-ubuntu-based-linux-distributions
and here:
https://yarnpkg.com/lang/en/docs/install/#linux-tab
Then make sure you can call:
yarn
node
On the server. If not, you might need to add paths to executables into your PATH variable
I prefer to compile assets locally and then copy to the production servers with rsync:
# lib/capistrano/tasks/precompile.rake
namespace :assets do
desc 'Precompile assets locally and then rsync to web servers'
task :precompile do
run_locally do
with rails_env: stage_of_env do
execute :bundle, 'exec rake assets:precompile'
end
end
on roles(:web), in: :parallel do |server|
run_locally do
execute :rsync,
"-a --delete ./public/packs/ #{fetch(:user)}@#{server.hostname}:#{shared_path}/public/packs/"
execute :rsync,
"-a --delete ./public/assets/ #{fetch(:user)}@#{server.hostname}:#{shared_path}/public/assets/"
end
end
run_locally do
execute :rm, '-rf public/assets'
execute :rm, '-rf public/packs'
end
end
end
# config/deploy.rb
after 'deploy:updated', 'assets:precompile'
In your Capfile you need to include all the capistrano tasks:
# Load custom tasks from `lib/capistrano/tasks` if you have any defined
Dir.glob('lib/capistrano/tasks/**/*.rake').each { |r| import r }
This eliminates the need to install node and yarn on the production servers.
Of course you need node and yarn installed locally
What worked for me was making sure NVM was included in the PATH. By default, in a bash terminal, NVM adds its environment variables to the end of ~/.bashrc
, but much of that file is not usually executed in a non-interactive terminal (which Capistrano runs in). I found this comment helpful:
Put your NVM source script in your .bashrc which is still evaluated even during an non-interactive SSH session. Just make sure you place the declarations at the top, before the case statement:
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm
[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion" # This loads nvm bash_completion
# If not running interactively, don't do anything
case $- in
*i*) ;;
*) return;;
esac