Basic fabric file
Language: Python - Created: 5th Feb, 2010
import os
from iangeorge import settings_live
from fabric.api import *
REPO_LOCATION = 'svn://xxxx/xxxxx/x'
SERVER_DEPENDENCIES = (
'python-setuptools',
'libapache2-mod-wsgi',
)
APACHE_CONFIG = """
<VirtualHost *:80>
ServerAdmin %(email)s
ServerName %(url)s
DocumentRoot %(siteroot)s/%(app)s
WSGIScriptAlias / %(siteroot)s/bin/django.wsgi
WSGIDaemonProcess %(domain)s processes=1 threads=10
WSGIProcessGroup %(domain)s
Alias /robots.txt /%(mediaroot)s/text/robots.txt
Alias /favicon.ico /%(mediaroot)s/images/icons/favicon.ico
Alias /media %(mediaroot)s/
<Location "/media">
SetHandler None
</Location>
Alias /admin_media %(siteroot)s/parts/django/django/contrib/admin/media/
<Location "/admin_media">
SetHandler None
</Location>
</VirtualHost>
"""
def production():
"""Stub function, doesn't do anything but must be called before
anything else to set up the environment"""
env.hosts = ['xxxx.xxxxxx.xxx']
env.user = 'xxxx'
env.password = 'xxxxx'
env.app_name = settings_live.APP_NAME
env.repo = {'url': REPO_LOCATION, 'username':'xxxxxx', 'password':'xxxxxxxx'}
env.email = settings_live.ADMINS[0][1]
env.deploy_to = settings_live.PROJECT_PATH
env.deploy_url = settings_live.SITE_URL
env.deploy_media_to = settings_live.MEDIA_ROOT
env.deploy_media_url = settings_live.MEDIA_URL
env.release = current_version()
def check_env():
"""Not really intended for use from the command line, checks if
any env data is set"""
if not 'repo' in env:
raise Exception("No environment set, call production (or another env setting command) before this. e.g.
$fab production deploy")
def current_version():
"""Gets the latest tagged relase number from the svn repository"""
check_env()
cur_vers = local('svn ls --no-auth-cache --username %(u)s --password %(p)s %(repo)s/releases/' % {
'u': env.repo['username'],
'p':env.repo['password'],
'repo':env.repo['url']
}).split('
')
#nasty :( but it works. Removes the trailing slash, splits into int,
#fraction and sorts by int, then fraction and then reverses the
#list.
cur_vers = [v.strip('/').split('.') for v in cur_vers if len(v) > 0]
cur_vers.sort(lambda x, y: cmp(int(x[1]),int(y[1])))
cur_vers.sort(lambda x, y: cmp(int(x[0]),int(y[0])))
cur_vers.reverse()
return ".".join(cur_vers[0])
def tag_release(major_inc=0, minor_inc=1):
"""
Tags the /dev branch as a release using the latest
/release/[version] as a starting point
Args:
maj:amount to increment the major version by, defaults to 0
min:amount to increment the minor version by, defaults to 1
"""
check_env()
print "Current version: %s" % env.release
next_ver = [0]
if '.' in str(env.release):
next_ver = [int(v) for v in env.release.split('.')]
if len(next_ver) < 2:
next_ver.append(0)
if len(next_ver) != 2:
raise Exception('Unknown version: %s, either amend the code to cope with this versioning system or amend the repository structure' % next_ver)
else:
next_ver[0] += major_inc
next_ver[1] += minor_inc
r = ".".join([str(v) for v in next_ver])
print 'Tagging release version %s' % r
run('svn cp --no-auth-cache --username %(user)s --password %(pass)s --message ''Tagging r%(release)s'' %(repo)s/dev %(repo)s/releases/%(release)s' %
{'repo':env.repo['url'], 'release':r, 'user':env.repo['username'], 'pass':env.repo['password']}
)
env.release = r
def deploy_code():
"""
Deploys the current release to the location specified in
settings_live.PROJECT_PATH
"""
print "Ensure directory is in place"
run('mkdir -p %s' % env.deploy_to)
print "Export code to directory"
run('svn export --force --no-auth-cache --username %(u)s --password %(p)s %(repo)s/releases/%(rel)s %(to)s' % {
'u': env.repo['username'],
'p':env.repo['password'],
'repo':env.repo['url'],
'rel':env.release,
'to':env.deploy_to
})
def buildout():
"""Bootstraps zc.buildout, and runs the base config"""
with cd(env.deploy_to):
run('python bootstrap.py -c buildout_base.cfg')
run('bin/buildout -c buildout_base.cfg')
def install_server_dependencies():
run('apt-get update')
run('apt-get install %s' % " ".join(SERVER_DEPENDENCIES))
def setup_site():
"""Adds an entry to sites-enabled with reference to the
bin/django.wsgi created by the django buildout recipe"""
check_env()
install_server_dependencies()
site_config = APACHE_CONFIG % {
'email':env.email,
'url':env.deploy_url,
'domain':env.deploy_url.replace('http://',''),
'siteroot': env.deploy_to,
'app': env.app_name,
'mediaroot':os.path.join(env.deploy_to, env.app_name, env.deploy_media_to)
}
run('rm -f /etc/apache2/sites-enabled/%s' % env.app_name)
run('rm -f /etc/apache2/sites-available/%s' % env.app_name)
run('echo "%s" > /etc/apache2/sites-available/%s' % (site_config, env.app_name))
run('a2ensite %s' % env.app_name)
run('/etc/init.d/apache2 restart')
def database():
"""Currently changes the permissions on the sqlite database and
runs syncdb"""
check_env()
#temp sqlite hack :(
run('chmod 777 %s/db' % env.deploy_to)
with cd(env.deploy_to):
run('bin/django syncdb')
def deploy():
"""Deployment release: deploys or updates site"""
tag_release()
deploy_code()
buildout()
setup_site()
database()
def update():
"""Update site, assumes apache is already set up on the server"""
tag_release()
deploy_code()
buildout()
database()
Copy the address below if you want to share this with someone