Asset Precompile on the development machine before capistrano deployment - ruby-on-rails-3.1

I want the asset precompile to happen on my dev machine beofore the code is packed (tar ball'ed) by capistrano and have the precompiled assets already included in the final deployment package.
When I try the inbuilt capistrano recipe thats in
load 'deploy/assets' it runs
rake RAILS_GROUPS=assets assets:precompile on the server.
The reason I am looking for this because at the moment the precompile is taking too long on my EC2 micro-instance (and also at times just hangs),
It would great if asset compile could be done even before the deploy starts so that I can save the server from this heavy duty work load - until at least I have better configured servers available.

The workflow is still a little bumpy at the moment, but you may find some success using Guard-Rails-Assets. It's a little slow, especially if you are making a lot of asset changes, but it will compile assets when they are changed and you can just check them in to your repo to be deployed later.

I've just written a gem to solve this problem inside Rails, called turbo-sprockets-rails3. It speeds up your assets:precompile by only recompiling changed files, and only compiling once to generate all assets. It works out of the box for Capistrano, since your assets directory is shared between releases.
It would be really awesome if you could help me test out the turbo-sprockets-rails3 gem, and let me know if you have any problems.

Remove load 'deploy/assets' from Capfile or config/deploy.rb, and add the following lines to the config/deploy.rb:
set :assets_role, [ :web, :app ]
set :normalize_asset_timestamps, false
set :assets_tar_path, "#{release_name}-assets.tar.gz"
before "deploy:update" do
run_locally "rake assets:precompile"
run_locally "cd public; tar czf #{Dir.tmpdir}/#{assets_tar_path} assets"
end
before "deploy:finalize_update", :roles => assets_role, :except => { :no_release => true } do
upload "#{Dir.tmpdir}/#{assets_tar_path}", "#{shared_path}/#{assets_tar_path}"
run "cd #{shared_path}; /bin/tar xzf #{assets_tar_path}"
run "/bin/ln -s #{shared_path}/assets #{release_path}/public"
run "/bin/rm #{shared_path}/#{assets_tar_path}"
end
If you use turbo-sprockets-rails3, add this to the last block:
run "cd #{release_path}; #{rake} assets:clean_expired 2> /dev/null"

Related

Phoenix framework - assets don't update without running mix phx.digest

After changing an asset (a css or js) file I see in the logs that the change was noticed and compiled, and the browser also auto-reloads.
[debug] Live reload: priv/static/js/app.js
10:53:15 - info: compiled MyComponent.jsx and 2095 cached files into 2
files in 2.3 sec
However, it doesn't appear that the assets in /priv/static were actually updated. I can only see my change in the browser once I run mix phx.digest, and hard refresh the browser.
Any ideas on how to troubleshoot this?
Using:
Phoenix 1.3
brunch 2.10.7
config/dev.exs:
config :my_app, MyApp.Web.Endpoint,
http: [port: 4000],
debug_errors: true,
code_reloader: true,
check_origin: false,
watchers: [node: ["node_modules/brunch/bin/brunch", "watch", "--stdin",
cd: Path.expand("../assets", __DIR__)]]
# Watch static and templates for browser reloading.
config :my_app, MyApp.Web.Endpoint,
live_reload: [
patterns: [
~r{priv/static/.*(js|css|png|jpeg|jpg|gif|svg)$},
~r{priv/gettext/.*(po)$},
~r{lib/my_app/web/views/.*(ex)$},
~r{lib/my_app/web/templates/.*(eex)$}
]
]
TL;DR — If you don't set the cache_static_manifest setting on your endpoint, it won't generate versioned URLs.
So, I know I'm about three years late here, but I recently figured this out. I discovered that merely setting the cache_static_manifest value in the Endpoint config will cause it to use the digest in any mode. (This is documented, but not in a way that seemed particularly clear to me.)
Now, you might be thinking "But I didn't set that in dev mode." I thought that, too, until I realized that I had written a naive config/runtime.exs.
At the time, I had been focused on configuring things a runtime when running a release, but completely forgot that it configures things even when not running in a release. Once I made it conditional, everything was fine.
Example:
if Config.config_env == :production do
config :my_app, MyAppWeb.Endpoint, cache_static_manifest: "priv/static/cache_manifest.json"
end
I ran into the same issue and for me it helped to manually remove the static folder with rm -rf priv/static and to restart the server with mix phx.server. Afterwards the hot reloading worked without having to manually run mix phx.digest all the time.
Another possible cause is that the Endpoint module (lib/my_app_web/endpoint.ex) is setting Plug.Static to use compressed assets:
defmodule MyAppWeb.Endpoint do
use Phoenix.Endpoint, otp_app: :my_app_web
plug Plug.Static,
# ...
gzip: true,
Then, if a release has been built from within the project directory and the gzipped assets are still present when developing, they will be served instead of the newly-saved, non-compressed assets.
To avoid this:
config/dev.exs:
config :my_app, :environment, :dev
config/test.exs:
config :my_app, :environment, :test
config/prod.exs:
config :my_app, :environment, :prod
lib/my_app_web/endpoint.ex:
defmodule MyAppWeb.Endpoint do
use Phoenix.Endpoint, otp_app: :my_app_web
in_prod = Application.get_env(:my_app, :environment) == :prod
plug Plug.Static,
# ...
gzip: in_prod,

Run command after gem install from gem root folder

I'm deploying a Sinatra app as a gem. I have a command that starts the app as a service.
We are using chef to manage our deployments.
How can I run the command to start the app service but only after it's fully installed (including run-time dependencies)?
I've tried Googling for trying to run a post-install script but I haven't found anything that is of use or concrete without some complicated 'extconf.rb' work around
I would prefer not to use an execute resource if I can help it.
EDIT: I tried what was suggested but it breaks thins in way that causes berkshelf not to work in our pipeline.
Here's the code I'm using:
execute "run-service:post_install" do
cwd (f = File.expand_path(__FILE__).split('/')).shift(f.length - 3).join('\\')
timeout 5
command "bundle && rake service:post_install"
# action :nothing
# subscribes :run, "gem_package[gem_name]" , :delayed
end
It doesn't matter if I un-comment or not the last two lines, it just breaks things but if i take out the whole thing it stops breaking things. Obviously I'm doing something wrong but I'm not sure what.
EDIT:
IT's the command itself that breaks it, when I change command to ls and action to :run, it breaks.
EDIT:after changing the command path around a bit I managed to get it to spit out a usable error, it was trying to run the command from chef cook books path, so I've (hopefully) forced it to use the correct path.
Why do you not want to use an execute resource? That is exactly what it is for, running commands from Chef. Chef obeys the order of the resources, so if you have a gem_package followed by an execute they will run in that order.
So, In the end I decided to try using the service resource because it allows you to set start, and stop commands.
The code that I used is :
service service_name do
init_command ("#{%x(gem env gemdir).strip.gsub('/','\\')}\\gems\\gem_name-#{installing_version}")
start_command "rake service:start"
stop_command "rake service:stop"
reload_command "rake service:reload"
restart_command "rake service:restart"
supports start: true, restart: true, reload: true
action [:enable,:start]
end
I'm still having problems but this is of a different sort.

How disable assets compilation on heroku?

I'm trying to deploy my rails app to heroku using this turtorial:
https://devcenter.heroku.com/articles/getting-started-with-rails4
So, I use rails 4.1.1 and ruby 2.1.1
My Gemfile has gem 'rails_12factor', group: :production inside.
My application.rb:
require File.expand_path('../boot', __FILE__)
require 'rails/all'
Bundler.require(*Rails.groups)
module Charticus
class Application Rails::Application
# Settings in config/environments/* take precedence over those specified here.
# Application configuration should go into files in config/initializers
# -- all .rb files in that directory are automatically loaded.
# Set Time.zone default to the specified zone and make Active Record auto-convert to this zone.
# Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC.
# config.time_zone = 'Central Time (US & Canada)'
# The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded.
# config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s]
# config.i18n.default_locale = :de
end
end
I created file public/assets/manifest.yml
But when I deploy app to heroku - it compile all my js-files files to application.js and all css-files application.css. And I can't see it on app.heroku.com using firebug.
What I need to do with my configurations to see all my js and css files on app.heroku.com ?
How disable assets precompiling and minification on heroku?
Help me please!
Thanks
lib/tasks/assets.rake
Rake::Task["assets:precompile"].clear
namespace :assets do
task 'precompile' do
puts "Not pre-compiling assets..."
end
end
You are done.
I compare config/environments/development.rb and config/environments/production.rb.
And make production.rb asset configs like in development.rb:
Comment this lines:
config.serve_static_assets = false
config.assets.js_compressor = :uglifier
config.assets.compile = false
config.assets.digest = true
Then:
Push my changes to git repo git push origin master
Push changes to heroku git push heroku master
Rails 4 applications have a manifest-*.json file, not a manifest.yml file. This file is typically generated when you run rake assets:precompile , how are you compiling your assets?
Regardless, you need a file public/assets/manifest-(fingerprint).json file
Fast forward to 2018, and you would need to add the following to config/initializers/production.rb:
config.assets.enabled = false
Then you'd need to customize Heroku's Ruby Buildpack to not run the assets:precompile rake task. I won't provide a link to such a buildpack because I won't support or warrant one, but its pretty easy to find it in lib/language_pack/ruby.rb and start removing relevant code.
You'd then have to configure your Heroku app to use your new forked Buildpack instead of the default one (e.g. using heroku buildpacks).
Thats the cleanest way to disable the asset pipeline in a Heroku app w/ Rails, without resorting to overriding Rails' built-in rake tasks.
Fast forward to 2021 and Rails 6.x, if you completely removed Webpacker and Sprockets/Asset Pipeline, replace the bin/yarn file content with something like:
#!/usr/bin/env ruby
puts 'Yarn not present, nothing to do.'
#danielricecodes's advice is probably still valid but way more invasive.

ckeditor.js file can't be found by rails_admin

I am trying to use ckeditor (4.0.6) with Using rails_admin (0.5.0) in Rails 4.0 on DigitalOcean server.
I have included it in the rails_admin.rb initializer as follows and it works in production mode on my local
config.model Faq do
field :display_order
field :question
field :answer, :ck_editor
end
However on DigitalOcean when I go into Rails_Admin and try to make a new FAQ object it won't load ckeditor because it can't find the js.
http://dummy.com/assets/ckeditor/ckeditor.js?_=1381313244552 404 (Not Found)
rails_admin-5daa9b7b76a226bdfa46a07fdaf2d77d.js:3
How can I fix this?
The problem is because Rails assets compile actually added a fingerprint on to the assets file of every CKeditor file, while the rails-admin is looking for a non fingerprint version of the file.
This issue only happens in the rails 4 with ckeditor. Actually the Readme.md of the ckeditor gem did mention about the issue and how to resolve it, but it isn't complete.
To resolve you could write a rake file to remove all the fingerprints and run this during deployment.
Here is my solution to resolve this issue.
Create a rake file in lib/tasks/ckeditor.rake with the following code
namespace :ckeditor do
desc 'Create nondigest versions of some ckeditor assets (e.g. moono skin png)'
task :create_nondigest_assets do
fingerprint = /\-[0-9a-f]{32}\./
for file in Dir[File.join('public/assets/ckeditor', '**', '*.js'),
File.join('public/assets/ckeditor', '**', '*.js.gz'),
File.join('public/assets/ckeditor', '**', '*.css'),
File.join('public/assets/ckeditor', '**', '*.png'),
File.join('public/assets/ckeditor', '**', '*.gif')]
next unless file =~ fingerprint
nondigest = file.sub fingerprint, '.' # contents-0d8ffa186a00f5063461bc0ba0d96087.css => contents.css
FileUtils.cp file, nondigest, verbose: true
end
end
end
For Capistrano user, make sure you include this in your deploy.rb
desc 'copy ckeditor nondigest assets'
task :copy_nondigest_assets, roles: :app do
run "cd #{latest_release} && #{rake} RAILS_ENV=#{rails_env} ckeditor:create_nondigest_assets"
end
after 'deploy:assets:precompile', 'copy_nondigest_assets'
For Heroku user, you would need to run the rake file manually each time before you check in your code. Make sure you do your rake assets:precompile before this.
rake ckeditor:create_nondigest_assets
Hope it helps
I don't know, have you precompiled your assets?
If you're switching from a different kind of host, like Heroku, you
may forget that you have to manually precompile your assets. You're
lucky, though – it's easy!
RAILS_ENV=production rake assets:precompile If you run into problems,
try running this instead:
RAILS_ENV=production rake assets:precompile:primary
From https://www.digitalocean.com/community/articles/how-to-launch-your-ruby-on-rails-app-with-the-digitalocean-one-click-image

Heroku does NOT compile files under assets pipelines in Rails 4

Everything goes well in local machine with assets pipeline in Rails 4 and Ruby 2.0. But when deploying to heroku, it is shown that:
-----> Preparing app for Rails asset pipeline
Running: rake assets:precompile
I, [2013-03-12T03:28:29.908234 #912] INFO -- : Writing /tmp/build_1n6yi8lwna3sj/public/assets/rails-2ee5a98f26fbf8c6c461127da73c47eb.png
I, [2013-03-12T03:28:29.914096 #912] INFO -- : Writing /tmp/build_1n6yi8lwna3sj/public/assets/trash-3c3c2861eca3747315d712bcfc182902.png
I, [2013-03-12T03:28:33.963234 #912] INFO -- : Writing /tmp/build_1n6yi8lwna3sj/public/assets/application-bf2525bd32aa2a7068dbcfaa591b3874.js
I, [2013-03-12T03:28:40.362850 #912] INFO -- : Writing /tmp/build_1n6yi8lwna3sj/public/assets/application-13374a65f29a3b4cea6f8da2816ce7ff.css
Asset precompilation completed (14.36s)
Heroku seems to compile files but put it in /tmp without any errors. My questions are:
How come Heroku compile assets files to /tmp?
My last solution was to run RAILS_ENV=production bundle exec rake assets:precompile locally, but this generated a manifest-xxxxxx.json in public/assets, rather than manifest.yml, so that heroku doesn't detect the JSON manifest file. I sorted it out by manually created a yml from the json file and heroku became happy. Has heroku's approach been outdated?
Heroku's asset plugins no longer work since Rails 4 does not support plugins. You need to use Heroku's asset gems instead. Place this in your Gemfile:
group :production do
gem 'rails_log_stdout', github: 'heroku/rails_log_stdout'
gem 'rails3_serve_static_assets', github: 'heroku/rails3_serve_static_assets'
end
Follow Heroku's guide on getting started with Rails 4.
Update (07/22/2013): Heroku now supplies a different gem to precompile assets.
group :production do
gem 'rails_12factor'
end
You need to config Rails to serve static assets in production: config/environments/production.rb
SampleApp::Application.configure do
.
.
.
config.serve_static_assets = true
.
.
.
end
UPDATE:
In Rails 4 is deprecated, and has been changed by:
config.serve_static_files = true
Since rails 4 replaced manifest.yml with manifest-(fingerprint).json, you'll want to enable static asset serving.
From Getting Started with Rails 4.x on Heroku:
gem 'rails_12factor', group: :production
then
bundle install
and, finally,
git push heroku
Fixed the issue for me. Hope this helps!
I run exactly into the same problem.
I set config.serve_static_assets = true in my environments/production.rb file until heroku wont't support the new manifest format.
So it is a temporal solution until heroku support will be added.
After hours of googling in which none of the guides on Heroku or the suggestions on StackOverFlow helped me, I finally ran into this blog post which offered this clue:
heroku labs:enable user-env-compile --app=YOUR_APP
Without this, the asset pipeline will always try to init the whole app and connect to the database (despite all the things you may have read that rails 4 now longer does this). This exposes your Heroku configuration to Rails so it can boot up successfully and run rake tasks like assets:precompile.
I needed to use this gem:
gem 'rails_12factor', group: :production #need this for rails 4 assets on heroku
And in /config/environments/production.rb I needed to set:
config.assets.compile = true
My understanding is that the rails_12_factor gem sets config.serve_static_assets = true, amongst other things.
In my case, assets compiled following the instructions above but it wasn't picking the bootstrap glyphicons 'fontawesome-webfont' so this worked for me finally after wasting so many hours researching.
Gem file
gem 'rails_12factor', group: :production
bundle install
config/application.rb
config.assets.precompile += %w(*.png *.jpg *.jpeg *.gif,
"fontawesome-webfont.ttf",
"fontawesome-webfont.eot",
"fontawesome-webfont.svg",
"fontawesome-webfont.woff")
config.assets.precompile << Proc.new do |path|
if path =~ /\.(css|js)\z/
full_path = Rails.application.assets.resolve(path).to_path
app_assets_path = Rails.root.join('app', 'assets').to_path
if full_path.starts_with? app_assets_path
puts "including asset: " + full_path
true
else
puts "excluding asset: " + full_path
false
end
else
false
end
end
environment/production.rb
config.serve_static_assets = true
Then finally, I ran
rake assets:precompile RAILS_ENV=production and pushed it to heroku and that worked.
This was an issue with the Heroku Ruby Buildpack, but an update was deployed today (2013-05-21). Please try it out and let us know.
To answer your questions:
#1) This is sprockets output; things are compiled to /tmp and then moved (See here in Sprockets). To my knowledge this has always been done this way, but it wasn't until Sprockets version was updated in Rails that we got this new debug-type output.
#2) Previously assets:precompile genereated a manifest.json file, but now in Rails 4 the manifest file has a fingerprint in it, which wasn't detected previously. This was fixed with #74.
I added this to the top of one of my css.scss files in the assets/stylesheets/ folder.
#import "font-awesome";
then ran..
rake assets:clean
and...
rake assets:precompile RAILS_ENV=production
In Rails 4.2.4 your production.rb has the line:
config.serve_static_files = ENV['RAILS_SERVE_STATIC_FILES'].present?
That means, gem 'rails_12factor', group: :production doesn`t need to change it to true, as it can be set through the heroku environment variables. You also will get a warning if you remove the rails_12factor gem.
If you have problems with assets, login to the heroku console heroku run rails console and find out the asset path for a file puts helper.asset_path("application.js") .
One strange behaviour I noticed between development and production, when the file ending is not provided:
With a image /assets/images/image_01.jpg the following output from asset_pathsdiffers:
Development:
development > puts helper.asset_path('profile_01')
=> /assets/profile_01-bbd16aac5ef1d295411af44c103fcc631ab90ee94957414d4c01c3aed1055714.jpg
development > puts helper.asset_path('profile_01.jpg')
=> /assets/profile_01-bbd16aac5ef1d295411af44c103fcc631ab90ee94957414d4c01c3aed1055714.jpg
Production:
development > puts helper.asset_path('profile_01')
=> /profile_01
development > puts helper.asset_path('profile_01.jpg')
=> /assets/profile_01-bbd16aac5ef1d295411af44c103fcc631ab90ee94957414d4c01c3aed1055714.jpg
You do not have to run RAILS_ENV=production rake assets:precompile, heroku does this for you during deploy. Also you do not have to precompile the assets in development and push them to heroku.
Apart from ensuring you have the 'rails_12factor' gem installed the only thing you need to do is this.
# config/application.rb
config.assets.paths << Rails.root.join('vendor', 'assets')
It seems that although Rails knows exactly what it wants, Heroku needs reminding to include the assets folder as part of the assets paths.
Use Image Extensions
I had this same issue, but for a different reason.
Instead of
<%= asset_path 'facebook-link' %>
Use:
<%= asset_path 'facebook-link.png' %>
While the first one worked locally, when I pushed to Heroku my images were breaking and I had no clue why. Using the full file extension fixed the problem :)
Add this gem gem 'rails_serve_static_assets'
https://github.com/heroku/rails_serve_static_assets
If you are using controller specific assets as in:
<%= javascript_include_tag params[:controller] %> or <%= javascript_include_tag params[:controller] %>
Then in production you will need to explicitly precompile those (in development rails compiles files on the fly).
See official Rails guide here: http://guides.rubyonrails.org/asset_pipeline.html#controller-specific-assets
To precompile as explained in the guides (here: http://guides.rubyonrails.org/asset_pipeline.html#precompiling-assets) you will need to add the following to the config/application.rb
# config/application.rb
config.assets.precompile << Proc.new do |path|
if path =~ /\.(css|js)\z/
full_path = Rails.application.assets.resolve(path).to_path
app_assets_path = Rails.root.join('app', 'assets').to_path
if full_path.starts_with? app_assets_path
puts "including asset: " + full_path
true
else
puts "excluding asset: " + full_path
false
end
else
false
end
end
I figure I'll add this as an answer since this question is linked from the Heroku Support page if you search for "assets".
This is mostly for people who are updating their app to Rails 4, but after going through this - and many other SO posts - what finally got me was changing the following in production.rb:
config.action_dispatch.x_sendfile_header = "X-Sendfile"
To:
config.action_dispatch.x_sendfile_header = nil
I hadn't caught this when I upgraded and as usual this took me forever to figure out. Hopefully it helps someone else! Shout out to PatrickEm who asked/answered the same in his question.
This may not answer the original question's root cause, But I was having a similar symptom with a different root cause.
Pre-compilation of a JPEG files changes the file extension to JPG, meaning that asset_path("my_image.jpeg") and asset_path("my_image") didn't work. Remove the "e" from JPEG and voila, it works.
Others have described the same problem here https://blazarblogs.wordpress.com/2016/04/06/rails-force-to-precompile-jpeg-to-jpg/
Is this a bug? Or desired behaviour? And also weird that it only doesn't work in my Heroku-hosted production environment. Maybe they have some sort of configuration.

Resources