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