summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarkus Zapke-Grùˆndemann <markus@keimlink.de>2012-01-24 03:26:51 +0100
committerMarkus Zapke-Grùˆndemann <markus@keimlink.de>2012-01-24 03:26:51 +0100
commit3f56ff5bfb09f3cf071d023bab97f606d385a637 (patch)
tree84cff03c9855629a93936be2878e4d0436ea191b
parent1bbb7f7a9ab2096c3e0f3fe3a60bc301bc2d314b (diff)
add fabfile for easy deployment
-rw-r--r--fabfile/__init__.py32
-rw-r--r--fabfile/helpers.py97
-rw-r--r--fabfile/setups.py39
3 files changed, 168 insertions, 0 deletions
diff --git a/fabfile/__init__.py b/fabfile/__init__.py
new file mode 100644
index 0000000..332068c
--- /dev/null
+++ b/fabfile/__init__.py
@@ -0,0 +1,32 @@
+"""subweb deployment package.
+
+Always prefix a task with the appropriate setup.
+
+Examples:
+
+ $ fab setups.stage deploy
+ $ fab setups.production version
+ $ fab setups.prod load_fixture:fixtures/flatpages.json
+"""
+from fabric.api import *
+
+from fabfile import helpers
+from fabfile import setups
+
+
+@task
+def deploy():
+ """Deploys the project.
+
+ Updates the sources, links the appropriate settings, collects the static
+ files and synchronizes/migrates the database.
+
+ Installing/updating Python packages or loading fixtures needs to be done
+ manually.
+ """
+ helpers.update_project()
+ helpers.link_settings()
+ helpers.collect_static()
+ helpers.syncdb()
+ helpers.migrate()
+ # TODO restart application server
diff --git a/fabfile/helpers.py b/fabfile/helpers.py
new file mode 100644
index 0000000..c31461b
--- /dev/null
+++ b/fabfile/helpers.py
@@ -0,0 +1,97 @@
+"""Deployment helpers.
+"""
+from os.path import join as join_path
+
+from fabric.api import *
+from fabric.contrib import files
+
+
+def ve_run(cmd):
+ """Runs a command inside the activated virtualenv.
+ """
+ require('root', provided_by=['setups.stage', 'setups.production'])
+ with prefix('source %(root)s/bin/activate' % env):
+ run(cmd)
+
+
+def manage(cmd):
+ """Runs a command with manage.py.
+ """
+ require('manage_py', provided_by=['setups.stage', 'setups.production'])
+ ve_run('%s %s' % (env.manage_py, cmd))
+
+
+def update_project():
+ """Updates the project source.
+ """
+ require('src_root', provided_by=['setups.stage', 'setups.production'])
+ require('git_branch', provided_by=['setups.stage', 'setups.production'])
+ with cd(env.src_root):
+ run('git pull origin %(git_branch)s' % env)
+
+
+def link_settings():
+ """Links the appropriate settings.
+ """
+ require('stage', provided_by=['setups.stage', 'setups.production'])
+ require('config', provided_by=['setups.stage', 'setups.production'])
+ require('proj_root', provided_by=['setups.stage', 'setups.production'])
+ if env.stage:
+ host_settings = join_path(env.config, '%(host)s_stage.py' % env)
+ else:
+ host_settings = join_path(env.config, '%(host)s.py' % env)
+ settings = join_path(env.proj_root, 'local_settings.py')
+ if files.exists(settings):
+ run('rm %s' % settings)
+ if files.exists(host_settings):
+ run('ln -s %s %s' % (host_settings, settings))
+ else:
+ print 'No host specific settings file found. Create one at %s' % host_settings
+
+
+def collect_static():
+ """Collects all static files.
+ """
+ manage('collectstatic')
+
+
+@task
+def syncdb():
+ """Runs the syncdb management command.
+ """
+ manage('syncdb')
+
+
+@task
+def migrate(app_name=None):
+ """Runs the migrations for one or all apps.
+ """
+ manage('migrate %s' % app_name)
+
+
+@task(alias='id')
+def indetify():
+ """Identifes the deployed project.
+
+ Displays the deployed project version, all Python packages installed inside
+ the virtualenv and the state of the migrations.
+ """
+ require('proj_root', provided_by=['setups.stage', 'setups.production'])
+ with cd(env.proj_root):
+ run('git log -1')
+ ve_run('pip freeze')
+ manage('migrate -list')
+
+
+@task(alias='install')
+def install_requirements():
+ """Installs the requirements.
+ """
+ require('pip_file', provided_by=['setups.stage', 'setups.production'])
+ ve_run('pip install -r %(pip_file)s' % env)
+
+
+@task(alias='load')
+def load_fixture(fixture_path):
+ """Loads one or more fixtures."""
+ manage('loaddata %s' % fixture_path)
diff --git a/fabfile/setups.py b/fabfile/setups.py
new file mode 100644
index 0000000..f4d1de8
--- /dev/null
+++ b/fabfile/setups.py
@@ -0,0 +1,39 @@
+"""Setups to deploy to.
+"""
+from os.path import join as join_path
+
+from fabric.api import *
+
+
+@task
+def stage():
+ """Defines stage setup.
+ """
+ env.stage = True
+ env.git_branch = 'master'
+ env.hosts = ['oberon.sublab.org']
+ env.home = '/home/subweb'
+ env.root = join_path(env.home, 'stage')
+ finalize()
+
+
+@task(alias='prod')
+def production():
+ """Defines production setup.
+ """
+ env.stage = False
+ env.git_branch = 'master'
+ env.hosts = ['oberon.sublab.org']
+ env.home = '/home/subweb'
+ env.root = join_path(env.home, 'production')
+ finalize()
+
+
+def finalize():
+ """Performs the final setup.
+ """
+ env.config = join_path(env.home, 'config')
+ env.src_root = join_path(env.root, 'subweb')
+ env.pip_file = join_path(env.src_root, 'requirements.txt')
+ env.proj_root = join_path(env.src_root, 'sublab_project')
+ env.manage_py = join_path(env.proj_root, 'manage.py')