From 01bd8f6bb23b0e50c3b27f8aa9924fd0d07f29d2 Mon Sep 17 00:00:00 2001 From: Smit Vora Date: Thu, 3 Nov 2022 12:59:11 +0530 Subject: [PATCH] feat: install client apps using script (#992) * feat: install client apps using script * chore: ignore shellcheck pre-commit --- .gitignore | 2 + devcontainer-example/docker-compose.yml | 2 + development/README.md | 35 ++++++ development/apps-example.json | 15 +++ development/installer.sh | 160 ++++++++++++++++++++++++ 5 files changed, 214 insertions(+) create mode 100644 development/apps-example.json create mode 100755 development/installer.sh diff --git a/.gitignore b/.gitignore index c2005695..9e4c46f9 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,8 @@ sites development/* !development/README.md +!development/installer.sh +!development/apps-example.json !development/vscode-example/ # Pycharm diff --git a/devcontainer-example/docker-compose.yml b/devcontainer-example/docker-compose.yml index 42efdc3f..ea07eb3a 100644 --- a/devcontainer-example/docker-compose.yml +++ b/devcontainer-example/docker-compose.yml @@ -36,6 +36,8 @@ services: - SHELL=/bin/bash volumes: - ..:/workspace:cached + # Enable if you require git cloning + # - ${HOME}/.ssh:/home/frappe/.ssh working_dir: /workspace/development ports: - 8000-8005:8000-8005 diff --git a/development/README.md b/development/README.md index 27d8a9fe..fd4e13a6 100644 --- a/development/README.md +++ b/development/README.md @@ -61,6 +61,8 @@ Notes: ### Setup first bench +> Jump to [scripts](#setup-bench--new-site-using-script) section to setup a bench automatically. Alternatively, you can setup a bench manually using below guide. + Run the following commands in the terminal inside the container. You might need to create a new terminal in VSCode. ```shell @@ -225,6 +227,39 @@ You can now login with user `Administrator` and the password you choose when cre Your website will now be accessible at location [mysite.localhost:8000](http://mysite.localhost:8000) Note: To start bench with debugger refer section for debugging. +### Setup bench / new site using script + +Most developers work with numerous clients and versions. Moreover, apps may be required to be installed by everyone on the team working for a client. + +This is simplified using a script to automate the process of creating a new bench / site and installing the required apps. + +Create a copy of apps-example.json and name it apps.json + +```shell +cp apps-example.json apps.json +``` + +Maintain a directory of all client apps in apps.json. Note that Maintaining a fork is optional in apps.json. Also `name` should be app name in apps.json (could be different from repo name). + +> You may have apps in private repos which may require ssh access. You may use SSH from your home directory on linux (configurable in docker-compose.yml). + +After you have created apps.json, run the following command: + +```shell +bash installer.sh +``` + +The script will ask for the following information: + +- Client name (from apps.json). +- Bench directory name. If you enter existing bench directory name, it will create a new site in that bench. Else it will create a new bench and site. +- Site name (should end with `.localhost`). + +A new bench and / or site is created for the client with following defaults. + +- MariaDB root password: `123` +- Admin password: `admin` + ### Start Frappe with Visual Studio Code Python Debugging To enable Python debugging inside Visual Studio Code, you must first install the `ms-python.python` extension inside the container. This should have already happened automatically, but depending on your VSCode config, you can force it by: diff --git a/development/apps-example.json b/development/apps-example.json new file mode 100644 index 00000000..664efd69 --- /dev/null +++ b/development/apps-example.json @@ -0,0 +1,15 @@ +{ + "client_name": [ + { + "name": "frappe", + "branch": "develop", + "upstream": "git@github.com:frappe/frappe.git", + "fork": "[your fork]" + }, + { + "name": "erpnext", + "branch": "develop", + "upstream": "git@github.com:frappe/erpnext.git" + } + ] +} diff --git a/development/installer.sh b/development/installer.sh new file mode 100755 index 00000000..e0159ae2 --- /dev/null +++ b/development/installer.sh @@ -0,0 +1,160 @@ +#!/bin/bash +# Developer Note: Run this script in the /workspace/development directory + +export NVM_DIR=~/.nvm +# shellcheck disable=SC1091 +source $NVM_DIR/nvm.sh + +sudo apt -qq update && sudo apt -qq install jq -y + +get_client_apps() { + apps=$(jq ".\"$client\"" apps.json) + + if [ "$apps" == "null" ]; then + echo "No apps found for $client" + exit 1 + fi +} + +validate_bench_exists() { + dir="$(pwd)/$bench_name" + if [ -d "$dir" ]; then + echo "Bench already exists. Only site will be created" + is_existing_bench=true + else + is_existing_bench=false + fi +} + +validate_branch() { + if [ "$app" == "frappe" ] || [ "$app" == "erpnext" ]; then + if [ "$branch" != "develop" ] && [ "$branch" != "version-14" ] && [ "$branch" != "version-13" ]; then + echo "Branch should be one of develop or version-14 or version-13" + exit 1 + fi + fi +} + +validate_site() { + if [[ ! "$site_name" =~ ^.*\.localhost$ ]]; then + echo "Site name should end with .localhost" + exit 1 + fi + + if [ "$is_existing_bench" ]; then + validate_site_exists + fi +} + +validate_site_exists() { + dir="$(pwd)/$bench_name/sites/$site_name" + if [ -d "$dir" ]; then + echo "Site already exists. Exiting" + exit 1 + fi +} + +validate_app_exists() { + dir="$(pwd)/apps/$app" + if [ -d "$dir" ]; then + echo "App $app already exists." + is_app_installed=true + else + is_app_installed=false + fi +} + +add_fork() { + dir="$(pwd)/apps/$app" + if [ "$fork" != "null" ]; then + git -C "$dir" remote add fork "$fork" + fi +} + +install_apps() { + initialize_bench=$1 + + for row in $(echo "$apps" | jq -r '.[] | @base64'); do + # helper function to retrieve values from dict + _jq() { + echo "${row}" | base64 --decode | jq -r "${1}" + } + + app=$(_jq '.name') + branch=$(_jq '.branch') + upstream=$(_jq '.upstream') + fork=$(_jq '.fork') + + if [ "$initialize_bench" ] && [ "$app" == "frappe" ]; then + init_bench + fi + if [ ! "$initialize_bench" ]; then + get_apps_from_upstream + fi + done +} + +init_bench() { + echo "Creating bench $bench_name" + + if [ "$branch" == "develop" ] || [ "$branch" == "version-14" ]; then + python_version=python3.10 + PYENV_VERSION=3.10.5 + NODE_VERSION=v16 + elif [ "$branch" == "version-13" ]; then + python_version=python3.9 + PYENV_VERSION=3.9.9 + NODE_VERSION=v14 + fi + + nvm use "$NODE_VERSION" + PYENV_VERSION="$PYENV_VERSION" bench init --skip-redis-config-generation --frappe-branch "$branch" --python "$python_version" "$bench_name" + cd "$bench_name" || exit + + echo "Setting up config" + + bench set-config -g db_host mariadb + bench set-config -g redis_cache redis://redis-cache:6379 + bench set-config -g redis_queue redis://redis-queue:6379 + bench set-config -g redis_socketio redis://redis-socketio:6379 + + ./env/bin/pip install honcho +} + +get_apps_from_upstream() { + validate_app_exists + if [ ! "$is_app_installed" ]; then + bench get-app --branch "$branch" --resolve-deps "$app" "$upstream" && add_fork + fi + + if [ "$app" != "frappe" ]; then + all_apps+=("$app") + fi +} + +echo "Client Name (from apps.json file)?" +read -r client && client=${client:-develop_client} && get_client_apps + +echo "Bench Directory Name? (give name of existing bench to just create a new site) (default: frape-bench)" +read -r bench_name && bench_name=${bench_name:-frappe-bench} && validate_bench_exists + +echo "Site Name? (should end with .localhost) (default: site1.localhost)" +read -r site_name && site_name=${site_name:-site1.localhost} && validate_site + +if [ "$is_existing_bench" == true ]; then + cd "$bench_name" || exit +else + install_apps true +fi + +echo "Getting apps from upstream for $client" +all_apps=() && install_apps + +echo "Creating site $site_name" +bench new-site "$site_name" --mariadb-root-password 123 --admin-password admin --no-mariadb-socket + +echo "Installing apps to $site_name" +bench --site "$site_name" install-app "${all_apps[@]}" + +bench --site "$site_name" set-config developer_mode 1 +bench --site "$site_name" clear-cache