Dopracowanie aplikacji django-sponsors.
[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
9
10 # ===========
11 # = Servers =
12 # ===========
13 def staging():
14     """Use staging server"""
15     env.hosts = ['zuber@stigma.nowoczesnapolska.org.pl:2222']
16     env.path = '/var/lektury'
17     
18 def production():
19     """Use production server"""
20     env.hosts = ['fundacja@wolnelektury:22123']
21     env.path = '/opt/lektury'
22
23
24 # =========
25 # = Tasks =
26 # =========
27 def test():
28     "Run the test suite and bail out if it fails"
29     require('hosts', 'path', provided_by=[staging, production])
30     result = run('cd %(path)s/%(project_name)s; python manage.py test' % env)
31
32 def deploy():
33     """
34     Deploy the latest version of the site to the servers, 
35     install any required third party modules, 
36     install the virtual host and then restart the webserver
37     """
38     require('hosts', 'path', provided_by=[staging, production])
39     
40     import time
41     env.release = time.strftime('%Y-%m-%dT%H%M')
42     
43     upload_tar_from_git()
44     upload_requirements_bundle()
45     install_requirements()
46     symlink_current_release()
47     migrate()
48     restart_webserver()
49
50 def deploy_version(version):
51     "Specify a specific version to be made live"
52     require('hosts', 'path', provided_by=[localhost,webserver])
53     env.version = version
54     with cd(env.path):
55         run('rm releases/previous; mv releases/current releases/previous;', pty=True)
56         run('ln -s %(version)s releases/current' % env, pty=True)
57     restart_webserver()
58
59 def rollback():
60     """
61     Limited rollback capability. Simple loads the previously current
62     version of the code. Rolling back again will swap between the two.
63     """
64     require('hosts', provided_by=[staging, production])
65     require('path')
66     with cd(env.path):
67         run('mv releases/current releases/_previous;', pty=True)
68         run('mv releases/previous releases/current;', pty=True)
69         run('mv releases/_previous releases/previous;', pty=True)
70     restart_webserver()
71     
72 # def setup():
73 #     """
74 #     Setup a fresh virtualenv as well as a few useful directories, then run
75 #     a full deployment
76 #     """
77 #     require('hosts', provided_by=[staging, production])
78 #     require('path')
79 #     sudo('aptitude install -y python-setuptools')
80 #     sudo('easy_install pip')
81 #     sudo('pip install virtualenv')
82 #     sudo('aptitude install -y apache2-threaded')
83 #     sudo('aptitude install -y libapache2-mod-wsgi') # beware, outdated on hardy!
84 #     # we want to get rid of the default apache config
85 #     sudo('cd /etc/apache2/sites-available/; a2dissite default;', pty=True)
86 #     sudo('mkdir -p %(path)s; chown %(user)s:%(user)s %(path)s;' % env, pty=True)
87 #     run('ln -s %(path)s www;' % env, pty=True) # symlink web dir in home
88 #     with cd(env.path):
89 #         run('virtualenv .;' % env, pty=True)
90 #         run('mkdir logs; chmod a+w logs; mkdir releases; mkdir shared; mkdir packages;' % env, pty=True)
91 #         if env.use_photologue: run('mkdir photologue');
92 #         run('cd releases; ln -s . current; ln -s . previous;', pty=True)
93 #     deploy()
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 master branch and upload it"
101     print '>>> upload tar from git'
102     require('release', provided_by=[deploy])
103     local('git archive --format=tar master | gzip > %(release)s.tar.gz' % env)
104     run('mkdir -p %(path)s/releases/%(release)s' % env, pty=True)
105     run('mkdir -p %(path)s/packages' % env, pty=True)
106     put('%(release)s.tar.gz' % env, '%(path)s/packages/' % env)
107     run('cd %(path)s/releases/%(release)s && tar zxf ../../packages/%(release)s.tar.gz' % env, pty=True)
108     local('rm %(release)s.tar.gz' % env)
109
110 def upload_requirements_bundle():
111     "Create a pybundle from requirements.txt file and upload it"
112     print '>>> upload requirements bundle'
113     require('release', provided_by=[deploy])
114     requirements_mtime = os.path.getmtime('requirements.txt')
115     pybundle_mtime = 0
116     try:
117         pybundle_mtime = os.path.getmtime('requirements.pybundle')
118     except os.error:
119         pass
120     if pybundle_mtime < requirements_mtime:
121         pip_options = file('pip-options.txt').read().strip()
122         local('pip bundle %s -r requirements.txt requirements.pybundle' % pip_options)
123     put('requirements.pybundle', '%(path)s/releases/%(release)s' % env)
124
125 def install_requirements():
126     "Install the required packages from the requirements file using pip"
127     print '>>> install requirements'
128     require('release', provided_by=[deploy])
129     with cd('%(path)s/releases/%(release)s' % env):
130         run('virtualenv --no-site-packages .')
131         run('pip install -E . requirements.pybundle')
132
133 def symlink_current_release():
134     "Symlink our current release"
135     print '>>> symlink current release'
136     require('release', provided_by=[deploy])
137     require('path', provided_by=[staging, production])
138     with cd(env.path):
139         with settings(
140             hide('warnings', 'running', 'stdout', 'stderr'),
141             warn_only=True
142         ):
143             run('rm releases/previous; mv releases/current releases/previous;')
144         
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         run('../bin/python manage.py migrate' % env, pty=True)
154
155 def restart_webserver():
156     "Restart the web server"
157     print '>>> restart webserver'
158     run('touch %(path)s/releases/current/%(project_name)s/%(project_name)s.wsgi' % env)
159
160 # def install_site():
161 #     "Add the virtualhost file to apache"
162 #     require('release', provided_by=[deploy, setup])
163 #     #sudo('cd %(path)s/releases/%(release)s; cp %(project_name)s%(virtualhost_path)s%(project_name)s /etc/apache2/sites-available/' % env)
164 #     sudo('cd %(path)s/releases/%(release)s; cp vhost.conf /etc/apache2/sites-available/%(project_name)s' % env)
165 #     sudo('cd /etc/apache2/sites-available/; a2ensite %(project_name)s' % env, pty=True)