capistrano / rails

Official Ruby on Rails specific tasks for Capistrano
http://www.capistranorb.com/
MIT License
867 stars 270 forks source link

Not compiling webpacker assets on deployment #237

Closed angarc closed 4 years ago

angarc commented 4 years ago

Important: GitHub issues are for feature requests or bug reports. The Capistrano team recommends you use Stack Overflow for general questions. For more details, please see our contribution policy.


Steps to reproduce

Use this custom rake task

after "deploy:finished", "deploy:bin_webpack"

namespace :deploy do
  desc 'Run bin webpack'
  task :bin_webpack do
    on roles(:web) do
      within release_path do
        execute("cd #{release_path} && bin/webpack")
      end
    end
  end
end

and then run cap production deploy

Expected behavior

Assets should be compiled and you should be able to see css and javascript working on front end.

Actual behavior

I get this error:


EBUG [110a754c]       /usr/lib/ruby/2.5.0/rubygems/core_ext/kernel_require.rb:59:in `require'

 DEBUG [110a754c]       :

 DEBUG [110a754c]       cannot load such file -- bundler/setup

 DEBUG [110a754c]        (

 DEBUG [110a754c]       LoadError

 DEBUG [110a754c]       )

 DEBUG [110a754c]               from /usr/lib/ruby/2.5.0/rubygems/core_ext/kernel_require.rb:59:in `require'

 DEBUG [110a754c]               from bin/webpack:11:in `<main>'

When I remove the custom task

The deployment works, however the assets don't compile. I can tell because when I visit the website, it's like the css and javascript are non-existent.

The website looks like one of those old school pure html websites.

System configuration

https://gist.github.com/angarc/1ccda59935b5413c53aa34c76a5fa09f

mattbrictson commented 4 years ago

I have never used webpack directly in a Rails app, so I am not sure what is going on here. My experience is with webpacker, which automatically hooks into the standard Rails assets:precompile step, making custom tasks unnecessary.

However if were to take a guess, I see there is something odd about the custom task:

within release_path do
  execute("cd #{release_path} && bin/webpack")
end

within release_path already changes into the release directory, so cd #{release_path} && is redundant. Furthermore, when you execute a shell script containing spaces like "cd #{release_path} && bin/webpack", Capistrano executes the script verbatim, without going through plugins like rvm or bundler. That could be the source of the problem.

Does this version give a different result?

within release_path do
  execute("bin/webpack")
end
angarc commented 4 years ago

@mattbrictson

My bad, I am using Webpacker. I have had this problem with every rails 6 app I’ve tried to deploy. Any ideas as to why it’s not automatically hooking into assets:precompile?

Update

I tried following the link you provided:

https://github.com/rails/webpacker/blob/c7292e9a1e158e5fc9ec3026256cf7a42d70f549/docs/deployment.md#deployment

I edited my nginx config for the website, added some more linked directories, and also added that last rake task about running yarn install before the running of assets:precompile

It still did not work. I didn't get an error, but again I could not see any of the css or javascript on the frontend. Only the html was showing up.

Also, I tried this:

within release_path do
  execute("bin/webpack")
end

and It didn't work either.

mattbrictson commented 4 years ago

Hmm. I would check the following:

  1. Do the deploy logs have evidence that the deploy:assets:precompile task is running?
  2. Are Node and Yarn installed and working on the server?
  3. Are files being created inside public/packs/?
angarc commented 4 years ago

@mattbrictson

Yes, yes, and yes.

Also, for public/packs, I tried sending them over to production from development. I.e., uncommenting public/packs from my .gitignore. That didn't work either.

Also, thanks for taking the time to help. I was able to get passed all of this by ssh-ing into my server every deployment and running bin/webpack which was a bit annoying but not much of a problem. However, it would be nice if the whole deployment process could be automated.

mattbrictson commented 4 years ago

Sorry, I am stumped. I know for certain that assets:precompile works, because I have a personal project that deploys using that mechanism.

The fact that you said the files exist in public/packs but still aren't getting served at first led me to think maybe it is a web server issue; i.e. either Nginx is misconfigured or config.public_file_server.enabled is not set to true in environments/production.rb. However that is contradicted by the fact that running bin/webpack manually makes things work, which has nothing to do with the web server. That's the part that doesn't add up for me.

The only thing I can think of is that maybe RAILS_ENV or NODE_ENV are not set properly depending on whether you log in interactively via SSH vs deploy via Capistrano. Many Capistrano issues boil down to this fundamental issue: https://capistranorb.com/documentation/faq/why-does-something-work-in-my-ssh-session-but-not-in-capistrano/

angarc commented 4 years ago

@mattbrictson

Lol wow thank you, this actually solved the problem. All I had to do was set RAILS_ENV and NODE_ENV environment variables to "production" and now everything works as it should on deployment!

Thanks for all the help!

Ex-Ark commented 4 years ago

Had kind of a similar issue, but I didn't want to hard code RAILS_ENV=production in my deploy.rb task (which might be development or test depending on deploy target like staging ..) so I did:

namespace :deploy do
  desc 'Run bin webpack'
  task :bin_webpack do
    on roles(:web) do
      within release_path do
       with rails_env: fetch(:rails_env) do
        execute :bundle, 'exec rails assets:precompile'
      end
    end
  end
end

and in config/deploy/production.rb

# server "example.com", user: "deploy", roles: %w{app db web}, my_property: :my_value
set :rails_env, 'production'

hope it helps someone