eb30a2fdf76665914316f0f0cc4d3d868e5cc49b
[turniej.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 = 'turniej'
13 env.use_south = True
14
15 # Servers
16 def giewont():
17     env.hosts = ['giewont.icm.edu.pl']
18     env.user = 'lektury'
19     env.path = '/srv/turniej.wolnelektury.pl'
20     env.virtualenv = '/usr/bin/virtualenv'
21     # This goes to VHost configuration
22     env.server_name = 'turniej.wolnelektury.pl'
23     env.server_admin = 'Radoslaw Czajka <radoslaw.czajka@nowoczesnapolska.org.pl>'
24     # /var/log/apache2/* logs
25     env.access_log = 'turniej.log'
26     env.error_log = 'turniej-errors.log'
27
28
29 servers = [giewont]
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=servers)
37     require('python', provided_by=[find_python])
38     result = run('cd %(path)s/%(project_name)s; %(python)s manage.py test' % env)
39
40 def setup():
41     """
42     Setup a fresh virtualenv as well as a few useful directories, then run
43     a full deployment. virtualenv with pip should be already installed.
44     """
45     require('hosts', 'path', 'virtualenv', provided_by=servers)
46
47     run('mkdir -p %(path)s; cd %(path)s; %(virtualenv)s ve;' % env, pty=True)
48     run('cd %(path)s; mkdir releases; mkdir packages;' % env, pty=True)
49     run('cd %(path)s/releases; ln -s . current; ln -s . previous' % env, pty=True)
50     upload_default_localsettings()
51     deploy()
52
53 def deploy():
54     """
55     Deploy the latest version of the site to the servers,
56     install any required third party modules,
57     install the virtual host and then restart the webserver
58     """
59
60     import time
61     env.release = time.strftime('%Y-%m-%dT%H%M')
62
63     upload_tar_from_git()
64     find_python()
65     upload_wsgi_script()
66     upload_vhost_sample()
67     install_requirements()
68     copy_localsettings()
69     symlink_current_release()
70     collectstatic()
71     migrate()
72     restart_webserver()
73
74 def deploy_version(version):
75     "Specify a specific version to be made live"
76     require('hosts', 'path', provided_by=servers)
77     env.version = version
78     with cd(env.path):
79         run('rm releases/previous; mv releases/current releases/previous;', pty=True)
80         run('ln -s %(version)s releases/current' % env, pty=True)
81     restart_webserver()
82
83 def rollback():
84     """
85     Limited rollback capability. Simple loads the previously current
86     version of the code. Rolling back again will swap between the two.
87     """
88     require('hosts', 'path', provided_by=servers)
89     with cd(env.path):
90         run('mv releases/current releases/_previous;', pty=True)
91         run('mv releases/previous releases/current;', pty=True)
92         run('mv releases/_previous releases/previous;', pty=True)
93     restart_webserver()
94
95
96 # =====================================================================
97 # = Helpers. These are called by other functions rather than directly =
98 # =====================================================================
99 def upload_tar_from_git():
100     "Create an archive from the current Git branch and upload it"
101     print '>>> upload tar from git'
102     require('path', provided_by=servers)
103     require('release', provided_by=[deploy])
104     local('/bin/bash lib/git-archive-all.sh --format tar %(release)s.tar' % env)
105     local('gzip %(release)s.tar' % 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 find_python():
113     "Finds where virtualenv Python stuff is"
114     print ">>> find Python paths"
115     require('path', provided_by=servers)
116     env.python = '%(path)s/ve/bin/python' % env
117     env.pip = '%(path)s/ve/bin/pip' % env
118     env.site_packages = run('%(python)s -c "from distutils.sysconfig import get_python_lib; print get_python_lib()"' % env)
119
120 def upload_vhost_sample():
121     "Create and upload Apache virtual host configuration sample"
122     print ">>> upload vhost sample"
123     require('path', 'project_name', 'user', provided_by=servers)
124     require('access_log', 'error_log', 'server_admin', 'server_name', provided_by=servers)
125     require('site_packages', provided_by=[find_python])
126     files.upload_template('%(project_name)s.vhost.template' % env, '%(path)s/%(project_name)s.vhost' % env, context=env)
127
128 def upload_wsgi_script():
129     "Create and upload a wsgi script sample"
130     print ">>> upload wsgi script sample"
131     require('path', 'project_name', provided_by=servers)
132     require('python', 'site_packages', provided_by=[find_python])
133     files.upload_template('%(project_name)s.wsgi.template' % env, '%(path)s/%(project_name)s.wsgi' % env, context=env)
134     run('chmod ug+x %(path)s/%(project_name)s.wsgi' % env)
135
136 def install_requirements():
137     "Install the required packages from the requirements file using pip"
138     print '>>> install requirements'
139     require('path', provided_by=servers)
140     require('release', provided_by=[deploy])
141     require('pip', provided_by=[find_python])
142     run('%(pip)s install -r %(path)s/releases/%(release)s/requirements.txt' % env, pty=True)
143
144 def secret_key():
145     """Generates a new SECRET_KEY."""
146     from random import Random
147     import string
148
149     r = Random()
150     return "".join(r.choice(string.printable) for i in range(64))
151
152 def upload_default_localsettings():
153     "Uploads localsettings.py with media paths and stuff"
154     print ">>> upload default localsettings.py"
155     require('path', provided_by=servers)
156
157     env.secret_key = secret_key()
158     files.upload_template('%(project_name)s/localsettings.py.template' % env, '%(path)s/localsettings.py' % env, context=env)
159
160 def copy_localsettings():
161     "Copy localsettings.py from root directory to release directory (if this file exists)"
162     print ">>> copy localsettings"
163     require('path', 'project_name', provided_by=servers)
164     require('release', provided_by=[deploy])
165
166     with settings(warn_only=True):
167         run('cp %(path)s/localsettings.py %(path)s/releases/%(release)s/%(project_name)s' % env)
168
169 def symlink_current_release():
170     "Symlink our current release"
171     print '>>> symlink current release'
172     require('path', provided_by=servers)
173     require('release', provided_by=[deploy])
174     with cd(env.path):
175         run('rm releases/previous; mv releases/current releases/previous')
176         run('ln -s %(release)s releases/current' % env)
177
178 def collectstatic():
179     """Runs collectstatic management command from Django staticfiles."""
180     print '>>> collectstatic'
181     require('path', 'project_name', provided_by=servers)
182     require('python', provided_by=[find_python])
183     with cd('%(path)s/releases/current/%(project_name)s' % env):
184         run('%(python)s manage.py collectstatic --noinput' % env, pty=True)
185
186 def migrate():
187     "Update the database"
188     print '>>> migrate'
189     require('path', 'project_name', provided_by=servers)
190     require('python', provided_by=[find_python])
191     with cd('%(path)s/releases/current/%(project_name)s' % env):
192         run('%(python)s manage.py syncdb --noinput' % env, pty=True)
193         if env.use_south:
194             run('%(python)s manage.py migrate' % env, pty=True)
195
196 def restart_webserver():
197     "Restart the web server"
198     print '>>> restart webserver'
199     require('path', 'project_name', provided_by=servers)
200     run('touch %(path)s/%(project_name)s.wsgi' % env)