If you're using rails with Sprockets and Opscode Chef, how are you handling asset precompilation during deployment? I want to keep my git history clean, so I don't want do precompile them locally and then commit them to the repository.
The easiest way seems to be to add them to the application cookbook's migration command, but that seems nasty to me. Asset precompilation should be separate from database migrations. Any other suggestions on how to handle this?
If you are using the deploy_revision resource, you can stick the rake task to do the asset precompiling into the before_restart block.
Here is the snippet of code that is in my deploy_revision resource. Since I am using RVM, I have installed Fletcher Nichol's amazing RVM cookbook of awesomeness. You could replace this with a ruby-block resource.
Checkout a more complete example in my gist.
app = node[:rails][:app_name]
before_restart do
rvm_shell "assets precompile" do
ruby_string "#{app[:ruby_ver]}##{app[:gemset]}"
cwd release_path
user app[:deploy_user]
group app[:deploy_user]
# TODO I could not set the environment via the builtin command. Does not look like it is getting passed to popen4
# So instead of `environment "RAILS_ENV" => app[:environment]` I have it in the code block
code %{
export RAILS_ENV=#{app[:environment]}
bundle exec rake assets:precompile
}
end
end
Related
Using Rails 6.0.2.1 with Ruby 2.6.3 and NGINX
I have a rake task that has the job of re compiling assets when they change in the production server
#Called by delayed job UpdateAssetsJob
require 'rake'
desc "Applying Theme, will restart server and may take a while!"
task :apply_css => :environment do
Rails.logger.info("Applying CSS in #{Rails.env}")
if Rails.env == "production"
Rails.logger.info("Compiling Assets")
Rake::Task['assets:precompile'].invoke
Rake::Task['assets:precompile'].reenable
# `RAILS_ENV=production rails assets:precompile`
Rails.logger.info("Cleaning assets - busting cache")
Rake::Task['assets:clean'].invoke
Rake::Task['assets:clean'].reenable
# `RAILS_ENV="production" rake assets:clean`
Rails.logger.info("Restarting Puma server")
`bundle exec pumactl -S /home/app_path/shared/tmp/pids/puma.state -F /home/app_path/shared/puma.rb restart`
end
end
The problem with this is that assets will only ever be compiled once.
I have tried clobbering the assets before compiling using
#Clobber assets to force recompilation
Rails.logger.info("Clobber Assets")
Rake::Task['assets:clobber'].invoke
Rake::Task['assets:clobber'].reenable
But again this will only work once
The scenario is:
An administrator updates colours for the current application theme which causes a background task, delayed job, to write necessary changes to
assests/stylesheets/_colours.scss file
For these changes to take effect I compile the assets, clean the assets, ensuring visitors that have cached assets get the latest version and then restart the server
As I am using the partial syntax for the naming of _colours.scss I have no need for this functionality in the development environment as changes are automatically picked up
Suggestions for a more appropriate solution are welcome
Solved the issue by switching from using
Rake::Task['assets:precompile'].invoke
Rake::Task['assets:precompile'].reenable
to
RAILS_ENV=production rails assets:precompile
I do need to clobber the assets and unexplainably the assets:clobber task will run multiple times once I switched the precompile task
Problem solved
I use Capistrano for deploying my Rails 4 app. Precompiling assets on the server is very slow so I manually precompile it in development using RAILS_ENV=production bundle exec rake assets:precompile and add it to my git repo.
The problem I am facing is that the assets:precompile task does not remove the old assets. So, I have multiple copies of application-<manifest code>.css and application-<manifest-code>.js in my public assets.
Capistrano has deploy:assets:clean_expired task for this though I am not sure how can I replicate it in my case. I have seen other approaches which use capistrano task to precompile assets and rsync them up. This link - http://keighl.com/post/fast-rails-assets-precompile-capistrano/ - has an approach for Rails 3 using the turbo-sprockets-rails3 gem.
There are similar questions here - Do I have to run rake assets:clean before rake assets:precompile? and Confusion about rake assets:clean / cleanup on the asset pipeline in rails
How can I adapt it for Rails 4?
This is working well for me now - https://gist.github.com/mishrarohit/7802260 It uses git revision history to check if any changes have been made to assets. It will be better if we can use the manifest for this.
When I try to access my site, then check my Heroku logs, I see this error:
ActionView::Template::Error (couldn't find file 'reset'
2012-06-13T02:31:43+00:00 app[web.1]: (in
/app/app/assets/stylesheets/application.css:4)):
(application.css contains the line *= require reset)
Then I thought to run "heroku run bundle exec rake assets:precompile:all" but this gives a similar error:
-----> Preparing app for Rails asset pipeline
Running: rake assets:precompile
rake aborted!
couldn't find file 'main/first.js.coffee'
(in /tmp/build_3428u21sggsoc/app/assets/javascripts/application.js:1)
Tasks: TOP => assets:precompile:primary
(That file is the first one required from my application.js, which has first line "//= require main/first.js.coffee")
In summary: my application runs fine locally, but when I deploy to Heroku, the files can no longer be found. Any ideas why?
Edit: here is the project tree. (There is one more directory before the app one, and that is the main project directory that also contains config, db, log, etc)
Another edit: there is no problem with .gitignore, or .slugignore.
At first, I would suggest you to run your application in production mode on your local computer. There are some errors (in assets but I also found some in routing) which can have impact only for production environment so you can test and fix them locally instead of having to do it from the production server.
About the asset precompilation on Heroku, the solution given by akjoe should result in compiled assets tracked in git repo : with this option, you should disable the asset precompilation which happen on Heroku and let Rails serve you assets (set config.serve_static_assets = true in your production.rb file) but this is not the best way to deal with the asset pipeline as you lost one of his major benefice which is freeing your rails application of request for asset.
To make it working properly, you should setup something like heroku explain : Using Rack::Cache with Memcached for Static Asset Caching in Rails 3.1+
I would also suggest you to try the assets precompilation locally in production environment RAILS_ENV=production bundle exec rake assets:precompile. To see if you got any error.
Finally you may want to check this different links to find useful information :
Rails 3.1+ Asset Pipeline on Heroku Cedar
Railscasts : #279 Understanding the Asset Pipeline
Rails Guide
I've had almost exactly the same problem and similar errors with stylesheets edits not taking effect... I found that I would edit css (or as in your case references to css files) which seemed to be ignored by Heroku. Turns out Heroku was ONLY referencing the stylesheets in the public/assets directory. I cleared this directory and was able to get it working.
I later found that you need to precompile your assets directory BEFORE you checkin to git. You would do this as follows:
Precompile assets directory: rake assets:precompile
Add the project files to the current Git repository: git add .
Checkin the file changes to the current Git repository: git commit
-am "description goes here"
Push the files to Heroku: git push heroku master (substitute
'master' for the branch you wish to push to Heroku).
Hope that helps!
The problem with this app is that is WIP, so we are not using anything to deploy it to our production server, we just clone it from github and we are doing a git pull every time we have something done, rake assets:precompile task takes more than 30 minutes to finish!, WTF?.
We are doing this:
$ bundle exec rake assets:clean
$ bundle exec rake assets:precompile
Our production server:
ruby 1.9.3p194 (rbenv)
rails 3.2.3
unicorn
nginx
Our rails + unicorn + rbenv + init.d daemon configuration is here: https://gist.github.com/2776085
Now, here's our assets manifests, Gemfile and our production.rb files: http://pastie.org/3958070
So, somebody knows why this takes so long? or there's a way to speed up assets compilation in production?.
Thank you.
UPDATE: Assets compilation times locally: http://pastie.org/3961734
Rails's asset pipeline looks a little bit further than app/assets/{javascripts,stylesheets}.
As mentioned in the guides, there are also other locations where you can put your application's assets:
app/assets
lib/assets
vendor/assets
I suggest you to read the complete guide on Rails's asset pipeline to get more information about all this and also some tips for your production environment, such as nginx rules for caching, speeding up the assets pre-compilation, etc.
Was our fault, we have an extra folder inside app/assets, like app/assets/blah with a lot of folders inside, so the assets pipeline was looking over there, still, we don't know why the assets pipeline isn't just looking inside app/assets/javascripts and app/assets/stylesheets.
Started working on a new application this week that is running the latest rails 3.2.2 with the asset pipeline. For the assets I would like the assets to be compiled when pushing the app to heroku (rather than having to manually compile and store compiled assets in the repo). The docs suggest this should happen automatically.
The problem I have is when I run git push heroku master it does not seem to run the rake assets:precompile task at all. The assets are never compiled. Here is the output I get:
-----> Heroku receiving push
-----> Ruby/Rails app detected
-----> Installing dependencies using Bundler version 1.1.rc.7
Running: bundle install --without development:test --path vendor/bundle --binstubs bin/ --deployment
Using rake (0.9.2.2)
.......
.......
Your bundle is complete! It was installed into ./vendor/bundle
Cleaning up the bundler cache.
-----> Writing config/database.yml to read from DATABASE_URL
-----> Rails plugin injection
Injecting rails_log_stdout
Injecting rails3_serve_static_assets
-----> Discovering process types
Procfile declares types -> web
Default types for Ruby/Rails -> console, rake, worker
-----> Compiled slug size is 61.7MB
-----> Launching... done, v30
[appname] deployed to Heroku
I have the asset pipeline enabled in my application.rb
require File.expand_path('../boot', __FILE__)
require "action_controller/railtie"
require "action_mailer/railtie"
require "active_resource/railtie"
require "sprockets/railtie"
Bundler.require *Rails.groups(:assets) if defined?(Bundler)
module Appname
class Application < Rails::Application
# ...
# Enable the asset pipeline
config.assets.enabled = true
# Do not boot the app when precompiling assets
config.assets.initialize_on_precompile = false
end
end
Anyone know what might be causing the problem? I'm happy to gist more code if need be. If I run heroku info it shows that i'm running on the Cedar stack.
I had to turn on config.assets.compile = true to stop receiving 500 errors in production, although this compiles the assets at runtime (which I do not want).
This seems to be solved now. I believe it was caused by the Rakefile not loading the assets:precompile task in production.
The rakefile was loading up tasks for both the cucumber and rspec gems which are not bundled into production. As a result the assets:precompile task was not available in production so heroku didn't attempt to run it.
I wrapped the test tasks in a environment check conditional like so:
if %(development test).include?(Rails.env)
require 'rspec/core'
require 'rspec/core/rake_task'
end
If there's anything wrong in your Rakefile then the precompile step will be skipped entirely. For me, I was referring to a dependency that was only being loaded in my test and development environments and not production so the rakefile was bombing.
Using the suggestion from #Lecky-Lao worked for me.
heroku run rake -T --app staging-hawkmo
Running `rake -T` attached to terminal... up, run.1
rake aborted!
cannot load such file -- jasmine-headless-webkit
Once I saw that it was as simple as wrapping the Rakefile require in an environment test.
I normally add this to production.rb:
# Precompile additional assets (application.js, application.css, and all non-JS/CSS are already added)
config.assets.precompile += %w( style.css grid.css ... geo.js jquery.flexslider-min.js)
and set:
config.assets.compile = false
It appears that this results from something dying because of a fatal error when heroku attempts to start/check for assets. This may not actually be related to Rails 3.2. I don't know.
I didn't have time to wait for heroku to help so I went through the painful process below to determine what the problem was. I recommend you do it also.
Create a new, separate rails 3.2.2 app. There is nothing in it besides the default files. Create a heroku app: heroku create --stack cedar. Just for your sanity, push out this app as it stands and see that the precompilation step happens during slug compilation.
Copy into the new app, each logical block of your application. I started with app/assets. (thinking it was something to do with assets and precompilation... nah) cp -R ../ProblemApp/app/assets/* app/assets/ Then add, commit, and push this to the heroku git remote.
At some point, you are going to copy over a group of files that will stop the assets:precompile message from appearing during slug compilation. Now, one by one, revert those files to the original raw state or comment out suspicious lines and push back out to heroku. Once you see the precompilation message again, you've found your problem.
It turned out that for us, I had several false alarms. When I copied the config directory over to the new app, the app module name was our old app and not the new one. This also prevented the precompilation from happening, but it was not the original cause I was looking for.
In the end, we had a rake task that was responsible for loading CSV data into the app during development. It had one line that was causing a problem:
require "#{Rails.root.to_s}/config/environment"
Commenting out this line in our original app fixed our problem. So is this Rails 3.2 related? Why is heroku running unrelated rake tasks? I dunno. But shit's working. :)
Just having the same issue on both Rails 3.1.3 and Rails 3.2.3. Following Mario's idea, The rake task do exist while I run "heroku run rake -T". So anyone got feedback from Heroku's feedback yet? I might just raise ticket for this as well then...
I had the same problem I following this guide https://devcenter.heroku.com/articles/rails-asset-pipeline fixed it.
Regards.
Try to add the following into production.rb
config.assets.precompile = ['*.js', '*.css']
I also found this site https://coderwall.com/p/ga9l-a
Rename your css to .css.erb and use the asset_path tag in your rule.
E.g.
background: url(<%= asset_path 'bg.png'%>);
As mentioned in 2.3.1
http://guides.rubyonrails.org/asset_pipeline.html#coding-links-to-assets