def remote_reload_graph(restart=False): if restart: dijkstar('restart') else: # XXX: Only works if `dijkstar serve --workers=1`; if workers is # greater than 1, run `dikstar('restart')` command instead. remote('curl -X POST "http://localhost:8000/reload-graph"')
def upload_docs(config): source = config.docs.build_dir if not source.endswith('/'): source += '/' destination = posixpath.join(config.docs.upload_path, config.package) if not destination.endswith('/'): destination += '/' url = ':'.join((config.domain_name, destination)) print('Uploading {source} to {url}...'.format_map(locals())) local(config, ( 'rsync', '--rsync-path "sudo -u tangled rsync"', '-rltvz --delete', source, url, )) remote(config, ( 'chgrp -R www-data', config.docs.upload_path, '&& chmod -R u=rwX,g=rX,o=', config.docs.upload_path, ), host=config.domain_name, run_as=None, sudo=True)
def reload_uwsgi(config): """Restart uWSGI app process. The uWSGI app process needs to be reloaded after deploying a new version. """ remote(config, '/usr/bin/uwsgi --reload /run/uwsgi/app/tangled/pid')
def push_apache_config(config, enable=True): local(config, ( 'rsync -rltvz', '--rsync-path "sudo rsync"', 'etc/apache2/', '{remote.host}:/etc/apache2', )) if enable: remote(config, 'a2ensite {domain_name}')
def remote_load_osm_data(fetch=True): remote(( 'pwd', './venv/bin/run', '-e', 'production', 'fetch-osm-data' if fetch else None, 'load-osm-data', ), cd='~/current')
def push_uwsgi_config(config, enable=True): """Push uWSGI app config.""" file = config.deploy.uwsgi.config_file link = config.deploy.uwsgi.config_link local(config, ( 'rsync -rltvz', '--rsync-path "sudo rsync"', file.lstrip('/'), ':'.join((config.remote.host, file)), )) if enable: remote(config, ('ln -sf', file, link), run_as=None, sudo=True)
def deploy(host, to='/sites/bycycle.org/current/frontend/', build_=True, clean_=False, overwrite=False, dry_run=False): printer.header(f'Deploying to {host}...') if build_: build(clean_=clean_) printer.info(f'Pushing build/ to {to}...') sync('build/', to, host, run_as='bycycle', delete=overwrite, dry_run=dry_run, echo=True) printer.info(f'Setting ownership of {to}...') remote(('chown -R bycycle:www-data', to), sudo=True)
def deploy(config, version=None, overwrite=False, overwrite_venv=False, install=True, push=True, link=True, reload=True): # Setup ---------------------------------------------------------- if version: config = config.copy(version=version) elif config.get('version'): printer.info('Using default version:', config.version) else: abort(1, 'Version must be specified via config or passed as an option') # Local ---------------------------------------------------------- build_dir = config.build.dir if overwrite and os.path.exists(build_dir): shutil.rmtree(build_dir) os.makedirs(build_dir, exist_ok=True) # Add config files copy_file(config, 'application.wsgi', build_dir, template=True) copy_file(config, 'base.ini', build_dir) copy_file(config, '{env}.ini', build_dir, template=True) copy_file(config, 'commands.py', build_dir) copy_file(config, 'commands.cfg', build_dir) # Create source distributions dist_dir = os.path.abspath(config.build.dist_dir) sdist_command = ('python setup.py sdist --dist-dir', dist_dir) local(config, sdist_command, hide='stdout') for path in config.deploy.sdists: local(config, sdist_command, hide='stdout', cd=path) tarball_name = '{config.version}.tar.gz'.format(config=config) tarball_path = os.path.join(build_dir, tarball_name) with tarfile.open(tarball_path, 'w:gz') as tarball: tarball.add(build_dir, config.version) if push: local(config, ( 'rsync -rltvz', '--rsync-path "sudo -u {deploy.user} rsync"', tarball_path, '{remote.host}:{deploy.root}', )) # Remote ---------------------------------------------------------- deploy_dir_exists = remote(config, 'test -d {deploy.dir}', abort_on_failure=False) if deploy_dir_exists and overwrite: remote(config, 'rm -r {deploy.dir}') remote(config, ('tar -xvzf', tarball_name), cd='{deploy.root}') # Create virtualenv for this version venv_exists = remote(config, 'test -d {deploy.venv}', abort_on_failure=False) if venv_exists and overwrite_venv: remote(config, 'rm -r {deploy.venv}') venv_exists = False if not venv_exists: remote(config, ( 'python{python.version} -m venv {deploy.venv} &&', '{deploy.pip.exe} install', '--cache-dir {deploy.pip.cache_dir}', '--upgrade setuptools pip wheel', )) # Build source if install: remote(config, ( '{deploy.pip.exe}', 'install', '--find-links {deploy.pip.find_links}', '--cache-dir {deploy.pip.cache_dir}', '--disable-pip-version-check', '{package}', ), cd='{deploy.root}', timeout=120) # Make this version the current version if link: remote(config, 'ln -sfn {deploy.dir} {deploy.link}') # Set permissions remote(config, 'chmod -R ug=rwX,o= {deploy.root}') if reload: reload_uwsgi(config)
def remote_create_graph(): remote('./venv/bin/run -e production create-graph', cd='~/current') remote_reload_graph()
def dijkstar(cmd): remote(('systemctl', cmd, 'dijkstar.service'), sudo=True)
def uwsgi(command, raise_on_error=True): remote(('systemctl', command, 'uwsgi.service'), sudo=True, raise_on_error=raise_on_error)
def nginx(cmd, raise_on_error=True): remote(('systemctl', cmd, 'nginx.service'), sudo=True, raise_on_error=raise_on_error)
def deploy(env, host, version=None, build_=True, clean_=True, verbose=False, push=True, overwrite=False, chown=True, chmod=True, link=True, dry_run=False): if env == 'development': abort(1, 'Can\'t deploy to development environment') version = version or git_version() root_dir = f'/sites/{host}/webui' build_dir = f'{root_dir}/builds/{version}' link_path = f'{root_dir}/current' real_run = not dry_run printer.hr( f'{"[DRY RUN] " if dry_run else ""}Deploying version {version} to {env}', color='header') printer.header('Host:', host) printer.header('Remote root directory:', root_dir) printer.header('Remote build directory:', build_dir) printer.header('Remote link to current build:', link_path) printer.header('Steps:') printer.header(f' - {"Cleaning" if clean_ else "Not cleaning"}') printer.header(f' - {"Building" if build_ else "Not building"}') printer.header(f' - {f"Pushing" if push else "Not pushing"}') printer.header(f' - {f"Setting owner" if chown else "Not setting owner"}') printer.header( f' - {f"Setting permissions" if chmod else "Not setting permissions"}' ) if overwrite: printer.warning(f' - Overwriting {build_dir}') printer.header(f' - {"Linking" if link else "Not linking"}') confirm(f'Continue with deployment of version {version} to {env}?', abort_on_unconfirmed=True) if build_: build(env, clean_=clean_, verbose=verbose) if push: remote(f'test -d {build_dir} || mkdir -p {build_dir}') printer.info(f'Pushing public/ to {build_dir}...') sync('public/', f'{build_dir}/', host, delete=overwrite, dry_run=dry_run, echo=verbose) if chown: owner = 'bycycle:www-data' printer.info(f'Setting ownership of {build_dir} to {owner}...') if real_run: remote(('chown', '-R', owner, build_dir), sudo=True) if chmod: mode = 'u=rwX,g=rwX,o=' printer.info(f'Setting permissions on {build_dir} to {mode}...') if real_run: remote(('chmod', '-R', mode, build_dir), sudo=True) if link: printer.info(f'Linking {link_path} to {build_dir}') if real_run: remote(('ln', '-sfn', build_dir, link_path))