Refactoring Capistrano Deployment
Capistrano.
Love it or hate it, many people use it. And once you get it configured, it works
fairly well. I just finished up a long overdue refactoring of an old
deploy.rb file, one we've been happily treating as a blackbox for years,
mostly due to its unnecessary complexity. I'll take the blame. The road to
maintenance hell is filled with good intentions.
First I threw away all the one-off tasks that we never used or never worked quite
right: watching God /
Nginx logs, reloading configs, starting, stopping,
restarting, and checking statuses. You get the idea. The important ones are handled by
deploy:restart and its brethren, the rest are easily accomplished with
cap invoke COMMAND="foobar".
Next, all our twisted callback dependency trees got the axe. Now there's a single
hook that's called after deploy:update_code to swap in some production
configuration files, install any required gems, and optimize assets. Similarly, an
after deploy:setup hook takes care of setting up all directories and
configuration files in a single, easy-to-read, block of code.
Finally, I wanted to hide many of the default Capistrano tasks that just seem to
confuse new developers. Explaining the difference between deploy,
deploy:migrate, deploy:migrations,
deploy:update, and deploy:update_code gets tiring. Mostly
because I forget myself after a while. Just use deploy (which in our
case triggers migrations). This little hack at the bottom of deploy.rb
keeps it simple*:
config/deploy.rb
%w{ deploy:migrate deploy:update deploy:update_code ... }.each do |name| find_task(name).instance_variable_get(:@desc).insert(0, '[internal]') end
Now cap -T is short and sweet, and you can always do
Cap -vT to see everything. If you're interested, sickpea.com's
deploy.rb is available as a
gist on Github.