Deploying Capistrano with Rails 5.1 and Webpacker

Capistrano operates in a shell that is both non-login and non-interactive. This type of shell usage is explained in more detail on http://capistranorb.com/documentation/advanced-features/ptys/. Due to this, the version of Node that Capistrano uses is not the overridden version in your system. To resolve this, you can use Solution 1 which involves compiling assets locally and copying them to the production servers with rsync. This method eliminates the requirement of installing node and yarn on the production servers. To implement Solution 1, you must include all the capistrano tasks in your Capfile.


Solution 1:

My approach is to compile the assets on my local machine and then transfer them to the production servers using 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'

It is necessary to add all the Capistrano tasks to your Capfile.

# Load custom tasks from `lib/capistrano/tasks` if you have any defined
Dir.glob('lib/capistrano/tasks/**/*.rake').each { |r| import r }

This obviates the requirement of installing node and yarn on the servers designated for production.

Naturally, it is necessary to have both node and yarn installed on your local device.


Solution 2:


Ensuring NVM was added to the PATH helped me. NVM usually adds its environment variables to the end of the

~/.bashrc

in a bash terminal by default. However, most of that file is not executed in a non-interactive terminal that Capistrano runs in. I came across a useful comment that aided me.

To ensure that your NVM source script is evaluated even during non-interactive SSH sessions, place the declarations at the top of your .bashrc file, 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


Solution 3:


The error message indicates the absence of Yarn or Node on the server, implying an incorrect installation.

Follow the provided guidelines to install both of them.

Check out the download page for Node.js to find installation instructions for debian and ubuntu based linux distributions.

and here:

Visit the Linux tab on the Yarn Package Manager website to get instructions on how to install Yarn on your Linux system.

Then make sure you can call:

yarn
node

In case the executables are not found on the server, it may be necessary to include their paths in the PATH variable.

Frequently Asked Questions