Skip to content

Instantly share code, notes, and snippets.

@mikedory
Last active December 15, 2015 08:09
Show Gist options
  • Save mikedory/5228351 to your computer and use it in GitHub Desktop.
Save mikedory/5228351 to your computer and use it in GitHub Desktop.
A *better* gist for deploying Django code to a remote server via Git/Fabric and then managing the app via Supervisor — this time with an option for tags and branches. Switch out the "appname" bits and everything in local_settings.py to suit your app's settings.
# import the fabric requirements
from __future__ import with_statement
from fabric.api import *
from fabric.contrib.console import confirm
# import local_settings.py
from gifhq.local_settings import *
"""
Test and prepare everything locally, commit files, and push to Github
This leaves a placeholder for minification as well
"""
# run Django's test framework
def test():
with settings(warn_only=True):
result = local('./manage.py test appname', capture=True)
if result.failed and not confirm("Tests failed! D: Continue anyway?"):
abort("Aborting!")
# add and commit all local files
def commit():
with settings(warn_only=True):
commit = local("git add -p && git commit")
if commit.failed:
print("Nothing to commit. Moving on.")
# push up to github
def push():
local("git push origin master")
def minify():
# this is where one would pack/minify stuff
pass
# run all the pre-flight tests
def prepare_deploy():
minify()
test()
commit()
push()
"""
Deploy to the remote server!
For tags:
fab env deploy:tag=YYYY-MM-DD-tag-description
For branches:
fab deploy:branch=master
So to deploy a tag to production, run:
fab prod deploy:tag=YYYY-MM-DD-tag-description
And to deploy to a single server:
fab -u username -H domain.com -i /path/to/.ssh/id_rsa deploy:tag=YYYY-MM-DD-tag-description
"""
# drop the code off on the remote server
def code_deploy(tag=None, branch=None):
# when deploying by tag
if tag is not None:
# define where this is all going
code_deploy_dir = code_dir_root + "/" + tag
print "*** deploying %s to %s ***" % (tag, code_deploy_dir)
# make the directory, deploy the code, and symlink it
run('mkdir -p %s' % code_deploy_dir)
with cd(code_dir_root):
run("git clone %s %s" % (code_repo, code_deploy_dir))
with cd(code_deploy_dir):
run("git checkout %s" % tag)
with cd(code_dir_root):
run("ln -nfs %s %s" % (code_deploy_dir, code_dir_target))
# when deploying by branch
elif branch is not None:
print "*** deploying %s to %s ***" % (branch, code_dir_target)
# test to make sure the repo exists
with settings(warn_only=True):
if run("test -d %s" % code_dir_target).failed:
run("git clone %s %s" % (code_repo, code_dir_target))
# fetch, checkout, and merge the target branch
with cd(code_dir_target):
run("git fetch")
run("git checkout %s" % branch)
run("git merge origin/%s" % branch)
# gotta have one or the other!
else:
abort("like, seriously. you need a tag or a branch, brah.")
print "*** code deployed ***"
# restart the supervisor process
def supervisor_restart():
# restart processes and clean up
print "*** restarting server ***"
run("supervisorctl restart appname")
# run the code deploy, then restart the supervisor process
@parallel(pool_size=pool_size)
def deploy(tag=None, branch=None):
code_deploy(tag, branch)
supervisor_restart()
# deploy/fabric needs
from fabric.api import *
# deploy directory and repo info
code_dir_root = '/path/to/code/directory'
code_dir_target = '/path/to/code/directory/target'
code_repo = '[email protected]:user/REPO.git'
# how many hosts you want to handle concurrently
pool_size = 5
# remote server configs
def prod():
env.user = 'username'
env.hosts = ['domain.com']
env.key_filename = '/path/to/.ssh/id_rsa'
def staging():
env.user = 'username'
env.hosts = ['domain.com']
env.key_filename = '/path/to/.ssh/id_rsa'
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment