Skip to content
This repository

Rails 3.1 Asset Pipeline support #35

Merged
merged 1 commit into from over 2 years ago

8 participants

Chris Griego Lee Hambley Sheldon Hearn Ênio Lopes Alex Ganov Richard Hulse Paco Guzmán Lukáš Konarovský
Chris Griego
cgriego commented May 17, 2011

I haven't dug into the details yet, but deploying Rails 3.1 will need some special consideration for the new asset pipeline support. I think it will mainly be symlinking a public/assets folder to the shared folder and running a precompile rake task. The tricky thing will be not breaking Rails < 3.1 apps.

Chris Griego
cgriego commented May 24, 2011

I'm really struggling with figuring out how to handle the rake assets:precompile task. I'm considering requiring the application load a "deploy/assets" recipe to get this functionality.

Chris Griego
cgriego commented May 25, 2011

There are other tools already in use that have asset compilation steps. Maybe it's as simple as having a variable that defines what the asset pre-compilation rake task is and run it only if it is defined and then update the generated deploy.rb to document it.

Chris Griego

Pull request added. Not the cleanest thing in the world but it's in line with people's expectations of Capistrano 2.x.

Chris Griego

Wait, I forgot about symlinking the assets folder to share unchanged assets across deploys. I think given that part of it, I'll go back to the idea of making it an additional recipe load.

Lee Hambley
Owner

Thanks @cgreigo - I'll get to reviewing and merging all these pull requests towards the end of the week, so we'll get something out of the door this month.

Lee Hambley
Owner

@sheldonh - thanks I believe I have enough information between you and @cgriego to do a decent job of getting this out of the door this weekend, watch this space for a pre-release :)

Chris Griego

@leehambley I've updated the pull request with a separate recipe that better supports the Rails 3.1 asset pipeline but it doesn't make any attempt to support any other asset compilers. This uses the best practices DHH outlined in his RailsConf keynote (namely the symlinking assets across deploys).

Chris Griego

I'm wondering if deploy:assets:symlink should run on any server with a release and not filter to just web servers. I could go either way.

Lee Hambley
Owner
Chris Griego

@leehambley I don't buy it. What makes an asset role distinct? What is a web server if not a server for assets?

Lee Hambley
Owner
Chris Griego

Help me understand. I don't see the functional difference between a server with the :web role as capistrano treats it now and an origin server for a CDN.

Ênio Lopes

Is this going to be merged anytime soon?

Lee Hambley
Owner
Alex Ganov
aganov commented July 05, 2011

When using this patch with bundler/capistrano recipes deploy:assets:symlink failing because the recipes are executed before bundle install. Any way to get bundler's recipe executed before deploy:assets?

Chris Griego

@aganov I'll have to change how the recipe hooks in.

Bundler runs the bundle:install task after deploy:update_code. Right now the assets recipe is running the asset precompile task after deploy:finalize_update which happens in the context of deploy:update_code.

There's no good common hook outside of deploy:update_code though, so the asset task could be changed to also hook in and run after deploy:update_code, but then in order to get the Bundler task to run before the asset recipe, you'll be dependent on the load order of the recipes, which would be pretty problematic in real world use.

load 'deploy'
load 'bundler/capistrano'
load 'deploy/assets'
Lee Hambley
Owner
Chris Griego

Unfortunately I don't think there is a sane additional hook to pick here. finalize_update is the sane hook and it already exists. I'm going to make the changes to this patch that allow it to work with Bundler in an load-order-dependent mode and then submit a patch to Bundler to change it to use the proper hook. I trust @indirect will merge it pretty quickly.

Chris Griego

Updated this pull request and sent the pull request to Bundler.

bundler/bundler#1300

Richard Hulse
rhulse commented July 15, 2011

You will also need to create a shared cache directory for the cache:

/tmp/cache/assets/ is used as the default cache directory

rails/rails@8f0e0b6
rails/rails@704ee0d

Otherwise the cache will be lost with each deployment.

Chris Griego

@rhulse Great catch, I'll get that worked in this weekend.

Richard Hulse
rhulse commented July 15, 2011

Cool. I'll update the asset pipeline docs when it is merged into master.

Chris Griego

I also need to add a variable for the assets path since it can be configured in Rails by setting assets.prefix.

Chris Griego

Removed the cache symlinking because it turns out it is not supposed to be shared.
rails/rails@d0f05a6#commitcomment-482674

Lee Hambley
Owner

@cgriego - great work on this, please give me a nod when you feel it's ready to be merged (or better yet, collapse the history into one clean commit I can pull) - I'll keep my eyes on this pull req. until such time as it feels like it's calmed down, or you tell me you're happy with it.

Chris Griego

@leehambley Added one small last fix from my testing and I've squashed. It's ready to go.

Richard Hulse
rhulse commented July 24, 2011

Do you have to set :assets_prefix in the project's deploy recipe, if you are not using the default of 'assets'?

Richard Hulse
rhulse commented July 24, 2011

Scratch that last comment, there is a bug. You have not use the param #{assets_prefix} every time in lines 23 and 24 of the patch.

This will cause issues for people who are using /assets as shared already. (Cannot offer a patch sorry, not git access from the office).

Chris Griego

@rhulse The assets_prefix variable is used to control the public path only and mirrors the Rails config option. The shared directory is a Capistrano concept and doesn't use the variable by design. The shared directory, being shared across deploys, needs to use stable, reserved names despite changes between users' individual deploys, like changing the prefix from one deploy to the next. No other shared directory name is configurable in the deploy recipe. This won't cause anyone who already has a public/assets directory any problems but it will if they have written custom recipes that setup a shared/assets folder and try to load the assets recipe but if they already have a custom assets system setup then they won't need to load this recipe.

Lee Hambley leehambley merged commit 228d686 into from August 02, 2011
Lee Hambley leehambley closed this August 02, 2011
Lukáš Konarovský

This is good, but what about not running precompile task, if it is not needed? Example in this blogpost - http://www.bencurtis.com/2011/12/skipping-asset-compilation-with-capistrano/

@daeltar please feel free to open an issue and/or send a patch (ideally making this configurable) - nothing will change from a commit comment!

Paco Guzmán

@pacoguzman Thank you for your constructive feedback.

Excuse me, that was the first thought after found what broke our deploy. We'll try to figure out a constructive way to solve our problems

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Showing 1 unique commit by 1 author.

Jul 19, 2011
Chris Griego Rails 3.1 Asset Pipeline support f68fcae
This page is out of date. Refresh to see the latest.
4  bin/capify
@@ -38,6 +38,10 @@ end
38 38
 files = {
39 39
   "Capfile" => unindent(<<-FILE),
40 40
     load 'deploy' if respond_to?(:namespace) # cap2 differentiator
  41
+
  42
+    # Uncomment if you are using Rails' asset pipeline
  43
+    # load 'deploy/assets'
  44
+
41 45
     Dir['vendor/gems/*/recipes/*.rb','vendor/plugins/*/recipes/*.rb'].each { |plugin| load(plugin) }
42 46
 
43 47
     load 'config/deploy' # remove this line to skip loading any of the default tasks
8  lib/capistrano/recipes/deploy.rb
@@ -28,7 +28,9 @@ def _cset(name, *args, &block)
28 28
 _cset(:deploy_to) { "/u/apps/#{application}" }
29 29
 _cset(:revision)  { source.head }
30 30
 
31  
-# Maintenance base filename
  31
+_cset :rails_env, "production"
  32
+_cset :rake, "rake"
  33
+
32 34
 _cset :maintenance_basename, "maintenance"
33 35
 
34 36
 # =========================================================================
@@ -384,8 +386,6 @@ def try_runner(*args)
384 386
       set :migrate_target, :latest
385 387
   DESC
386 388
   task :migrate, :roles => :db, :only => { :primary => true } do
387  
-    rake = fetch(:rake, "rake")
388  
-    rails_env = fetch(:rails_env, "production")
389 389
     migrate_env = fetch(:migrate_env, "")
390 390
     migrate_target = fetch(:migrate_target, :latest)
391 391
 
@@ -395,7 +395,7 @@ def try_runner(*args)
395 395
       else raise ArgumentError, "unknown migration target #{migrate_target.inspect}"
396 396
       end
397 397
 
398  
-    run "cd #{directory}; #{rake} RAILS_ENV=#{rails_env} #{migrate_env} db:migrate"
  398
+    run "cd #{directory} && #{rake} RAILS_ENV=#{rails_env} #{migrate_env} db:migrate"
399 399
   end
400 400
 
401 401
   desc <<-DESC
57  lib/capistrano/recipes/deploy/assets.rb
... ...
@@ -0,0 +1,57 @@
  1
+load 'deploy' unless defined?(_cset)
  2
+
  3
+_cset :asset_env, "RAILS_GROUPS=assets"
  4
+_cset :assets_prefix, "assets"
  5
+
  6
+before 'deploy:finalize_update', 'deploy:assets:symlink'
  7
+after 'deploy:update_code', 'deploy:assets:precompile'
  8
+
  9
+namespace :deploy do
  10
+  namespace :assets do
  11
+    desc <<-DESC
  12
+      [internal] This task will set up a symlink to the shared directory \
  13
+      for the assets directory. Assets are shared across deploys to avoid \
  14
+      mid-deploy mismatches between old application html asking for assets \
  15
+      and getting a 404 file not found error. The assets cache is shared \
  16
+      for efficiency. If you cutomize the assets path prefix, override the \
  17
+      :assets_prefix variable to match.
  18
+    DESC
  19
+    task :symlink, :roles => :web, :except => { :no_release => true } do
  20
+      run <<-CMD
  21
+        rm -rf #{latest_release}/public/#{assets_prefix} &&
  22
+        mkdir -p #{latest_release}/public &&
  23
+        mkdir -p #{shared_path}/assets &&
  24
+        ln -s #{shared_path}/assets #{latest_release}/public/#{assets_prefix}
  25
+      CMD
  26
+    end
  27
+
  28
+    desc <<-DESC
  29
+      Run the asset precompilation rake task. You can specify the full path \
  30
+      to the rake executable by setting the rake variable. You can also \
  31
+      specify additional environment variables to pass to rake via the \
  32
+      asset_env variable. The defaults are:
  33
+
  34
+        set :rake,      "rake"
  35
+        set :rails_env, "production"
  36
+        set :asset_env, "RAILS_GROUPS=assets"
  37
+    DESC
  38
+    task :precompile, :roles => :web, :except => { :no_release => true } do
  39
+      run "cd #{latest_release} && #{rake} RAILS_ENV=#{rails_env} #{asset_env} assets:precompile"
  40
+    end
  41
+
  42
+    desc <<-DESC
  43
+      Run the asset clean rake task. Use with caution, this will delete \
  44
+      all of your compiled assets. You can specify the full path \
  45
+      to the rake executable by setting the rake variable. You can also \
  46
+      specify additional environment variables to pass to rake via the \
  47
+      asset_env variable. The defaults are:
  48
+
  49
+        set :rake,      "rake"
  50
+        set :rails_env, "production"
  51
+        set :asset_env, "RAILS_GROUPS=assets"
  52
+    DESC
  53
+    task :clean, :roles => :web, :except => { :no_release => true } do
  54
+      run "cd #{latest_release} && #{rake} RAILS_ENV=#{rails_env} #{asset_env} assets:clean"
  55
+    end
  56
+  end
  57
+end
Commit_comment_tip

Tip: You can add notes to lines in a file. Hover to the left of a line to make a note

Something went wrong with that request. Please try again.