old_contents: from io import StringIO
  from fabric.api import *  # noqa
  from fabric.contrib.console import confirm
  
  tool_name = 'wikibugs'
  
  env.hosts = ['tools-login.wmflabs.org']
  env.sudo_user = 'tools.{}'.format(tool_name)
  env.sudo_prefix = 'sudo -ni '
  env.use_ssh_config = True
  
  home_dir = '/data/project/{}'.format(tool_name)
  code_dir = '{}/wikibugs2'.format(home_dir)
  python = '{}/py-wikibugs2/bin/python'.format(home_dir)
  
  jobs = {
      'wb2-phab': '{python} {code_dir}/wikibugs.py',
      'wb2-irc': '{python} {code_dir}/redis2irc.py',
  }
  
  
  def irclog_deploy(message):
      with cd(code_dir):
          sudo('./log_to_irc.py "{}"'.format(message))
  
  
  @task
  def pull():
      with cd(code_dir):
          sudo('git rev-list HEAD --max-count=1')
          sudo('git reset --hard origin/master')
          sudo('git pull')
  
  
  @task
  def crontab():
      with cd(home_dir):
          contents = StringIO(u"""# This crontab was auto-generated by Fabric
  #m   h   dom mon dow cmd
   0   0   *   *   0   /usr/bin/jsub -N taxonomy -mem 512m -once {python} {code_dir}/taxonomy.py > /dev/null
  """.format(**globals())
          )
          put(contents, 'crontab', mode=0o664)
          sudo('crontab crontab')
  
  
  def start_job(name):
      # string formatting as fab doesn't get list-style commands...
      sudo('jstart -N {name} -l release=trusty -mem 1G -once {command}'.format(
          name=name,
          command=jobs[name].format(**globals())
      ))
  
  
  def restart_job(name):
      sudo('qmod -rj {name}'.format(name=name))
  
  
  @task
  def start_jobs():
      with settings(warn_only=True):
          start_job('wb2-phab')
          start_job('wb2-irc')
  
  
  @task
  def deploy(*args):
      if len(args) == 0:
          alljobs = list(jobs.keys())
          if not confirm("No jobs provided, assuming {}. OK?".format(', '.join(alljobs)), default=False):
              abort('No jobs provided. Usage: fab deploy:[job]')
              return
          args = alljobs
      pull()
      for job in args:
          restart_job(job)
      irclog_deploy(', '.join(args))
  
  
  @task
  def grab_config():
      with cd(code_dir):
          get('config.json', '.')
  
new_contents: from io import StringIO
  from fabric.api import *  # noqa
  from fabric.contrib.console import confirm
  
  tool_name = 'wikibugs'
  
  env.hosts = ['tools-login.wmflabs.org']
  env.sudo_user = 'tools.{}'.format(tool_name)
  env.sudo_prefix = 'sudo -ni '
  env.use_ssh_config = True
  
  home_dir = '/data/project/{}'.format(tool_name)
  code_dir = '{}/wikibugs2'.format(home_dir)
  python = '{}/py-wikibugs2/bin/python'.format(home_dir)
  
  jobs = {
      'wb2-phab': '{python} {code_dir}/wikibugs.py',
      'wb2-irc': '{python} {code_dir}/redis2irc.py',
  }
  
  jsub = '/usr/bin/jsub'
  jsub_params = '-l release=trusty '\
                '-mem 1G ' \
                '-once ' \
                '-v PYTHONIOENCODING="utf8:backslashreplace" '
  
  
  def irclog_deploy(message):
      with cd(code_dir):
          sudo('./log_to_irc.py "{}"'.format(message))
  
  
  @task
  def pull():
      with cd(code_dir):
          sudo('git rev-list HEAD --max-count=1')
          sudo('git reset --hard origin/master')
          sudo('git pull')
  
  
  @task
  def crontab():
      with cd(home_dir):
          contents = StringIO(u"""# This crontab was auto-generated by Fabric
  #m   h   dom mon dow cmd
   0   0   *   *   0   {jsub} -N taxonomy {jsub_params} {python} {code_dir}/taxonomy.py > /dev/null
  """.format(**globals())
          )
          put(contents, 'crontab', mode=0o664)
          sudo('crontab crontab')
  
  
  def start_job(name):
      # string formatting as fab doesn't get list-style commands...
      sudo('{jsub} -N {name} {jsub_params} -continuous {command}'.format(
          name=name,
          command=jobs[name].format(**globals())
      ))
  
  
  def restart_job(name):
      sudo('qmod -rj {name}'.format(name=name))
  
  
  @task
  def start_jobs():
      with settings(warn_only=True):
          start_job('wb2-phab')
          start_job('wb2-irc')
  
  
  @task
  def deploy(*args):
      if len(args) == 0:
          alljobs = list(jobs.keys())
          if not confirm("No jobs provided, assuming {}. OK?".format(', '.join(alljobs)), default=False):
              abort('No jobs provided. Usage: fab deploy:[job]')
              return
          args = alljobs
      pull()
      for job in args:
          restart_job(job)
      irclog_deploy(', '.join(args))
  
  
  @task
  def grab_config():
      with cd(code_dir):
          get('config.json', '.')
  
subject: Set PYTHONIOENCODING in jsub