Permalink
Browse files

Move fabfile.py, and make it awesomer. This hasn't been tested yet.

  • Loading branch information...
xenith committed May 24, 2012
1 parent da85011 commit 7ac2b49290051f273006161e0959e266d559cf39
Showing with 210 additions and 39 deletions.
  1. +210 −0 fabfile.py
  2. +0 −39 lib/fabric_helpers.py
View
@@ -0,0 +1,210 @@
+"""
+Starter fabfile for deploying the {{ project_name }} project.
+
+Change all the things marked CHANGEME. Other things can be left at their
+defaults if you are happy with the default layout.
+"""
+
+import posixpath
+
+from fabric.api import run, local, env, settings, cd, task
+from fabric.contrib.files import exists
+from fabric.operations import _prefix_commands, _prefix_env_vars
+#from fabric.decorators import runs_once
+#from fabric.context_managers import cd, lcd, settings, hide
+
+# CHANGEME
+env.hosts = ['user@{{ project_name }}.example.com']
+env.code_dir = '/srv/www/{{ project_name }}'
+env.project_dir = '/srv/www/{{ project_name }}/{{ project_name }}'
+env.static_root = '/srv/www/{{ project_name }}/static/'
+env.virtualenv = '/srv/www/{{ project_name }}/.virtualenv'
+env.code_repo = 'git@github.com:user/{{project_name}}.git'
+env.django_settings_module = '{{ project_name }}.settings'
+
+# Python version
+PYTHON_BIN = "python2.7"
+PYTHON_PREFIX = "" # e.g. /usr/local Use "" for automatic
+PYTHON_FULL_PATH = "%s/bin/%s" % (PYTHON_PREFIX, PYTHON_BIN) if PYTHON_PREFIX else PYTHON_BIN
+
+# Set to true if you can restart your webserver (via wsgi.py), false to stop/start your webserver
+# CHANGEME
+DJANGO_SERVER_RESTART = False
+
+
+def virtualenv(venv_dir):
+ """
+ Context manager that establishes a virtualenv to use.
+ """
+ return settings(venv=venv_dir)
+
+
+def run_venv(command, **kwargs):
+ """
+ Runs a command in a virtualenv (which has been specified using
+ the virtualenv context manager
+ """
+ run("source %s/bin/activate" % env.virtualenv + " && " + command, **kwargs)
+
+
+def install_dependencies():
+ ensure_virtualenv()
+ with virtualenv(env.virtualenv):
+ with cd(env.code_dir):
+ run_venv("pip install -r requirements/prod.txt")
+
+
+def ensure_virtualenv():
+ if exists(env.virtualenv):
+ return
+
+ with cd(env.code_dir):
+ run("virtualenv --no-site-packages --python=%s %s" %
+ (PYTHON_BIN, env.virtualenv))
+ run("echo %s > %s/lib/%s/site-packages/projectsource.pth" %
+ (env.project_dir, env.virtualenv, PYTHON_BIN))
+
+
+def ensure_src_dir():
+ if not exists(env.code_dir):
+ run("mkdir -p %s" % env.code_dir)
+ with cd(env.code_dir):
+ if not exists(posixpath.join(env.code_dir, '.git')):
+ run('git clone %s .' % (env.code_repo))
+
+
+def push_sources():
+ """
+ Push source code to server
+ """
+ ensure_src_dir()
+ local('git push origin master')
+ with cd(env.code_dir):
+ run('git pull origin master')
+
+
+@task
+def run_tests():
+ """ Runs the Django test suite as is. """
+ local("./manage.py test")
+
+
+@task
+def version():
+ """ Show last commit to the deployed repo. """
+ with cd(env.code_dir):
+ run('git log -1')
+
+
+@task
+def uname():
+ """ Prints information about the host. """
+ run("uname -a")
+
+
+@task
+def webserver_stop():
+ """
+ Stop the webserver that is running the Django instance
+ """
+ run("service apache2 stop")
+
+
+@task
+def webserver_start():
+ """
+ Starts the webserver that is running the Django instance
+ """
+ run("service apache2 start")
+
+
+@task
+def webserver_restart():
+ """
+ Restarts the webserver that is running the Django instance
+ """
+ if DJANGO_SERVER_RESTART:
+ with cd(env.code_dir):
+ run("touch %s/wsgi.py" % env.project_dir)
+ else:
+ with settings(warn_only=True):
+ webserver_stop()
+ webserver_start()
+
+
+def restart():
+ """ Restart the wsgi process """
+ with cd(env.code_dir):
+ run("touch %s/{{ project_name }}/wsgi.py" % env.code_dir)
+
+
+def build_static():
+ assert env.static_root.strip() != '' and env.static_root.strip() != '/'
+ with virtualenv(env.virtualenv):
+ with cd(env.code_dir):
+ run_venv("./manage.py collectstatic -v 0 --clear --noinput")
+
+ run("chmod -R ugo+r %s" % env.static_root)
+
+
+@task
+def first_deployment_mode():
+ """
+ Use before first deployment to switch on fake south migrations.
+ """
+ env.initial_deploy = True
+
+
+@task
+def update_database(app=None):
+ """
+ Update the database (run the migrations)
+ Usage: fab update_database:app_name
+ """
+ with virtualenv(env.virtualenv):
+ with cd(env.code_dir):
+ if getattr(env, 'initial_deploy', False):
+ run_venv("./manage.py syncdb --all")
+ run_venv("./manage.py migrate --fake --noinput")
+ else:
+ run_venv("./manage.py syncdb --noinput")
+ if app:
+ run_venv("./manage.py migrate %s --noinput" % app)
+ else:
+ run_venv("./manage.py migrate --noinput")
+
+
+@task
+def sshagent_run(cmd):
+ """
+ Helper function.
+ Runs a command with SSH agent forwarding enabled.
+
+ Note:: Fabric (and paramiko) can't forward your SSH agent.
+ This helper uses your system's ssh to do so.
+ """
+ # Handle context manager modifications
+ wrapped_cmd = _prefix_commands(_prefix_env_vars(cmd), 'remote')
+ try:
+ host, port = env.host_string.split(':')
+ return local(
+ "ssh -p %s -A %s@%s '%s'" % (port, env.user, host, wrapped_cmd)
+ )
+ except ValueError:
+ return local(
+ "ssh -A %s@%s '%s'" % (env.user, env.host_string, wrapped_cmd)
+ )
+
+
+@task
+def deploy():
+ """
+ Deploy the project.
+ """
+ with settings(warn_only=True):
+ webserver_stop()
+ push_sources()
+ install_dependencies()
+ update_database()
+ build_static()
+ webserver_start()
View
@@ -1,39 +0,0 @@
-import os
-import string
-from fabric.api import env
-
-_conf_root = os.path.join(
- os.path.dirname(
- os.path.dirname(os.path.abspath(__file__))), 'conf')
-
-_conf_dirs = [x for x in os.listdir(_conf_root)
- if os.path.isdir(os.path.join(_conf_root, x))
- and x != 'base']
-
-def _mk_sethost_fn(host_dicts):
- def inner():
- """ (Autogenerated host connection function.) """
- hoststrings = []
- if env.key_filename == None: env.key_filename = []
- for host in host_dicts:
- hostname = host.get('hostname', '')
- user = host.get('user', '')
- port = host.get('port', '')
- hoststring = '%s%s%s' % (user and user + '@',
- hostname,
- port and ':' + str(port),
- )
- hoststrings.append(hoststring)
- key_filename = host.get('key_filename')
- if key_filename:
- env.key_filename.append(key_filename)
- env.hosts = hoststrings
- return inner
-
-for x in _conf_dirs:
- try:
- module_name = string.join(('conf', x, 'hosts'), '.')
- module = __import__(module_name, fromlist=['hosts',])
- locals()[x] = _mk_sethost_fn(module.hosts)
- except ImportError:
- pass

0 comments on commit 7ac2b49

Please sign in to comment.