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