Initial commit
[cas.git] / fabfile.py
1 from __future__ import with_statement # needed for python 2.5
2 from fabric.api import *
3 from fabric.contrib import files
4
5 import os
6
7
8 # ==========
9 # = Config =
10 # ==========
11 # Globals
12 env.project_name = 'cas'
13 env.use_south = False
14
15 # Servers
16 def staging():
17     """Use staging server"""
18     env.hosts = ['stigma.nowoczesnapolska.org.pl:2222']
19     env.user = 'platforma'
20     env.path = '/var/services/cas'
21     env.python = '/usr/bin/python'
22     env.virtualenv = '/usr/bin/virtualenv'
23     env.pip = '/usr/bin/pip'
24     
25 def production():
26     """Use production server"""
27     env.hosts = ['wolnelektury.pl:22123']
28     env.user = 'fundacja'
29     env.path = '/opt/lektury/cas'
30     env.python = '/opt/lektury/basevirtualenv/bin/python'
31     env.virtualenv = '/opt/lektury/basevirtualenv/bin/virtualenv'
32     env.pip = '/opt/lektury/basevirtualenv/bin/pip'
33
34
35 # =========
36 # = Tasks =
37 # =========
38 def test():
39     "Run the test suite and bail out if it fails"
40     require('hosts', 'path', provided_by=[staging, production])
41     result = run('cd %(path)s/%(project_name)s; %(python)s manage.py test' % env)
42
43 def setup():
44     """
45     Setup a fresh virtualenv as well as a few useful directories, then run
46     a full deployment. virtualenv and pip should be already installed.
47     """
48     require('hosts', 'path', provided_by=[staging, production])
49
50     run('mkdir -p %(path)s; cd %(path)s; %(virtualenv)s --no-site-packages .;' % env, pty=True)
51     run('cd %(path)s; mkdir releases; mkdir shared; mkdir packages;' % env, pty=True)
52     run('cd %(path)s/releases; ln -s . current; ln -s . previous' % env, pty=True)
53     deploy()
54
55 def deploy():
56     """
57     Deploy the latest version of the site to the servers, 
58     install any required third party modules, 
59     install the virtual host and then restart the webserver
60     """
61     require('hosts', 'path', provided_by=[staging, production])
62
63     import time
64     env.release = time.strftime('%Y-%m-%dT%H%M')
65
66     upload_tar_from_git()
67     upload_wsgi_script()
68     # upload_vhost_sample()
69     install_requirements()
70     copy_localsettings()
71     symlink_current_release()
72     migrate()
73     restart_webserver()
74
75 def deploy_version(version):
76     "Specify a specific version to be made live"
77     require('hosts', 'path', provided_by=[localhost,webserver])
78     env.version = version
79     with cd(env.path):
80         run('rm releases/previous; mv releases/current releases/previous;', pty=True)
81         run('ln -s %(version)s releases/current' % env, pty=True)
82     restart_webserver()
83
84 def rollback():
85     """
86     Limited rollback capability. Simple loads the previously current
87     version of the code. Rolling back again will swap between the two.
88     """
89     require('hosts', provided_by=[staging, production])
90     require('path')
91     with cd(env.path):
92         run('mv releases/current releases/_previous;', pty=True)
93         run('mv releases/previous releases/current;', pty=True)
94         run('mv releases/_previous releases/previous;', pty=True)
95     restart_webserver()
96
97
98 # =====================================================================
99 # = Helpers. These are called by other functions rather than directly =
100 # =====================================================================
101 def upload_tar_from_git():
102     "Create an archive from the current Git master branch and upload it"
103     print '>>> upload tar from git'
104     require('release', provided_by=[deploy])
105     local('git archive --format=tar master | gzip > %(release)s.tar.gz' % env)
106     run('mkdir -p %(path)s/releases/%(release)s' % env, pty=True)
107     run('mkdir -p %(path)s/packages' % env, pty=True)
108     put('%(release)s.tar.gz' % env, '%(path)s/packages/' % env)
109     run('cd %(path)s/releases/%(release)s && tar zxf ../../packages/%(release)s.tar.gz' % env, pty=True)
110     local('rm %(release)s.tar.gz' % env)
111
112 def upload_vhost_sample():
113     "Create and upload Apache virtual host configuration sample"
114     print ">>> upload vhost sample"
115     files.upload_template('%(project_name)s.vhost.template' % env, '%(path)s/%(project_name)s.vhost.sample' % env, context=env)
116
117 def upload_wsgi_script():
118     "Create and upload a wsgi script sample"
119     print ">>> upload wsgi script sample"
120     files.upload_template('%(project_name)s.wsgi.template' % env, '%(path)s/%(project_name)s.wsgi' % env, context=env)
121     run('chmod ug+x %(path)s/%(project_name)s.wsgi' % env)
122
123 def install_requirements():
124     "Install the required packages from the requirements file using pip"
125     print '>>> install requirements'
126     require('release', provided_by=[deploy])
127     run('cd %(path)s; %(pip)s install -E . -r %(path)s/releases/%(release)s/requirements.txt' % env, pty=True)
128
129 def copy_localsettings():
130     "Copy localsettings.py from root directory to release directory (if this file exists)"
131     print ">>> copy localsettings"
132     require('release', provided_by=[deploy])
133     require('path', provided_by=[staging, production])
134
135     with settings(warn_only=True):
136         run('cp %(path)s/localsettings.py %(path)s/releases/%(release)s/%(project_name)s' % env)
137
138 def symlink_current_release():
139     "Symlink our current release"
140     print '>>> symlink current release'
141     require('release', provided_by=[deploy])
142     require('path', provided_by=[staging, production])
143     with cd(env.path):
144         run('rm releases/previous; mv releases/current releases/previous')
145         run('ln -s %(release)s releases/current' % env)
146
147 def migrate():
148     "Update the database"
149     print '>>> migrate'
150     require('project_name', provided_by=[staging, production])
151     with cd('%(path)s/releases/current/%(project_name)s' % env):
152         run('../../../bin/python manage.py syncdb --noinput' % env, pty=True)
153         if env.use_south:
154             run('../../../bin/python manage.py migrate' % env, pty=True)
155
156 def restart_webserver():
157     "Restart the web server"
158     print '>>> restart webserver'
159     run('touch %(path)s/releases/current/%(project_name)s/%(project_name)s.wsgi' % env)