03|04 Dead simple code deployment
I run neohippie.net on a number of servers at geographically separate locations... For fun.
For a while now, I've been looking for a good way to do code deployment from my development server to the two production servers. Not surprisingly, a lot of people pointed me at Capistrano, the flavor of the day for doing Rails deployment. Seeing as how I don't use Rails (this site runs on Django), Capistrano's builtin deployment recipies were of little use to me... Sure, I could modify the recipies or write my own, or even adapt somebody else's, but at the end of the day I'm left with a large chunk of unmaintained Ruby code that can break anytime.
I also found that Capistrano's documentation is weak at best... http://www.capify.org/ only gives a very light introduction to Capistrano and how to get it installed, beyond that, there is little useful information. The Rails website has a fairly large section on Capistrano, but little of it is relevant to the current version. The only remaining documentation I was able to find came in the form of blog posts from other users stranded by a lack of information. I managed to figure out how to get some basic stuff setup, and ended up just reading the source code to figure the rest out... Which I never should have needed to do.
For these and other reasons, I set off to find something better. I found a blog post that made mention of Fabric, a Capistrano-like deployment tool written in Python. Great! I thought, this should solve all my problems. While I agree with the author's decision to keep the tool as minimal as possible, he's taken it a little too far in that you end up with nothing more than an elaborate shell script, which is exactly what I'm using now. I think Fabric has potential, but the whole point of a deployment system is to give you the ability to do things that would be difficult or time consuming to do with shell scripts (eg. rollback a deployment).
So, if anybody knows of a deployment system written in Python that's well documented, extensible, and open source, let me know... Until then, I'm going to keep using the following shell scripts.
Usage: ./deploy sitename
#!/bin/bash
DEPLOY_ROOT="/web/sites"
source "$DEPLOY_ROOT/$1/.deploy"
function group_cmd {
for server in $1; do
echo -n "[$server] "
ssh $deploy_user@$server "$2" &>/tmp/deploy.log
if [ ! $? -eq 0 ]; then
echo " error"
cat /tmp/deploy.log
else
echo " ok"
fi
done
}
group_cmd "`cat /web/etc/deploy/web_servers`" \
"mkdir -p $site_root && \
cd $site_root && \
$site_root/init stop && \
git pull && \
$site_root/init start"
/web/etc/deploy/web_servers
server1
server2
server3
...
/web/sites/sitename/.deploy
deploy_user="myname"
site_root="/web/sites/sitename"
site_repos="user@server:/path/to/repos"
Just because you can, doesn't mean you should.