"""Automated deployment with Fabric. To deploy to production: python3 -m pip install --user vps-deploy export FABRIC_HOSTS=user@hostname fab deploy """ import os from fabric import task # type: ignore from invoke.collection import Collection # type: ignore from patchwork.files import exists from vps_deploy import django_fabric2 as df2 # type: ignore hosts = os.environ['FABRIC_HOSTS'].split(',') def install_essentials(c): # ImageMagick (convert) and Inkscape required for generating badges. c.run('sudo apt-get install -yy git python3-dev python3-venv python3-wheel build-essential python3-cairocffi python3-psycopg2 postgresql uwsgi-emperor uwsgi-plugin-python3 memcached netcat nginx certbot libmemcached-dev xmlsec1 imagemagick inkscape cronic') @task(hosts=hosts) def deploy(c): install_essentials(c) df2.transfer_files_git(c) df2.init(c) if not exists(c, c.env.virtualenv): c.sudo(f'mkdir -p $(dirname {c.env.virtualenv})') c.sudo(f'chown {c.user} $(dirname {c.env.virtualenv})') c.run('{env.python} -m venv --system-site-packages {env.virtualenv}'.format(env=c.env)) with c.cd(c.env.project_dir): c.run('{env.virtualenv}/bin/python -m pip install -c constraints.txt -r requirements.txt'.format(env=c.env)) # Fixes "AttributeError: install_layout". See: # https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1003252 # https://github.com/pypa/setuptools/issues/3278 c.run('SETUPTOOLS_USE_DISTUTILS=stdlib {env.virtualenv}/bin/python -m pip install -c constraints.txt -r vendored_requirements.txt'.format(env=c.env)) df2.prepare_django(c, fail_level='ERROR') df2.fix_permissions( c, read=['pinaxcon', 'vendor', 'static'], read_write=[], ) df2.reload_uwsgi(c) df2.flush_memcached(c) df2.update_nginx(c) df2.install_scheduled_jobs( c, periodic_jobs=[ 'deploy/cron/cron.daily', ], ) df2.check_site_online(c) # The "ns" appears to be a magic name. ns = Collection( deploy, task(df2.download_postgres_db, hosts=hosts), task(df2.mirror_postgres_db, hosts=hosts), task(df2.mirror_media, hosts=hosts), task(df2.django_shell, hosts=hosts), task(df2.bash, hosts=hosts), ) ns.configure({ # Built-in Fabric config. 'run': { 'echo': True, # Needed so local commands work. Can also use FABRIC_RUN_REPLACE_ENV. 'replace_env': False, }, # Our custom project config. 'env': { 'branch': 'fossy2023', 'app_user': 'www-data', 'db_name': 'symposion', 'project_dir': '/srv/symposion_app', 'media_dir': 'media', 'virtualenv': '/srv/venvs/symposion-django-py39', 'site_name': 'symposion', 'requirements': 'requirements.txt', 'settings': 'pinaxcon.settings', 'uwsgi_conf': 'deploy/uwsgi.ini', 'nginx_conf': 'deploy/nginx.conf', 'python': '/usr/bin/python3.9', 'url': 'https://2023.fossy.us/', 'domain': '2023.fossy.us', }, })