The Buckblog

assorted ramblings by Jamis Buck

Capistrano 2.4.0

13 June 2008 — 5-minute read

Capistrano 2.4.0 is now available.

gem install capistrano

Report bugs to Capistrano’s Lighthouse project. And if you have some ideas for patches, please patch against the code at Capistrano’s GitHub repository.

Here’s the skinny on 2.4.0:

death to “git fetch --tags“

You git users out there will be pleased to learn that this release will no longer do “git fetch --tags”, meaning your git-based deploys will finally work again. Sorry that took so long to fix. It was really ridiculously simple. :(

cap -d

Mark Imbriaco added a debug switch for enabling conditional execution of commands. This is fantastic for debugging and testing tasks, since you can basically step through your tasks and approve or deny each remote command as it is executed. Just give cap the “-d” switch to enable this.

New and improved sudo helper

No, really. This time I mean it. I pulled the version of sudo introduced in 2.3.0 (where each sudo command was wrapped in an explicit sh invocation), and put it back almost exactly as it was. However, if you call sudo without a command to execute, it will instead return the sudo command to use. On top of that, if the run() helper detects that you’re using sudo, it will listen for password prompts. So you can now do arbitrarily complex sudo commands like this:

run "if [ -d /some/directory ]; then #{sudo} chmod -R g+w /some/directory; fi"

In other words, just dump the sudo() call into your command as an interpolated value, and the real sudo command gets substituted. You can pass options to it as well:

run "#{sudo :as => "bob"} something"

And, naturally, the original sudo() syntax we all know and love remains as before:

sudo "something", :as => "bob" 

The deployment recipes themselves have been updated to use this new syntax, as needed.

:runner vs. :admin_runner

Some cappers have noted that having deploy:setup and deploy:cleanup run as the :runner user messed up their carefully crafted permissions. I agreed that this was a problem. With this release, deploy:start, deploy:stop, and deploy:restart all continue to use the :runner user when sudoing, but deploy:setup and deploy:cleanup will use the :admin_runner user. The :admin_runner variable is unset, by default, meaning those tasks will sudo as root, but if you want them to run as :runner, just do “set :admin_runner, runner”.

deploy:upload with globs

You can now specify glob patterns with deploy:upload:

$ cap deploy:upload FILES="config/apache/*.conf" 

As before, you can also specify entire folders to upload, but now the upload is being done via the upload() helper (introduced in 2.3.0) so the behavior is more standardized.

before/after hooks use well-defined server scope

Prior to this release, if you defined a before hook using a block, the block would be executed within the same server scope as the original task that invoked task that this hook was attached to. (whew!)

In other words:

task :first, :roles => :app do 
  # ... 

task :second, :roles => :db do 
  # ... 

before :second do 
  # ... 

Prior to this release, when “first” calls “second”, the before hook at the bottom would get called, but it would get called with the :roles => :app server constraint active, instead of :roles => :db. This preview release makes those hooks use the server scope of the task they are attached to.

host reported correctly from SCM output

Prior to this release, when any output was processed by the :checkout, :export, or :remote_cache strategies, you’d not be able to tell what host the output was from (it’d just be prefixed [err] or [out]). With this release, that output is correctly tagged with the host that generated it, making it easier to troubleshoot issues with SCM command execution.

Disable asset timestamp normalization

Some SCM’s give you the option of forcing the modification times of files that are being checked out to be the time that they were last modified in the repository. If your SCM gives you that capability, and if you enable it (however that works in your SCM), then you don’t need the massive touch command that Capistrano’s default deployment tasks run on each deploy, which is cap’s way of forcing all assets on all of your servers to have the same timestamp.

To disable Capistrano’s default timestamp normalization step, just set the :normalize_asset_timestamps variable to false:

set :normalize_asset_timestamps, false

You could also do this if you are deploying to a single server only. Note, though, that if you do this when deploying to multiple servers, and you haven’t configured your SCM to set the timestamps on the files on checkout, then Rails may use inconsistent timestamps on the assets, causing caching of your assets to fail and resulting in longer load times for your users.

Other lesser fixes, straight from the CHANGELOG

  • Make git SCM honor the :scm_verbose option [Jamis Buck]
  • Don’t follow symlinks when using :copy_cache [Jamis Buck]
  • If :mode is given to upload() helper, do a chmod after to set the mode [Jamis Buck]
  • Fix load_from_file method for windows users [Neil Wilson]
  • Display a deprecation error if a remote git branch is specified [Tim Harper]
  • Make set(:default_shell, false) work for not using a shell on a per-command basis [Ryan McGeary]
  • Use upload() instead of put() with the copy strategy [Jamis Buck]
  • Improved test coverage [Ryan McGeary]
  • Fixed “coverage” take task [Ryan McGeary]
  • Fix deploy:pending when using git SCM [Ryan McGeary]
  • Make sure deploy:check works with :none scm (which has no default command) [Jamis Buck]

Reader Comments

Hoorah, thank you so much for all your hard work.

Looks like a great release! Thanks to you and the entire community for all your work.

“Prior to this release, if you defined a before hook using a block, the block would be executed within the same server scope as the original task that invoked task that this hook was attached to.”

That needs refactoring.

Soooo…does this thing have documentation at all? How can it be on 2.4.0 and have no link to even a syntax specification from its webpage?

@web design company: it’s actually remarkably EASY for it to be at 2.4.0 and have no documentation. The hard thing is to document something. That’s why there isn’t any. Yet. It’s a work in progress. If a lack of documentation is too much of a hurdle (and it definitely is, for some) then Capistrano probably isn’t something you’ll want to investigate at this point. If that’s the case, feel free to look elsewhere. My feelings won’t be hurt.

Awesome! I can’t wait to use some of these features. Capistrano has been really great for deploying my rails app, but I also use it to set up and start 2-machine debugging for my OS X kernel extensions!

It would be handy if there was a super short upgrade guide (and perhaps I missed this between 2.1 -> 2.4).

All my scripts started failing when I upgraded; just simple things like

set :user, ‘other-user’ becomes ssh_options[:user] = ‘other-user’

put_file becomes upload

Just the little stuff.



Thanks Jamis. I’ll try to find the time to continue improving the test coverage.

@webdesigncompany: is a good place to start for some documentation

Also, wasn’t there someone who was going to take on an official documentation role?

@Ben, set(:user, ‘other-user’) should be working—we’re using it at 37signals. If it isn’t, please report it as a bug on the capistrano bug tracker, along with steps to duplicate it.

@Mark, yeah, Tyler Bird is heading up the documentation effort. It’s a slow and thankless task, unfortunately. I want this to be documented, but at the moment, it’s all I can do to keep myself motivated to apply bug fixes and such. I certainly appreciate Tyler’s efforts.

Great release, Jamis and contributers!

A note to @web design company: Capistrano has an example configuration that is well documented, and there are a lot of examples floating around the internet. It’s really very easy to get up and running.

Thanks so much for this Jamis. Your hard work is much appreciated.

Thanks so much! death to “git fetch—tags“ is really what i was searching for!


After I upgraded, the git checkout step fails:

git checkout -q -b deploy 64250d7dda85f9bcf18f138e48fa257b08e96525


Usage: /usr/bin/git-checkout -f -m [<paths>...]

@Mark, it sounds like you’ve got an old version of git installed, which doesn’t like the -q switch. You can either upgrade git on your servers, or you can set :scm_verbose to false, which will suppress the -q switch.

er, I meant, set :scm_verbose to true, not false. The default is false, which means “be quiet”, which implies the -q switch. Setting that variable to true will prevent Capistrano from emitting the -q switch with the SCM commands.

@Mark @Jamis, great! I was having the same problem and setting :scm_verbose to tru totally fixed it. Thanks a lot!

I’m having trouble getting Capistrano to install with a gem, it seems to require the exact release of the net libs (*.0.0) instead of whatever the latest release actually is. If I tell gem to install the exact version it works, but I want all the latest geegaws and bells and whistles.

@Ron, yeah, that was my bad. Please try installing Capistrano 2.4.3—it should fix that problem.

It would be great if you could add more examples (instead of only that 5 liner in the examples directory)

Does “set :deploy_via, :copy” use scp or sftp? I know I can set a switch on upload using via => :Scp, but is there a switch on deploy_via for this too?

Love how Capistrano is maturing. I’ve finally found that the best docs on Capistrano are the blog posts here. I greatly appreciate them. :)