# -*- coding: utf-8 -*-
"GraphKit Deployer"
-
import sys
-from functools import wraps
# Deal with the fact that we aren't *really* a Python project,
# so we haven't declared python dependencies.
try:
from fabric.api import *
- from path import path as p # fabric.api.path conflicts
+ from path import path as p # renamed to avoid conflict w/ fabric.api.path
+ import yaml
except ImportError:
print """
ERROR: You're missing a dependency!
To build this project using fabric, you'll need to install fabric (and some other stuff):
- pip install -U fabric path.py
+ pip install -U fabric path.py PyYAML
"""
sys.exit(1)
+from util import *
+
### Fabric Config
env.dist = p('dist')
env.local_tmp = p('tmp')
env.work_dir = env.local_tmp/env.dist
+
env.browserify_js = 'vendor/browserify.js'
env.work_browserify_js = env.work_dir/env.browserify_js
env.vendor_search_dirs = map(p, ['static', 'var', env.work_dir])
env.app_bundle_min = p(env.app_bundle.replace('.js', '.min.js'))
-# Rename to avoid conflicts when we make top-level wrapper tasks
+
+### Setup Staging Environments
+
+# We declare stubs here to use @task and have them show up at the top level
+import stages
+
+@task
+def prod():
+ "Set deploy environment to production."
+
+@task
+def stage():
+ "Set deploy environment to stage."
+ stages.stage()
+
+
+
+### Project Tasks
+
import bundle
import deploy
@task(default=True)
-def gogogo():
+def gogogoo():
""" Bundles and deploys the project. [Default]
"""
bundle.bundle_all()
deploy.full_deploy()
+
#!/usr/bin/env fab
# -*- coding: utf-8 -*-
+"Deploy Bundle Tasks"
from fabric.api import *
from fabric.colors import white, blue, cyan, green, yellow, red, magenta
-from util import *
+from util import *
-### Build Deploy Bundle
@task(default=True)
def bundle_all():
#!/usr/bin/env fab
# -*- coding: utf-8 -*-
+"Deploy Tasks"
+
+from functools import wraps
from fabric.api import *
from fabric.colors import white, blue, cyan, green, yellow, red, magenta
from fabric.contrib.project import rsync_project
+
+import stages
from util import *
-### Deploy Environments
-# There should be a way to do this using stages.
-# See: http://tav.espians.com/fabric-python-with-cleaner-api-and-parallel-deployment-support.html
-# env.config_file = False
-# env.stages = ['prod', 'staging']
+### Helpers
-@task
-def prod():
- """ Set deploy environment to production.
- """
- env.deploy_env = 'prod'
- env.hosts = ['reportcard2.pmtpa.wmflabs']
- env.target_dir = '/srv/reportcard/kraken-ui'
- env.owner = 'www-data'
- env.group = 'www'
-
-@task
-def staging():
- """ Set deploy environment to staging.
- """
- env.deploy_env = 'staging'
- env.hosts = ['less.ly']
- env.target_dir = '/home/wmf/projects/kraken-ui'
- env.user = 'wmf'
- env.owner = 'wmf'
- env.group = 'www'
+def ensure_stage(fn):
+ "Decorator that ensures a stage is set."
+
+ @wraps(fn)
+ def wrapper(*args, **kwargs):
+ if 'deploy_env' not in env:
+ abort(red('You must specify a staging environment (prod, stage) prior to deploy!', bold=True))
+ return fn(*args, **kwargs)
+
+ return wrapper
### Deploy Tasks
@task(default=True)
+@ensure_stage
def full_deploy():
""" Deploy the project.
"""
- pass
+ fix_permissions()
+ update()
+ distribute()
+ fix_permissions()
+ restart_server()
@task
-def fix_permissions():
+@ensure_stage
+def fix_permissions(user=None, group=None):
""" Recursively fixes permissions on the deployment host.
"""
+ if user is None: user = env.owner
+ if group is None: group = env.group
sudo('chmod -R g+w %(target_dir)s' % env)
- sudo('chown -R %(owner)s:%(group)s %(target_dir)s' % env)
+ sudo('chown -R %s:%s %s' % (user, group, env.target_dir))
@task
+@ensure_stage
def update():
""" Runs git pull on the deployment host.
"""
- with cd(env.target_dir):
- run('git pull')
+ with cd(env.target_dir): run('git pull')
@task
+@ensure_stage
def distribute():
""" Copies `dist` package to deployment host.
"""
+ local("rsync -Caz -v %(work_dir)s %(user)s@%(host)s:%(target_dir)s/%(dist)s" % env)
# TODO: make sure the following works.
# rsync_project(local_dir=env.work_dir, remote_dir="%(user)s@%(host)s:%(target_dir)s/%(dist)s" % env)
- local("rsync -Caz -v %(work_dir)s %(user)s@%(host)s:%(target_dir)s/%(dist)s" % env)
@task
+@ensure_stage
def restart_server():
""" Restarts node.js server on the deployment host.
"""
- # need to work on this for less.ly
- sudo("supervisor restart reportcard")
+ sudo("supervisorctl restart reportcard")
--- /dev/null
+#!/usr/bin/env fab
+# -*- coding: utf-8 -*-
+"Setup Staging Environments"
+
+from fabric.api import env
+
+__all__ = ('prod', 'stage',)
+
+# (otto) There should be a way to do this using stages.
+# See: http://tav.espians.com/fabric-python-with-cleaner-api-and-parallel-deployment-support.html
+# (dsc) ...except that most of those changes are not actually in Fabric :(
+
+# env.config_file = False
+# env.stages = ['prod', 'staging']
+
+
+# NOTE WELL: These do not have @task as they'd show up as "stages.prod",
+# and we want them at the top level. See __init__.py for the wrappers.
+# Unfortunately, we can't put them in __init__.py without preventing deploy.py
+# from importing them.
+
+def prod():
+ """ Set deploy environment to production.
+ """
+ env.deploy_env = 'prod'
+ env.hosts = ['reportcard2.pmtpa.wmflabs']
+ env.target_dir = '/srv/reportcard/kraken-ui'
+ env.owner = 'www-data'
+ env.group = 'www'
+
+def stage():
+ """ Set deploy environment to stage.
+ """
+ env.deploy_env = 'stage'
+ env.hosts = ['less.ly']
+ env.target_dir = '/home/wmf/projects/kraken-ui'
+ env.user = 'wmf'
+ env.owner = 'wmf'
+ env.group = 'www'
+
from fabric.api import *
from fabric.colors import white, blue, cyan, green, yellow, red, magenta
-__all__ = ('quietly', 'msg', 'coke', 'update_version',)
+__all__ = ('quietly', 'msg', 'make_wrapper', 'coke', 'update_version',)
@contextmanager
return outer
+
### Misc
def coke(args, capture=False):