From d1a3017172a415919f3335c4e43edd7488ea69b2 Mon Sep 17 00:00:00 2001 From: "Chinmay D. Pai" Date: Sun, 15 Dec 2019 12:06:12 +0530 Subject: [PATCH 01/18] fix(get-app): handle existing directory and other formatting changes * if a directory for the application already exists, provide user with 2 options: * ask to remove the directory and reclone (overwrite) * ask if the user wants to reinstall the application * separate get_app_name from get_app * move building assets and postprocessing to install_app method * make formatting changes to the code for flake8 * use reload_module from six instead of builtins Signed-off-by: Chinmay D. Pai --- bench/app.py | 102 ++++++++++++++++++++++++----------------- bench/commands/make.py | 3 +- 2 files changed, 61 insertions(+), 44 deletions(-) diff --git a/bench/app.py b/bench/app.py index 5becd1eb..ed6cee3d 100755 --- a/bench/app.py +++ b/bench/app.py @@ -4,6 +4,7 @@ from .utils import (exec_cmd, get_frappe, check_git_for_shallow_clone, build_ass restart_supervisor_processes, get_cmd_output, run_frappe_cmd, CommandFailedError, restart_systemd_processes) from .config.common_site_config import get_config +from six import reload_module import logging import requests @@ -14,6 +15,7 @@ import subprocess import bench import sys import shutil +import click logging.basicConfig(level="DEBUG") logger = logging.getLogger(__name__) @@ -50,7 +52,7 @@ def write_appstxt(apps, bench_path='.'): with open(os.path.join(bench_path, 'sites', 'apps.txt'), 'w') as f: return f.write('\n'.join(apps)) -def check_url(url, raise_err = True): +def check_url(url, raise_err=True): try: from urlparse import urlparse except ImportError: @@ -59,7 +61,7 @@ def check_url(url, raise_err = True): parsed = urlparse(url) if not parsed.scheme: if raise_err: - raise TypeError('{url} Not a valid URL'.format(url = url)) + raise TypeError('{url} Not a valid URL'.format(url=url)) else: return False @@ -93,58 +95,64 @@ def remove_from_excluded_apps_txt(app, bench_path='.'): return write_excluded_apps_txt(apps, bench_path=bench_path) def get_app(git_url, branch=None, bench_path='.', build_asset_files=True, verbose=False, - postprocess = True): + postprocess=True, overwrite=False): # from bench.utils import check_url try: from urlparse import urljoin except ImportError: from urllib.parse import urljoin - if not check_url(git_url, raise_err = False): + if not check_url(git_url, raise_err=False): orgs = ['frappe', 'erpnext'] for org in orgs: - url = 'https://api.github.com/repos/{org}/{app}'.format(org = org, app = git_url) + url = 'https://api.github.com/repos/{org}/{app}'.format(org=org, app=git_url) res = requests.get(url) if res.ok: - data = res.json() + data = res.json() if 'name' in data: if git_url == data['name']: - git_url = 'https://github.com/{org}/{app}'.format(org = org, app = git_url) + git_url = 'https://github.com/{org}/{app}'.format(org=org, app=git_url) break - #Gets repo name from URL + # Gets repo name from URL repo_name = git_url.rsplit('/', 1)[1].rsplit('.', 1)[0] - logger.info('getting app {}'.format(repo_name)) shallow_clone = '--depth 1' if check_git_for_shallow_clone() else '' branch = '--branch {branch}'.format(branch=branch) if branch else '' - exec_cmd("git clone {git_url} {branch} {shallow_clone} --origin upstream".format( - git_url=git_url, - shallow_clone=shallow_clone, - branch=branch), - cwd=os.path.join(bench_path, 'apps')) + if os.path.isdir(os.path.join(bench_path, 'apps', repo_name)): + # application directory already exists + # prompt user to overwrite it + if overwrite or click.confirm('''A directory for the application "{0}" already exists. +Do you want to continue and overwrite it?'''): + shutil.rmtree(os.path.join(bench_path, 'apps', repo_name)) + elif click.confirm('''Do you want to reinstall the existing application?''', abort=True): + app_name = get_app_name(bench_path, repo_name) + print("Reinstalling {0}".format(app_name)) + install_app(app=app_name, bench_path=bench_path, verbose=verbose, build_asset_files=build_asset_files) + sys.exit(1) - #Retrieves app name from setup.py + logger.info('Getting app {0}'.format(repo_name)) + exec_cmd("git clone {git_url} {branch} {shallow_clone} --origin upstream".format( + git_url=git_url, + shallow_clone=shallow_clone, + branch=branch), + cwd=os.path.join(bench_path, 'apps')) + + app_name = get_app_name(bench_path, repo_name) + print("Installing {0}".format(app_name)) + install_app(app=app_name, bench_path=bench_path, verbose=verbose, build_asset_files=build_asset_files) + + +def get_app_name(bench_path, repo_name): + # retrieves app name from setup.py app_path = os.path.join(bench_path, 'apps', repo_name, 'setup.py') with open(app_path, 'rb') as f: app_name = re.search(r'name\s*=\s*[\'"](.*)[\'"]', f.read().decode('utf-8')).group(1) if repo_name != app_name: apps_path = os.path.join(os.path.abspath(bench_path), 'apps') os.rename(os.path.join(apps_path, repo_name), os.path.join(apps_path, app_name)) + return app_name - print('installing', app_name) - install_app(app=app_name, bench_path=bench_path, verbose=verbose) - - if postprocess: - - if build_asset_files: - build_assets(bench_path=bench_path, app=app_name) - conf = get_config(bench_path=bench_path) - - if conf.get('restart_supervisor_on_update'): - restart_supervisor_processes(bench_path=bench_path) - if conf.get('restart_systemd_on_update'): - restart_systemd_processes(bench_path=bench_path) def new_app(app, bench_path='.'): # For backwards compatibility @@ -160,7 +168,8 @@ def new_app(app, bench_path='.'): run_frappe_cmd('make-app', apps, app, bench_path=bench_path) install_app(app, bench_path=bench_path) -def install_app(app, bench_path=".", verbose=False, no_cache=False): + +def install_app(app, bench_path=".", verbose=False, no_cache=False, postprocess=True, build_asset_files=True): logger.info("installing {}".format(app)) pip_path = os.path.join(bench_path, "env", "bin", "pip") @@ -168,11 +177,23 @@ def install_app(app, bench_path=".", verbose=False, no_cache=False): app_path = os.path.join(bench_path, "apps", app) cache_flag = "--no-cache-dir" if no_cache else "" - exec_cmd("{pip} install {quiet} -U -e {app} {no_cache}".format(pip=pip_path, quiet=quiet_flag, app=app_path, no_cache=cache_flag)) + exec_cmd("{pip} install {quiet} -U -e {app} {no_cache}".format(pip=pip_path, + quiet=quiet_flag, app=app_path, no_cache=cache_flag)) add_to_appstxt(app, bench_path=bench_path) + if postprocess: + if build_asset_files: + build_assets(bench_path=bench_path, app=app) + conf = get_config(bench_path=bench_path) + + if conf.get('restart_supervisor_on_update'): + restart_supervisor_processes(bench_path=bench_path) + if conf.get('restart_systemd_on_update'): + restart_systemd_processes(bench_path=bench_path) + + def remove_app(app, bench_path='.'): - if not app in get_apps(bench_path): + if app not in get_apps(bench_path): print("No app named {0}".format(app)) sys.exit(1) @@ -281,8 +302,7 @@ def get_current_branch(app, bench_path='.'): def get_remote(app, bench_path='.'): repo_dir = get_repo_dir(app, bench_path=bench_path) - contents = subprocess.check_output(['git', 'remote', '-v'], cwd=repo_dir, - stderr=subprocess.STDOUT) + contents = subprocess.check_output(['git', 'remote', '-v'], cwd=repo_dir, stderr=subprocess.STDOUT) contents = contents.decode('utf-8') if re.findall('upstream[\s]+', contents): return 'upstream' @@ -371,7 +391,7 @@ def switch_branch(branch, apps=None, bench_path='.', upgrade=False, check_upgrad except CommandFailedError: print("Error switching to branch {0} for {1}".format(branch, app)) except InvalidRemoteException: - print("Remote does not exist for app "+app) + print("Remote does not exist for app {0}".format(app)) except InvalidBranchException: print("Branch {0} does not exist in Upstream for {1}".format(branch, app)) @@ -382,11 +402,7 @@ def switch_branch(branch, apps=None, bench_path='.', upgrade=False, check_upgrad update_requirements() update_node_packages() pre_upgrade(version_upgrade[1], version_upgrade[2]) - if sys.version_info >= (3, 4): - import importlib - importlib.reload(utils) - else: - reload(utils) + reload_module(utils) backup_all_sites() patch_sites() build_assets() @@ -402,8 +418,7 @@ def switch_to_develop(apps=None, bench_path='.', upgrade=True): switch_branch('develop', apps=apps, bench_path=bench_path, upgrade=upgrade) def get_version_from_string(contents, field='__version__'): - match = re.search(r"^(\s*%s\s*=\s*['\\\"])(.+?)(['\"])(?sm)" % field, - contents) + match = re.search(r"^(\s*%s\s*=\s*['\\\"])(.+?)(['\"])(?sm)" % field, contents) return match.group(2) def get_major_version(version): @@ -427,7 +442,8 @@ def validate_branch(): branch = get_current_branch(app) if branch == "master": - print(''' master branch is renamed to version-11 and develop to version-12. Please switch to new branches to get future updates. + print('''master branch is renamed to version-11 and develop to version-12. +Please switch to new branches to get future updates. To switch to version 11, run the following commands: bench switch-to-branch version-11''') - sys.exit(1) \ No newline at end of file + sys.exit(1) diff --git a/bench/commands/make.py b/bench/commands/make.py index b3ca8341..dc10515a 100755 --- a/bench/commands/make.py +++ b/bench/commands/make.py @@ -35,10 +35,11 @@ def init(path, apps_path, frappe_path, frappe_branch, no_procfile, no_backups, @click.argument('name', nargs=-1) # Dummy argument for backward compatibility @click.argument('git-url') @click.option('--branch', default=None, help="branch to checkout") +@click.option('--overwrite' is_flag=True) def get_app(git_url, branch, name=None): "clone an app from the internet and set it up in your bench" from bench.app import get_app - get_app(git_url, branch=branch) + get_app(git_url, branch=branch, overwrite=overwrite) @click.command('new-app') From 699705f64b8e549e0a8322a0ea429a5d5361da07 Mon Sep 17 00:00:00 2001 From: "Chinmay D. Pai" Date: Sun, 15 Dec 2019 13:46:14 +0530 Subject: [PATCH 02/18] fix: incorrect import statement use six.moves instead of six Signed-off-by: Chinmay D. Pai --- bench/app.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bench/app.py b/bench/app.py index ed6cee3d..b590fbf3 100755 --- a/bench/app.py +++ b/bench/app.py @@ -4,7 +4,7 @@ from .utils import (exec_cmd, get_frappe, check_git_for_shallow_clone, build_ass restart_supervisor_processes, get_cmd_output, run_frappe_cmd, CommandFailedError, restart_systemd_processes) from .config.common_site_config import get_config -from six import reload_module +from six.moves import reload_module import logging import requests From cac66a6b8811cb55049134ade75a9c8e86f56809 Mon Sep 17 00:00:00 2001 From: "Chinmay D. Pai" Date: Sun, 15 Dec 2019 13:59:12 +0530 Subject: [PATCH 03/18] fix: invalid syntax for click option ughhhhhhhhhh Signed-off-by: Chinmay D. Pai --- bench/commands/make.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bench/commands/make.py b/bench/commands/make.py index dc10515a..c2d27431 100755 --- a/bench/commands/make.py +++ b/bench/commands/make.py @@ -35,7 +35,7 @@ def init(path, apps_path, frappe_path, frappe_branch, no_procfile, no_backups, @click.argument('name', nargs=-1) # Dummy argument for backward compatibility @click.argument('git-url') @click.option('--branch', default=None, help="branch to checkout") -@click.option('--overwrite' is_flag=True) +@click.option('--overwrite', is_flag=True) def get_app(git_url, branch, name=None): "clone an app from the internet and set it up in your bench" from bench.app import get_app From 9107581a562118168ec6820d705e560be367c39b Mon Sep 17 00:00:00 2001 From: Gavin D'souza Date: Wed, 19 Feb 2020 15:33:10 +0530 Subject: [PATCH 04/18] docs: added bench usage docs --- docs/bench_usage.md | 249 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 249 insertions(+) create mode 100644 docs/bench_usage.md diff --git a/docs/bench_usage.md b/docs/bench_usage.md new file mode 100644 index 00000000..1cf71568 --- /dev/null +++ b/docs/bench_usage.md @@ -0,0 +1,249 @@ +# bench CLI Usage + +This may not be known to a lot of people but half the bench commands we're used to, exist in the Frappe Framework and not in bench directly. Those commands generally are the `--site` commands. This page is concerned only with the commands in the bench project. Any framework commands won't be a part of this consolidation. + + +## How are Frappe Framework commands available via bench? + +bench utilizes `frappe.utils.bench_manager` to get the framework's as well as those of any custom commands written in application installed in the Frappe environment. Currently, with *version 12* there are commands related to the scheduler, sites, translations and other utils in Frappe inherited by bench. + + +## Can I add CLI commands in my custom app and call them via bench? + +Along with the framework commands, Frappe's `bench_manager` module also searches for any commands in your custom applications. Thereby, bench communicates with the respective bench's Frappe which in turn checks for available commands in all of the applications. + +To make your custom command available to bench, just create a `commands` module under your parent module and write the command with a click wrapper and a variable commands which contains a list of click functions, which are your own commands. The directory strcuture may be visualized as: + +``` +frappe-bench +|──apps + |── frappe + ├── custom_app + │   ├── README.md + │   ├── custom_app + │   │   ├── commands <------ commands module + │   ├── license.txt + │   ├── requirements.txt + │   └── setup.py +``` + +The commands module maybe a single file such as `commands.py` or a directory with an `__init__.py` file. For a custom application of name 'flags', example may be given as + +```python +# file_path: frappe-bench/apps/flags/flags/commands.py +import click + +@click.command('set-flags') +@click.argument('state', type=click.Choice(['on', 'off'])) +def set_flags(state): + from flags.utils import set_flags + set_flags(state=state) + +commands = [ + set_flags +] +``` + +and with context of the current bench, this command maybe executed simply as + +```zsh +➜ bench set-flags +Flags are set to state: 'on' +``` + +# bench CLI Commands + +Under Click's structure, `bench` is the main command group, under which there are three main groups of commands in bench currently, namely + + - **install**: The install command group deals with commands used to install system dependencies for setting up Frappe environment + + - **setup**: This command group for consists of commands used to maipulate the requirements and environments required by your Frappe environment + + - **config**: The config command group deals with making changes in the current bench (not the CLI tool) configuration + + +## Using the bench command line + +```zsh +➜ bench +Usage: bench [OPTIONS] COMMAND [ARGS]... + + Bench manager for Frappe + +Options: + --version + --help Show this message and exit. + +Commands: + backup Backup single site + backup-all-sites Backup all sites in current bench + config Change bench configuration + disable-production Disables production environment for the bench. + download-translations Download latest translations + exclude-app Exclude app from updating + find Finds benches recursively from location + get-app Clone an app from the internet or filesystem and... +``` + +Similarly, all available flags and options can be checked for commands individually by executing them with the `--help` flag. The `init` command for instance: + +```zsh +➜ bench init --help +Usage: bench init [OPTIONS] PATH + + Initialize a new bench instance in the specified path + +Options: + --python TEXT Path to Python Executable. + --ignore-exist Ignore if Bench instance exists. + --apps_path TEXT path to json files with apps to install + after init +``` + + + +## bench and sudo + +Some bench commands may require sudo, such as some `setup` commands and everything else under the `install` commands group. For these commands, you may not be asked for your root password if sudoers setup has been done. The security implications, well we'll talk about those soon. + + + +## General Commands + +These commands belong directly to the bench group so they can be invoked directly prefixing each with `bench` in your shell. Therefore, the usage for these commands is as + +```zsh + bench COMMAND [ARGS]... +``` + +### The usual commands + + - **init**: Initialize a new bench instance in the specified path + - **restart**: Restart supervisor processes or systemd units. Used in production setup + - **update**: Updates bench tool and if executed in a bench directory, without any flags will backup, pull, setup requirements, build, run patches and restart bench. Using specific flags will only do certain tasks instead of all + - **migrate-env**: Migrate Virtual Environment to desired Python Version + - **retry-upgrade**: Retry a failed upgrade + - **disable-production**: Disables production environment for the bench. + - **renew-lets-encrypt**: Renew Let's Encrypt certificate + - **backup**: Backup single site + - **backup-all-sites**: Backup all sites in current bench + + - **get-app**: Clone an app from the internet or filesystem and set it up in your bench + - **remove-app**: Completely remove app from bench and re-build assets if not installed on any site + - **exclude-app**: Exclude app from updating + - **include-app**: Include app for updating + - **remote-set-url**: Set app remote url + - **remote-reset-url**: Reset app remote url to frappe official + - **remote-urls**: Show apps remote url + - **switch-to-branch**: Switch all apps to specified branch, or specify apps separated by space + - **switch-to-develop**: Switch frappe and erpnext to develop branch + + +### A little advanced + + - **set-nginx-port**: Set NGINX port for site + - **set-ssl-certificate**: Set SSL certificate path for site + - **set-ssl-key**: Set SSL certificate private key path for site + - **set-url-root**: Set URL root for site + - **set-mariadb-host**: Set MariaDB host for bench + - **set-redis-cache-host**: Set Redis cache host for bench + - **set-redis-queue-host**: Set Redis queue host for bench + - **set-redis-socketio-host**: Set Redis socketio host for bench + - **set-default-site**: Set default site for bench + - **download-translations**: Download latest translations + + +### Developer's commands + + - **start**: Start Frappe development processes + - **src**: Prints bench source folder path, which can be used as: cd `bench src` + - **find**: Finds benches recursively from location + - **pip**: For pip help use `bench pip help [COMMAND]` or `bench pip [COMMAND] -h` + - **new-app**: Create a new Frappe application under apps folder + + +### Release bench + - **release**: Release a Frappe application + - **prepare-beta-release**: Prepare major beta release from develop branch + + + +## Setup commands + +The setup commands used for setting up the Frappe environment in context of the current bench need to be executed using `bench setup` as the prefix. So, the general usage of these commands is as + +```zsh + bench setup COMMAND [ARGS]... +``` + + - **sudoers**: Add commands to sudoers list for execution without password + + - **env**: Setup virtualenv for bench + - **redis**: Generates configuration for Redis + - **fonts**: Add Frappe fonts to system + - **config**: Generate or over-write sites/common_site_config.json + - **backups**: Add cronjob for bench backups + - **socketio**: Setup node dependencies for socketio server + - **requirements**: Setup Python and Node dependencies + + - **manager**: Setup bench-manager.local site with the bench_manager app installed on it + + - **procfile**: Generate Procfile for bench start + + - **production**: Setup Frappe production environment for specific user + - **nginx**: Generate configuration files for NGINX + - **fail2ban**: Setup fail2ban, an intrusion prevention software framework that protects computer servers from brute-force attacks + - **systemd**: Generate configuration for systemd + - **firewall**: Setup firewall for system + - **ssh-port**: Set SSH Port for system + - **reload-nginx**: Checks NGINX config file and reloads service + - **supervisor**: Generate configuration for supervisor + - **lets-encrypt**: Setup lets-encrypt SSL for site + - **wildcard-ssl**: Setup wildcard SSL certificate for multi-tenant bench + + - **add-domain**: Add a custom domain to a particular site + - **remove-domain**: Remove custom domain from a site + - **sync-domains**: Check if there is a change in domains. If yes, updates the domains list. + + - **role**: Install dependencies via ansible roles + + + +## Config commands + +The config group commands are used for manipulating configurations in the current bench context. The usage for these commands is as + +```zsh + bench config COMMAND [ARGS]... +``` + + - **set-common-config**: Set value in common config + - **remove-common-config**: Remove specific keys from current bench's common config + + - **update_bench_on_update**: Enable/Disable bench updates on running bench update + - **restart_supervisor_on_update**: Enable/Disable auto restart of supervisor processes + - **restart_systemd_on_update**: Enable/Disable auto restart of systemd units + - **dns_multitenant**: Enable/Disable bench multitenancy on running bench update + - **serve_default_site**: Configure nginx to serve the default site on port 80 + - **http_timeout**: Set HTTP timeout + + + +## Install commands + +The install group commands are used for manipulating system level dependencies. The usage for these commands is as + +```zsh + bench install COMMAND [ARGS]... +``` + + - **prerequisites**: Installs pre-requisite libraries, essential tools like b2zip, htop, screen, vim, x11-fonts, python libs, cups and Redis + - **nodejs**: Installs Node.js v8 + - **nginx**: Installs NGINX. If user is specified, sudoers is setup for that user + - **packer**: Installs Oracle virtualbox and packer 1.2.1 + - **psutil**: Installs psutil via pip + - **mariadb**: Install and setup MariaDB of specified version and root password + - **wkhtmltopdf**: Installs wkhtmltopdf v0.12.3 for linux + - **supervisor**: Installs supervisor. If user is specified, sudoers is setup for that user + - **fail2ban**: Install fail2ban, an intrusion prevention software framework that protects computer servers from brute-force attacks + - **virtualbox**: Installs supervisor From d47e1ac330d27ba363e5594b029f0ef5ce368792 Mon Sep 17 00:00:00 2001 From: "Chinmay D. Pai" Date: Thu, 20 Feb 2020 19:46:40 +0530 Subject: [PATCH 05/18] chore: fix easy_install import print from __future__ for python2 to use print's file param Signed-off-by: Chinmay D. Pai --- playbooks/install.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/playbooks/install.py b/playbooks/install.py index 0da571b5..c40aa579 100644 --- a/playbooks/install.py +++ b/playbooks/install.py @@ -1,5 +1,16 @@ #!/usr/bin/env python3 -import os, sys, subprocess, getpass, json, multiprocessing, shutil, platform, warnings, datetime +from __future__ import print_function +import os +import sys +import subprocess +import getpass +import json +import multiprocessing +import shutil +import platform +import warnings +import datetime + tmp_bench_repo = os.path.join('/', 'tmp', '.bench') tmp_log_folder = os.path.join('/', 'tmp', 'logs') From 0b3feb1f7b93462267f7f593a19799b5aa9bb0e3 Mon Sep 17 00:00:00 2001 From: "Chinmay D. Pai" Date: Thu, 20 Feb 2020 19:55:50 +0530 Subject: [PATCH 06/18] chore: add check for CI Signed-off-by: Chinmay D. Pai --- playbooks/install.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/playbooks/install.py b/playbooks/install.py index c40aa579..174004df 100644 --- a/playbooks/install.py +++ b/playbooks/install.py @@ -405,7 +405,7 @@ def parse_commandline_args(): return args if __name__ == '__main__': - if sys.version[0] == '2': + if sys.version[0] == '2' and not os.environ.get('CI'): if not raw_input("It is recommended to run this script with Python 3\nDo you still wish to continue? [Y/n]: ").lower() == "y": sys.exit() From 986015c13cf5b3ba4612280a232d5de4e890da0b Mon Sep 17 00:00:00 2001 From: "Chinmay D. Pai" Date: Thu, 20 Feb 2020 20:02:35 +0530 Subject: [PATCH 07/18] chore: substitute shutil.which with find_executable on py2 Signed-off-by: Chinmay D. Pai --- playbooks/install.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/playbooks/install.py b/playbooks/install.py index 174004df..614a2087 100644 --- a/playbooks/install.py +++ b/playbooks/install.py @@ -405,9 +405,12 @@ def parse_commandline_args(): return args if __name__ == '__main__': - if sys.version[0] == '2' and not os.environ.get('CI'): - if not raw_input("It is recommended to run this script with Python 3\nDo you still wish to continue? [Y/n]: ").lower() == "y": - sys.exit() + if sys.version[0] == '2': + from disutils.spawn import find_executable + shutil.which = find_executable + if not os.environ.get('CI'): + if not raw_input("It is recommended to run this script with Python 3\nDo you still wish to continue? [Y/n]: ").lower() == "y": + sys.exit() if not is_sudo_user(): log("Please run this script as a non-root user with sudo privileges", level=3) From 0a9effdfb40e57bbba2020977884f3a76d0efeb4 Mon Sep 17 00:00:00 2001 From: "Chinmay D. Pai" Date: Thu, 20 Feb 2020 20:12:28 +0530 Subject: [PATCH 08/18] chore: setup distutils inside travis Signed-off-by: Chinmay D. Pai --- .travis.yml | 2 +- playbooks/install.py | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 9df3b6d4..a44f466b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,7 +5,7 @@ python: - "2.7" install: - - sudo pip install urllib3 pyOpenSSL ndg-httpsclient pyasn1 + - sudo pip install urllib3 pyOpenSSL ndg-httpsclient pyasn1 distutils - sudo apt-get purge -y mysql-common mysql-server mysql-client - sudo apt-get install --only-upgrade -y git - sudo apt-get install hhvm && rm -rf /home/travis/.kiex/ diff --git a/playbooks/install.py b/playbooks/install.py index 614a2087..bc9e4170 100644 --- a/playbooks/install.py +++ b/playbooks/install.py @@ -406,7 +406,12 @@ def parse_commandline_args(): if __name__ == '__main__': if sys.version[0] == '2': - from disutils.spawn import find_executable + try: + from disutils.spawn import find_executable + except ImportError: + print("Please install distutils or use Python3 to run the script") + print("$ pip install distutils") + sys.exit(1) shutil.which = find_executable if not os.environ.get('CI'): if not raw_input("It is recommended to run this script with Python 3\nDo you still wish to continue? [Y/n]: ").lower() == "y": From bf47661f3ed82e381c914eedbff80137818ca91e Mon Sep 17 00:00:00 2001 From: "Chinmay D. Pai" Date: Thu, 20 Feb 2020 20:18:57 +0530 Subject: [PATCH 09/18] chore: setup distutils using apt instead of pip Signed-off-by: Chinmay D. Pai --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index a44f466b..441c0f5a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,10 +5,10 @@ python: - "2.7" install: - - sudo pip install urllib3 pyOpenSSL ndg-httpsclient pyasn1 distutils + - sudo pip install urllib3 pyOpenSSL ndg-httpsclient pyasn1 - sudo apt-get purge -y mysql-common mysql-server mysql-client - sudo apt-get install --only-upgrade -y git - - sudo apt-get install hhvm && rm -rf /home/travis/.kiex/ + - sudo apt-get install hhvm python-distutils && rm -rf /home/travis/.kiex/ - mkdir -p ~/.bench - mkdir -p /tmp/.bench - cp -r $TRAVIS_BUILD_DIR/* ~/.bench From 92d2fbdc1383a524579b5337c0e5233eddf35668 Mon Sep 17 00:00:00 2001 From: gavin Date: Mon, 24 Feb 2020 12:09:24 +0530 Subject: [PATCH 10/18] fix: setup cron job for renewing ssl certificate (#918) * fix: setup cronjob for renewing ssl certificate cronjob set for 1st of every month * fix: cannonical PYPI package name updates refs: - https://pypi.org/project/python-crontab/ - https://github.com/frappe/bench/pull/918#issuecomment-589961301 --- bench/config/lets_encrypt.py | 7 +++---- requirements.txt | 2 +- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/bench/config/lets_encrypt.py b/bench/config/lets_encrypt.py index 45af7b23..4beac157 100755 --- a/bench/config/lets_encrypt.py +++ b/bench/config/lets_encrypt.py @@ -83,11 +83,10 @@ def run_certbot_and_setup_ssl(site, custom_domain, bench_path, interactive=True) def setup_crontab(): job_command = '/opt/certbot-auto renew -a nginx --post-hook "systemctl reload nginx"' - system_crontab = CronTab(tabfile='/etc/crontab', user=True) + system_crontab = CronTab(user='root') if job_command not in str(system_crontab): - job = system_crontab.new(command=job_command, comment="Renew lets-encrypt every month") - job.every().month() - job.enable() + job = system_crontab.new(command=job_command, comment="Renew lets-encrypt every month") + job.day.on(1) system_crontab.write() diff --git a/requirements.txt b/requirements.txt index 5c772902..a9b81fae 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,7 +2,7 @@ Click==7.0 GitPython==2.1.11 honcho==1.0.1 Jinja2==2.10.3 -python_crontab==2.4.0 +python-crontab==2.4.0 requests==2.22.0 semantic_version==2.8.2 setuptools==40.8.0 From 5af3716560138b99717bb965ab41f8aea9df29fd Mon Sep 17 00:00:00 2001 From: Gavin D'souza Date: Mon, 24 Feb 2020 12:51:53 +0530 Subject: [PATCH 11/18] docs: updated and re-link docs --- README.md | 15 +++++-- docs/bench_custom_cmd.md | 48 +++++++++++++++++++++ docs/bench_usage.md | 92 ++++++++++------------------------------ 3 files changed, 81 insertions(+), 74 deletions(-) create mode 100644 docs/bench_custom_cmd.md diff --git a/README.md b/README.md index 394448de..8eb96fed 100755 --- a/README.md +++ b/README.md @@ -15,6 +15,7 @@ bench is a command-line utility that helps you to install apps, manage multiple - [bench CLI](#bench-cli) - [Usage](#usage) - [Installation](#installation) + - [Custom Bench commands](#custom-bench-commands) - [Easy Install Script](#easy-install-script) - [Release Bench](#release-bench) - [Guides](#guides) @@ -49,7 +50,7 @@ Bench is a command line tool that helps you install, setup, manage multiple site * Install apps on a particular site bench --site [site-name] install-app [app-name] - + * Start bench (only for development) bench start @@ -60,7 +61,7 @@ Bench is a command line tool that helps you install, setup, manage multiple site _Note:_ Apart from `bench init`, all other bench commands have to be run having the respective bench directory as the working directory. _(`bench update` may also be run, but it's behaviour is covered in depth in the docs)_ -For more in depth information on commands and usage follow [here](https://github.com/frappe/bench/blob/master/docs/commands_and_usage.md). +For more in depth information on commands and usage follow [here](https://github.com/frappe/bench/blob/master/docs/commands_and_usage.md). As for a consolidated list of bench commands, go through [this page](https://github.com/frappe/bench/blob/master/docs/bench_usage.md). --- @@ -68,8 +69,8 @@ For more in depth information on commands and usage follow [here](https://github To do this install, you must have basic information on how Linux works and should be able to use the command-line. bench will also create nginx and supervisor config files, setup backups and much more. If you are using on a VPS make sure it has >= 1Gb of RAM or has swap setup properly. - git clone https://github.com/frappe/bench ~/.bench - pip3 install --user -e ~/.bench + git clone https://github.com/frappe/bench ~/.bench + pip3 install --user -e ~/.bench As bench is a python application, its installation really depends on `python` + `pip` + `git`. The Frappe Framework, however has various other system dependencies like `nodejs`, `yarn`, `redis` and a database system like `mariadb` or `postgres`. Go through the [installation requirements](https://github.com/frappe/bench/blob/master/docs/installation.md) for an updated list. @@ -77,6 +78,12 @@ If you have questions, please ask them on the [forum](https://discuss.erpnext.co --- +## Custom Bench Commands + +Want to utilize a bench command you've added in your custom Frappe application? [This](https://github.com/frappe/bench/blob/master/docs/bench_custom_cmd.md) guide might be of some help. + +--- + # Easy Install Script - This is an opinionated setup so it is best to setup on a blank server. diff --git a/docs/bench_custom_cmd.md b/docs/bench_custom_cmd.md new file mode 100644 index 00000000..693739ba --- /dev/null +++ b/docs/bench_custom_cmd.md @@ -0,0 +1,48 @@ +## How are Frappe Framework commands available via bench? + +bench utilizes `frappe.utils.bench_manager` to get the framework's as well as those of any custom commands written in application installed in the Frappe environment. Currently, with *version 12* there are commands related to the scheduler, sites, translations and other utils in Frappe inherited by bench. + + +## Can I add CLI commands in my custom app and call them via bench? + +Along with the framework commands, Frappe's `bench_manager` module also searches for any commands in your custom applications. Thereby, bench communicates with the respective bench's Frappe which in turn checks for available commands in all of the applications. + +To make your custom command available to bench, just create a `commands` module under your parent module and write the command with a click wrapper and a variable commands which contains a list of click functions, which are your own commands. The directory strcuture may be visualized as: + +``` +frappe-bench +|──apps + |── frappe + ├── custom_app + │   ├── README.md + │   ├── custom_app + │   │   ├── commands <------ commands module + │   ├── license.txt + │   ├── requirements.txt + │   └── setup.py +``` + +The commands module maybe a single file such as `commands.py` or a directory with an `__init__.py` file. For a custom application of name 'flags', example may be given as + +```python +# file_path: frappe-bench/apps/flags/flags/commands.py +import click + +@click.command('set-flags') +@click.argument('state', type=click.Choice(['on', 'off'])) +def set_flags(state): + from flags.utils import set_flags + set_flags(state=state) + +commands = [ + set_flags +] +``` + +and with context of the current bench, this command maybe executed simply as + +```zsh +➜ bench set-flags +Flags are set to state: 'on' +``` + diff --git a/docs/bench_usage.md b/docs/bench_usage.md index 1cf71568..cf9a0364 100644 --- a/docs/bench_usage.md +++ b/docs/bench_usage.md @@ -3,54 +3,6 @@ This may not be known to a lot of people but half the bench commands we're used to, exist in the Frappe Framework and not in bench directly. Those commands generally are the `--site` commands. This page is concerned only with the commands in the bench project. Any framework commands won't be a part of this consolidation. -## How are Frappe Framework commands available via bench? - -bench utilizes `frappe.utils.bench_manager` to get the framework's as well as those of any custom commands written in application installed in the Frappe environment. Currently, with *version 12* there are commands related to the scheduler, sites, translations and other utils in Frappe inherited by bench. - - -## Can I add CLI commands in my custom app and call them via bench? - -Along with the framework commands, Frappe's `bench_manager` module also searches for any commands in your custom applications. Thereby, bench communicates with the respective bench's Frappe which in turn checks for available commands in all of the applications. - -To make your custom command available to bench, just create a `commands` module under your parent module and write the command with a click wrapper and a variable commands which contains a list of click functions, which are your own commands. The directory strcuture may be visualized as: - -``` -frappe-bench -|──apps - |── frappe - ├── custom_app - │   ├── README.md - │   ├── custom_app - │   │   ├── commands <------ commands module - │   ├── license.txt - │   ├── requirements.txt - │   └── setup.py -``` - -The commands module maybe a single file such as `commands.py` or a directory with an `__init__.py` file. For a custom application of name 'flags', example may be given as - -```python -# file_path: frappe-bench/apps/flags/flags/commands.py -import click - -@click.command('set-flags') -@click.argument('state', type=click.Choice(['on', 'off'])) -def set_flags(state): - from flags.utils import set_flags - set_flags(state=state) - -commands = [ - set_flags -] -``` - -and with context of the current bench, this command maybe executed simply as - -```zsh -➜ bench set-flags -Flags are set to state: 'on' -``` - # bench CLI Commands Under Click's structure, `bench` is the main command group, under which there are three main groups of commands in bench currently, namely @@ -118,25 +70,25 @@ These commands belong directly to the bench group so they can be invoked directl ### The usual commands - - **init**: Initialize a new bench instance in the specified path - - **restart**: Restart supervisor processes or systemd units. Used in production setup - - **update**: Updates bench tool and if executed in a bench directory, without any flags will backup, pull, setup requirements, build, run patches and restart bench. Using specific flags will only do certain tasks instead of all - - **migrate-env**: Migrate Virtual Environment to desired Python Version + - **init**: Initialize a new bench instance in the specified path. This sets up a complete bench folder with an `apps` folder which contains all the Frappe apps available in the current bench, `sites` folder that stores all site data seperated by individual site folders, `config` folder that contains your redis, NGINX and supervisor configuration files. The `env` folder consists of all python dependencies the current bench and installed Frappe applications have. + - **restart**: Restart web, supervisor, systemd processes units. Used in production setup. + - **update**: Updates bench tool and if executed in a bench directory, without any flags will backup, pull, setup requirements, build, run patches and restart bench. Using specific flags will only do certain tasks instead of all. + - **migrate-env**: Migrate Virtual Environment to desired Python version. This regenerates the `env` folder with the specified Python version. - **retry-upgrade**: Retry a failed upgrade - **disable-production**: Disables production environment for the bench. - - **renew-lets-encrypt**: Renew Let's Encrypt certificate - - **backup**: Backup single site - - **backup-all-sites**: Backup all sites in current bench + - **renew-lets-encrypt**: Renew Let's Encrypt certificate for site SSL. + - **backup**: Backup single site data. Can be used to backup files as well. + - **backup-all-sites**: Backup all sites in current bench. - - **get-app**: Clone an app from the internet or filesystem and set it up in your bench - - **remove-app**: Completely remove app from bench and re-build assets if not installed on any site - - **exclude-app**: Exclude app from updating - - **include-app**: Include app for updating + - **get-app**: Download an app from the internet or filesystem and set it up in your bench. This clones the git repo of the Frappe project and installs it in the bench environment. + - **remove-app**: Completely remove app from bench and re-build assets if not installed on any site. + - **exclude-app**: Exclude app from updating during a `bench update` + - **include-app**: Include app for updating. All Frappe applications are included by default when installed. - **remote-set-url**: Set app remote url - **remote-reset-url**: Reset app remote url to frappe official - **remote-urls**: Show apps remote url - **switch-to-branch**: Switch all apps to specified branch, or specify apps separated by space - - **switch-to-develop**: Switch frappe and erpnext to develop branch + - **switch-to-develop**: Switch Frappe and ERPNext to develop branch ### A little advanced @@ -155,15 +107,15 @@ These commands belong directly to the bench group so they can be invoked directl ### Developer's commands - - **start**: Start Frappe development processes - - **src**: Prints bench source folder path, which can be used as: cd `bench src` - - **find**: Finds benches recursively from location - - **pip**: For pip help use `bench pip help [COMMAND]` or `bench pip [COMMAND] -h` - - **new-app**: Create a new Frappe application under apps folder + - **start**: Start Frappe development processes. Uses the Procfile to start the Frappe development environment. + - **src**: Prints bench source folder path, which can be used to cd into the bench installation repository by `cd $(bench src)`. + - **find**: Finds benches recursively from location or specified path. + - **pip**: Use the current bench's pip to manage Python packages. For help about pip usage: `bench pip help [COMMAND]` or `bench pip [COMMAND] -h`. + - **new-app**: Create a new Frappe application under apps folder. ### Release bench - - **release**: Release a Frappe application + - **release**: Create a release of a Frappe application - **prepare-beta-release**: Prepare major beta release from develop branch @@ -176,9 +128,9 @@ The setup commands used for setting up the Frappe environment in context of the bench setup COMMAND [ARGS]... ``` - - **sudoers**: Add commands to sudoers list for execution without password + - **sudoers**: Add commands to sudoers list for allowing bench commands execution without root password - - **env**: Setup virtualenv for bench + - **env**: Setup virtualenv for bench. This sets up a `env` folder under the root of the bench directory. - **redis**: Generates configuration for Redis - **fonts**: Add Frappe fonts to system - **config**: Generate or over-write sites/common_site_config.json @@ -186,11 +138,11 @@ The setup commands used for setting up the Frappe environment in context of the - **socketio**: Setup node dependencies for socketio server - **requirements**: Setup Python and Node dependencies - - **manager**: Setup bench-manager.local site with the bench_manager app installed on it + - **manager**: Setup `bench-manager.local` site with the [Bench Manager](https://github.com/frappe/bench_manager) app, a GUI for bench installed on it. - **procfile**: Generate Procfile for bench start - - **production**: Setup Frappe production environment for specific user + - **production**: Setup Frappe production environment for specific user. This installs ansible, NGINX, supervisor, fail2ban and generates the respective configuration files. - **nginx**: Generate configuration files for NGINX - **fail2ban**: Setup fail2ban, an intrusion prevention software framework that protects computer servers from brute-force attacks - **systemd**: Generate configuration for systemd From 0c0ed767f73738e19692e4ea7667f0be5b7c05b7 Mon Sep 17 00:00:00 2001 From: "Chinmay D. Pai" Date: Tue, 25 Feb 2020 11:45:03 +0530 Subject: [PATCH 12/18] chore: add overwrite flag, repo_name format, and exit gracefully Signed-off-by: Chinmay D. Pai --- bench/app.py | 4 ++-- bench/commands/make.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/bench/app.py b/bench/app.py index b590fbf3..841c3800 100755 --- a/bench/app.py +++ b/bench/app.py @@ -123,13 +123,13 @@ def get_app(git_url, branch=None, bench_path='.', build_asset_files=True, verbos # application directory already exists # prompt user to overwrite it if overwrite or click.confirm('''A directory for the application "{0}" already exists. -Do you want to continue and overwrite it?'''): +Do you want to continue and overwrite it?'''.format(repo_name)): shutil.rmtree(os.path.join(bench_path, 'apps', repo_name)) elif click.confirm('''Do you want to reinstall the existing application?''', abort=True): app_name = get_app_name(bench_path, repo_name) print("Reinstalling {0}".format(app_name)) install_app(app=app_name, bench_path=bench_path, verbose=verbose, build_asset_files=build_asset_files) - sys.exit(1) + sys.exit() logger.info('Getting app {0}'.format(repo_name)) exec_cmd("git clone {git_url} {branch} {shallow_clone} --origin upstream".format( diff --git a/bench/commands/make.py b/bench/commands/make.py index c2d27431..cd7738cd 100755 --- a/bench/commands/make.py +++ b/bench/commands/make.py @@ -36,7 +36,7 @@ def init(path, apps_path, frappe_path, frappe_branch, no_procfile, no_backups, @click.argument('git-url') @click.option('--branch', default=None, help="branch to checkout") @click.option('--overwrite', is_flag=True) -def get_app(git_url, branch, name=None): +def get_app(git_url, branch, overwrite, name=None): "clone an app from the internet and set it up in your bench" from bench.app import get_app get_app(git_url, branch=branch, overwrite=overwrite) From c660593a9ad0a99148a376913c5bec8bd77b675a Mon Sep 17 00:00:00 2001 From: Gavin D'souza Date: Tue, 25 Feb 2020 11:57:28 +0530 Subject: [PATCH 13/18] fix: pin dependencies of requirements --- requirements.txt | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/requirements.txt b/requirements.txt index a9b81fae..d677afd9 100644 --- a/requirements.txt +++ b/requirements.txt @@ -8,3 +8,11 @@ semantic_version==2.8.2 setuptools==40.8.0 six==1.12.0 virtualenv==16.6.0 +gitdb2==2.0.6 +MarkupSafe==1.1.1 +python-dateutil==2.8.1 +idna==2.8 +certifi==2019.9.11 +urllib3==1.25.7 +chardet==3.0.4 +smmap2==2.0.5 From e5b84be5660eba46f0c655821b6dc6a4c1c9e8ac Mon Sep 17 00:00:00 2001 From: "Chinmay D. Pai" Date: Tue, 25 Feb 2020 12:11:24 +0530 Subject: [PATCH 14/18] chore: pin gitdb2 only for python < 3.4 pip allows pinning requirement using environment markers[0] [0]: https://www.python.org/dev/peps/pep-0508/#environment-markers Signed-off-by: Chinmay D. Pai --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index d677afd9..1922bb98 100644 --- a/requirements.txt +++ b/requirements.txt @@ -8,7 +8,7 @@ semantic_version==2.8.2 setuptools==40.8.0 six==1.12.0 virtualenv==16.6.0 -gitdb2==2.0.6 +gitdb2==2.0.6;python_version<'3.4' MarkupSafe==1.1.1 python-dateutil==2.8.1 idna==2.8 From 3bd83da49b32fdc4d91dc3e5ce759a857b3f4a98 Mon Sep 17 00:00:00 2001 From: "Chinmay D. Pai" Date: Wed, 26 Feb 2020 20:00:52 +0530 Subject: [PATCH 15/18] chore: remove redundant print messages Signed-off-by: Chinmay D. Pai --- bench/app.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/bench/app.py b/bench/app.py index 500e8e7b..f9e5b7b5 100755 --- a/bench/app.py +++ b/bench/app.py @@ -127,7 +127,6 @@ Do you want to continue and overwrite it?'''.format(repo_name)): shutil.rmtree(os.path.join(bench_path, 'apps', repo_name)) elif click.confirm('''Do you want to reinstall the existing application?''', abort=True): app_name = get_app_name(bench_path, repo_name) - print("Reinstalling {0}".format(app_name)) install_app(app=app_name, bench_path=bench_path, verbose=verbose, skip_assets=skip_assets) sys.exit() @@ -139,7 +138,6 @@ Do you want to continue and overwrite it?'''.format(repo_name)): cwd=os.path.join(bench_path, 'apps')) app_name = get_app_name(bench_path, repo_name) - print("Installing {0}".format(app_name)) install_app(app=app_name, bench_path=bench_path, verbose=verbose, skip_assets=skip_assets) From 495a038c458834c395519ad5f1a13b684fa16d11 Mon Sep 17 00:00:00 2001 From: gavin Date: Thu, 27 Feb 2020 21:19:20 +0530 Subject: [PATCH 16/18] fix(easy-install): compatibility for easy install on PY2 (#937) * fix: compatibility for easy install on PY2 * test: remove python-distutils from travis * chore: handle specific CalledProcessError for setuptools Co-authored-by: Chinmay Pai --- .travis.yml | 2 +- playbooks/install.py | 18 +++++++++++------- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/.travis.yml b/.travis.yml index 441c0f5a..9df3b6d4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,7 +8,7 @@ install: - sudo pip install urllib3 pyOpenSSL ndg-httpsclient pyasn1 - sudo apt-get purge -y mysql-common mysql-server mysql-client - sudo apt-get install --only-upgrade -y git - - sudo apt-get install hhvm python-distutils && rm -rf /home/travis/.kiex/ + - sudo apt-get install hhvm && rm -rf /home/travis/.kiex/ - mkdir -p ~/.bench - mkdir -p /tmp/.bench - cp -r $TRAVIS_BUILD_DIR/* ~/.bench diff --git a/playbooks/install.py b/playbooks/install.py index bc9e4170..9867d185 100644 --- a/playbooks/install.py +++ b/playbooks/install.py @@ -406,17 +406,21 @@ def parse_commandline_args(): if __name__ == '__main__': if sys.version[0] == '2': - try: - from disutils.spawn import find_executable - except ImportError: - print("Please install distutils or use Python3 to run the script") - print("$ pip install distutils") - sys.exit(1) - shutil.which = find_executable if not os.environ.get('CI'): if not raw_input("It is recommended to run this script with Python 3\nDo you still wish to continue? [Y/n]: ").lower() == "y": sys.exit() + try: + from distutils.spawn import find_executable + except ImportError: + try: + subprocess.check_call('pip install --upgrade setuptools') + except subprocess.CalledProcessError: + print("Install distutils or use Python3 to run the script") + sys.exit(1) + + shutil.which = find_executable + if not is_sudo_user(): log("Please run this script as a non-root user with sudo privileges", level=3) sys.exit() From ddcd2c11a185e28ea653e3f7a1c03d015a63b652 Mon Sep 17 00:00:00 2001 From: gavin Date: Fri, 28 Feb 2020 14:42:14 +0530 Subject: [PATCH 17/18] chore: update GitPython (#938) * Revert "chore: pin gitdb2 only for python < 3.4" * chore: update GitPython and remove second level dependencies --- requirements.txt | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/requirements.txt b/requirements.txt index 1922bb98..e00b90ea 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,18 +1,10 @@ Click==7.0 -GitPython==2.1.11 +GitPython==2.1.15 honcho==1.0.1 Jinja2==2.10.3 python-crontab==2.4.0 requests==2.22.0 -semantic_version==2.8.2 +semantic-version==2.8.2 setuptools==40.8.0 six==1.12.0 virtualenv==16.6.0 -gitdb2==2.0.6;python_version<'3.4' -MarkupSafe==1.1.1 -python-dateutil==2.8.1 -idna==2.8 -certifi==2019.9.11 -urllib3==1.25.7 -chardet==3.0.4 -smmap2==2.0.5 From ec1343c0fae59388a64a22e6289005cb3e7801b2 Mon Sep 17 00:00:00 2001 From: gavin Date: Fri, 28 Feb 2020 15:33:00 +0530 Subject: [PATCH 18/18] fix: dont abort script if not overwriting scripts (#919) * fix: dont abort script if not overwriting scripts why: currently, running of `bench ` or `bench setup production` creates nginx conf files and asks for confirmation before overwriting them. in case user doesnt want to overwrite files, `setup production` and `lets-encrypt` is exitted abrubtly and nginx isnt started again after * fix: use click.confirm instead of six.moves.input * fix: use click.confirm instead of six.moves.input * chore: remove unused imports --- bench/config/nginx.py | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/bench/config/nginx.py b/bench/config/nginx.py index 7e584c3a..9f10c6f7 100644 --- a/bench/config/nginx.py +++ b/bench/config/nginx.py @@ -1,8 +1,24 @@ -import os, json, click, random, string, hashlib -from bench.utils import get_sites, get_bench_name, exec_cmd +# imports - standard imports +import hashlib +import os +import random +import string + +# imports - third party imports +import click from six import string_types +# imports - module imports +from bench.utils import get_bench_name, get_sites + + def make_nginx_conf(bench_path, yes=False): + conf_path = os.path.join(bench_path, "config", "nginx.conf") + + if not yes and os.path.exists(conf_path): + if not click.confirm('nginx.conf already exists and this will overwrite it. Do you want to continue?'): + return + from bench import env from bench.config.common_site_config import get_config @@ -37,10 +53,6 @@ def make_nginx_conf(bench_path, yes=False): nginx_conf = template.render(**template_vars) - conf_path = os.path.join(bench_path, "config", "nginx.conf") - if not yes and os.path.exists(conf_path): - click.confirm('nginx.conf already exists and this will overwrite it. Do you want to continue?', - abort=True) with open(conf_path, "w") as f: f.write(nginx_conf)