Python code deployment with Fabric

written on Friday, May 6, 2011

So last night at the IndyPy meetup I gave a very impromptu talk on Fabric. It lasted maybe five minutes and afterward I really felt like I just did not do this great tool justice. In order to make up for that, I thought I'd dive in a little deeper to Fabric.

Why I am an idiot

First and foremost, I love Fabric because it lets me be lazy. For far too long while I was developing Yukmarks, I was manually typing things like:

local$ ssh my-ip-address.com
remote$ git pull && sudo /etc/init.d/apache2 restart && ./manage.py dump_data && pg_dump >> foo.txt

That's right:

  1. ssh to my "production" server
  2. pull the latest revisions
  3. use django's built-in data dump to back up my database
  4. also use the postgres dump
  5. not pictured: updating the Haystack search index for Whoosh

You get the picture. It was ugly, and stupid, and time consuming, and I literally cannot believe that I spent all those calories typing those commands in over... and over... and over again.

Why I love Fabric

So then someone introduced me to Fabric. I now use Fabric to automate code deployment. (See my full fabfile here.)

(In no way do I claim to use Fabric to its full potential, nor do I claim to be an expert, nor do I claim that my fabfile is fabulous. If you've got tips or corrections, please leave them in the comments.)

To make Fabric work, you just import the API and you're off:

from fabric.api import *
from hosts import hosts, secret

# I keep my hosts and auth data in a local file called hosts.py
env.password = secret
env.hosts = hosts

def git_pull():
   run("cd %s; . bin/activate; cd %s; git pull; ./manage.py schemamigration"
       " --auto yuk; ./manage.py migrate yuk;cp %s* %s;sudo /etc/init.d/apache2"
       " force-reload" % (domain_dir, appdir, css_dir, static_file_dir))

The above code is exactly what it looks like: a number of semicolon-separated shell commands. It's probably the most idiot-proof, time-saving thing I've ever used. Please see the below:

Curiously, coding in Java while flying an airplane moves both dots toward the center.

Stop typing so much. Fabric makes things ridiculously easy.

Edit 5/8/11: I actually reduced the complexity of my update_index() fabfile function quite a bit. I was doing a lot of really stupid chowning back and forth, which I've now fixed. Old:

def update_search():
    run("cd %s; . bin/activate; cd %s; sudo chown matt:matt %s; sudo chown matt"
    ":matt %s*; ./manage.py update_index; sudo chown www-data:www-data %s; "
    "sudo chown www-data:www-data %s*; sudo /etc/init.d/apache2 force-reloa"
    "d" % (domain_dir, appdir, whoosh_dir,
           whoosh_dir, whoosh_dir, whoosh_dir))

New:

def update_search():
    run("sudo -u www-data /a/mattdeboard.net/bin/python %smanage.py update_inde"
        "x; sudo /etc/init.d/apache2 force-reload" % appdir)

p.s. In addition to Fabric, you'll definitely want to incorporate cron & creative use of your Makefile to make your life easier. Consult the github repo for Yukmarks.

This entry was tagged flask and python