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