Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cannot deploy an application using Rails 5.1 Webpacker #25

Open
olivierpichon opened this issue Aug 7, 2017 · 24 comments
Open

Cannot deploy an application using Rails 5.1 Webpacker #25

olivierpichon opened this issue Aug 7, 2017 · 24 comments

Comments

@olivierpichon
Copy link

Hi there!

It looks like capistrano-nvm is not playing well with Rails 5.1 Webpacker.

Rails started make ./bin/yarn a dependency for assets:precompile here: rails/rails@b1c08d8

.bin/yarn looks like this:

#!/usr/bin/env ruby
VENDOR_PATH = File.expand_path('..', __dir__)
Dir.chdir(VENDOR_PATH) do
  begin
    exec "yarnpkg #{ARGV.join(" ")}"
  rescue Errno::ENOENT
    $stderr.puts "Yarn executable was not detected in the system."
    $stderr.puts "Download Yarn at https://yarnpkg.com/en/docs/install"
    exit 1
  end
end

As you can see it does a direct system call to yarnpkg which is not found in the PATH. I am not sure what's the best way to go around this as Capistrano is not setting environment variables globally but use SSHKit instead. Any idea?

Thx for your help!

@koenpunt
Copy link
Owner

koenpunt commented Aug 7, 2017

This depends on how you installed yarn. Because if you install it standalone, there should be no problem.
So how did you install yarn?

@olivierpichon
Copy link
Author

After installing node via nvm, I used:
npm install -g yarn

@olivierpichon
Copy link
Author

When I install yarn globally, using https://yarnpkg.com/lang/en/docs/install/#linux-tab, I get a different error:

info Visit https://yarnpkg.com/en/docs/cli/install for documentation about this command.
rake stderr: error extract-text-webpack-plugin@3.0.0: The engine "node" is incompatible with this module. Expected version ">= 4.3 < 5.0.0 || >= 5.10".
error Found incompatible module
/var/www/xxxx/shared/bundle/ruby/2.4.0/bin/rake: No such file or directory - node

SSHKit::Command::Failed: rake exit status: 1
rake stdout: yarn install v0.27.5
[1/4] Resolving packages...
[2/4] Fetching packages...
info Visit https://yarnpkg.com/en/docs/cli/install for documentation about this command.
rake stderr: error extract-text-webpack-plugin@3.0.0: The engine "node" is incompatible with this module. Expected version ">= 4.3 < 5.0.0 || >= 5.10".

Then I imagine I could also install node via ubuntu package, but doesn't this defeat the purpose of using nvm?

Thx a lot!

@koenpunt
Copy link
Owner

koenpunt commented Aug 7, 2017

It seems like you have not the correct version of node installed. The engine "node" is incompatible with this module. Expected version ">= 4.3 < 5.0.0 || >= 5.10".

What's the output of node -v ?

@olivierpichon
Copy link
Author

olivierpichon commented Aug 7, 2017

The node version installed as a "user" install is v6.9.5.
Hence my previous comment: if, to make the deployment works, we need to install yarn globally as a ubuntu package and also install another node version globally (the required node version is the one required by yarn installed as a ubuntu package), then it looks like it defeats the purpose of having nvm and capistrano-nvm

@olivierpichon
Copy link
Author

olivierpichon commented Aug 7, 2017

For people having the same issue, this is the workaround we have been using which is not of course not pretty but which does not require to install yarn or node as a ubuntu system package:

set :default_env, {
  "PATH" => "/home/ubuntu/.nvm/versions/node/v6.9.5/bin:$PATH"
}

@olivierpichon
Copy link
Author

A better way, as suggested here https://stackoverflow.com/questions/39624035/capistrano-and-api-keys-in-env-variables#answer-39628182

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

@arevutsky
Copy link

arevutsky commented Aug 9, 2017

@olivierpichon You are right! We should add these 3 lines before "if not running interactively".

For my ubuntu (Ubuntu 16.04 LTS) it looks like:

~./bashrc

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
[ -z "$PS1" ] && return

My opinion: capistrano-nvm should solve this problem by itself. But it does not happen. I will check how it implemented on capistano-rvm gem. We should have a workable solution.

@arevutsky
Copy link

After my investigation, I understood 1 point: we do not have any problems with this gem, we have a problem with assets precompile. assets:precompile is a rake task, not a cap task.

@arevutsky
Copy link

arevutsky commented Aug 10, 2017

I created new tasks after investigation:

/lib/capistrano/tasks/nvm-webpacker.task

namespace :nvm do
  namespace :webpacker do
    task :validate => [:'nvm:map_bins'] do
      on release_roles(fetch(:nvm_roles)) do
        within release_path do
          if !test('node', '--version')
            warn "node is not installed"
            exit 1
          end

          if !test('yarn', '--version')
            warn "yarn is not installed"
            exit 1
          end
        end
      end
    end

    task :wrap => [:'nvm:map_bins'] do
      on roles(:web) do
        SSHKit.config.command_map.prefix['rake'].unshift(nvm_prefix)
      end
    end

    task :unwrap do
      on roles(:web) do
        SSHKit.config.command_map.prefix['rake'].delete(nvm_prefix)
      end
    end

    def nvm_prefix
      fetch(
        :nvm_prefix, -> {
          "#{fetch(:tmp_dir)}/#{fetch(:application)}/nvm-exec.sh"
        }
      )
    end

    after 'nvm:validate', 'nvm:webpacker:validate'
    before 'deploy:assets:precompile', 'nvm:webpacker:wrap'
    after 'deploy:assets:precompile', 'nvm:webpacker:unwrap'
  end
end
 

Description:
We check that we have node and yarn for assets:precompile task after nvm:validate. Also we prepend nvm script before rvm script.

cd /home/project/application/releases/20170810143247 && ( export NODE_VERSION="v8.2.1" RAILS_ENV="production" RAILS_GROUPS="" ; /tmp/igot/nvm-exec.sh ~/.rvm/bin/rvm ruby-2.3.3@project do bundle exec rake assets:precompile )

@freibuis
Copy link

freibuis commented Oct 3, 2017

this could be fixed by chaning

export NODE_VERSION="v8.2.1" RAILS_ENV="production" RAILS_GROUPS="" ; /tmp/igot/nvm-exec.sh ~/.rvm/bin/rvm ruby-2.3.3@project do bundle exec rake assets:precompile
export NODE_VERSION="v8.2.1" RAILS_ENV="production" RAILS_GROUPS="" ; /tmp/igot/nvm-exec.sh ; nvm use $NODE_VERSION ; ~/.rvm/bin/rvm ruby-2.3.3@project do bundle exec rake assets:precompile

the key is to run nvm use before any version of Yarn that is ran

@bjnord
Copy link

bjnord commented Jan 1, 2019

Thanks @arevutsky that fixed errors I was having with asset precompilation. I also had to add the wrap/unwrap to DB migration, which apparently also needs the JS runtime.

@Eusebius1920
Copy link

Any news on this?

Rails 6 is just around the corner and will make webpacker the default (javascript) asset pipeline, so this error is going to be experienced more and more.

@Eusebius1920
Copy link

Rails 6 is released now and webpacker is the default asset pipeline, can we fix this please?

@wmakley
Copy link

wmakley commented Oct 11, 2019

@arevutsky did you have to require that somewhere? running into this issue myself. nvm-webpacker works great... and then gets totally ignored during asset compilation.

Edit: nevermind, renamed it to .rake, as Capfile requires all .rake files in lib/capistrano/tasks. Worked like a charm, that should be a PR!

@prusswan
Copy link

#25 (comment) is spot on.

Without setting up nvm (for capistrano), the error is just the unhelpful rake exit status: 1 (SSHKit::Command::Failed). On the instance itself, yarn loads without error due to interactive session.

@SixiS
Copy link

SixiS commented Jul 4, 2020

Ahhh this was so painful to figure out.

This: #25 (comment)

@kubaracek
Copy link

kubaracek commented Dec 9, 2020

I don't think that this is an issue of this package.

Whoever has this issue:

  1. Make sure you have a default node version set. For example (nvm alias default v14.15.1) you will get away if you only have 1 node installed using nvm but as soon as you install second version, there's no default. It doesn't matter much which you choose as default. This package will use the right one if you set it correctly with set :nvm_node, 'someVersion' given your command is mapped (see point 2)
  2. Do you have nvm_map_bins set? for example set :nvm_map_bins, %w{node npm yarn webpack rake}. It's not super obvious from the documentation but the nvm_map_bins is a list of commands which will be prefixed with the nvm-exec.sh script that sets the correct node version in itself by doing nvm set command
  3. In case you're using yarn it must be somehow installed. Either by placing it somewhere in package.json and running npm install before your assets precomile pipeline or by installing it manually on each server with for example nvm use v14.15.1 && npm install yarn -g

You might also have a problem of shell. If whatever capistrano executes you can execute manually by sshing into the node and calling the command but capistrano fails doing same you might want to check setting correct shell in capistrano

@Mirk32
Copy link

Mirk32 commented Apr 2, 2021

3. t must be somehow installed. Either by placing it somewhere in package.json and running npm install before your assets precomile pipeline or by installing it manually on each server with for example nvm use v14.15.1 && npm install yarn -g

You might also have a problem of shell. If whatever

I updated nvm_map_bins with %w{node npm yarn webpack rake} and now it works for me, thank you!

@gregblass
Copy link

A better way, as suggested here https://stackoverflow.com/questions/39624035/capistrano-and-api-keys-in-env-variables#answer-39628182

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

Hours and hours I wasted until I found your comment. Thank you so much sir!

@abyong123
Copy link

yarn run v1.22.17
error Couldn't find a package.json file in "/home/ubuntu"
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.

can anybody help me with this? please?

@IvRRimum
Copy link

@abyong123 Did you manage to resolve this?

@el-quick
Copy link

A better way, as suggested here https://stackoverflow.com/questions/39624035/capistrano-and-api-keys-in-env-variables#answer-39628182

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

This should be on the README file.

@jschroe212
Copy link

For those still using webpacker and capistrano-nvm. This applied to webpacker 5.4.3

Webpacker enhances rake assets:precompile with yarn:install which eventually calls whatever yarn is in your system's path. The problem is that we're getting at yarn through a rake command issued through capistrano and that is not nvm mapped. So we need rake to be an nvm mapped bin as well. Our solution was to add rake to nvm_map_bins.

set :nvm_map_bins, %w{node npm yarn yarnpkg rake}

This will prefix any rake command issued through capistrano with the nvm-exec.sh script that capistrano-nvm uploads.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests