Dead simple code deployment

2008-03-04

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.

Next post - OpenWRT and VLANs