The U.S. Army
But, I can’t really blame all of it on life – after Matthias gave me a crash course on Capistrano basics, I was a bit daunted by recreating the application directory environment for every deploy. Symlinks, local configuration details, file permissions…oh my!
K.I.S.S.
Last weekend brought some cold rainy weather and I got around to thinking about Cap again. Could I write a simplified Cap file which would just run svn info
& svn update
?
Here’s my info task:
task :info, :roles => defer { eval(Capistrano::CLI.ui.ask("Server roles ([:role1,:role2,...]) : ")) } do run "svnversion #{deploy_dir}" do |channel, stream, data| data = data.chomp # remove line separators result = "r" + data + " " + channel[:host] #check for trailing SVN status characters 'M','C',etc. # if (data.to_i.to_s == data) # result += " => clean" # else # result += " => contaminated" # end puts result end end
The CLI.ui.ask
allows me to input the desired role group(s) at runtime. I’ve also figured out how to identify if a remote repository’s not 100% clean (which I’ve commented out for now). Here’s the sample output of a run:
danackerson ~/dev$ sudo cap info * executing `info' * executing "svnversion /data/www/svn/" Server roles ([:role1,:role2,...]) : :all servers: ["db.netdoktor.de", "slave1.netdoktor.de", "slave2.netdoktor.de", "test.netdoktor.de"] [db.netdoktor.de] executing command [slave1.netdoktor.de] executing command [slave2.netdoktor.de] executing command [test.netdoktor.de] executing command r3357 db.netdoktor.de r3357 slave1.netdoktor.de r3357 test.netdoktor.de r3357 slave2.netdoktor.de command finished
Nice. Why sudo
you may ask? Just because I’ve made deployment drop-dead easy, doesn’t mean I should be able to cold-cock my application. With great power comes great responsibility, and I reassert this by making my cap file executable only by root.
Where the Rubber Meets the Road
Ok, I’d cut my teeth and gained confidence that I could write custom cap tasks to accomplish important goals. Now time for the main event: svn update
:
task :update, :roles => defer { eval(Capistrano::CLI.ui.ask("Server roles ([:role1,:role2,...]) : ")) } do rev = ENV['REV']; if rev == nil rev = "HEAD" end run "svn update -r#{rev} #{deploy_dir}" end
The REV
env variable gives me the ability to specify a specific revision (useful for a rollback as well):
danackerson ~/dev$ sudo cap update REV=3356 * executing `update' * executing "svn update -r3356 /data/www/svn/" Server roles ([:role1,:role2,...]) : :test servers: ["test.netdoktor.de"] [test.netdoktor.de] executing command ** [out :: test.netdoktor.de] U /data/www/svn/do_news.gif ** [out :: test.netdoktor.de] U /data/www/svn/do_arzt.gif ** [out :: test.netdoktor.de] U /data/www/svn/do_forum.gif ** [out :: test.netdoktor.de] Updated to revision 3356. command finished
Leaps and Bounds
After putting the final touches on this Monday morning, I gave it a thorough workout. Not only did I notice a signficant time savings in using cap, but I suddenly had extremely fine deployment possibilities. By the time the day was through, I was running 4 different versions of our codebase among the various servers. This probably sounds horrifying, but it really allowed us to insulate the productive slaves from untested (and unnecessary) code changes. The sudo cap info
script gave me a quick overview of exactly what was running where.
Ultimately, it only cost me a few hours to get this setup and I certainly wish I would have done it like this four months ago. How are you using capistrano in your environment? Share with us in the comments!
I already posted in your newer article about capistrano. But since did you run into any trouble using it? It’s been over a year, so you should have good experience now.
LikeLike
I’ve used capistrano for over two years and it did not fail me in it’s basic operations.
Only, if you want to extend it, then you will have fun with it’s code base. But that’s another story…
LikeLike