mirror of
https://github.com/frappe/frappe_docker.git
synced 2024-11-08 14:21:05 +00:00
fix: use python for installer script (#1178)
This commit is contained in:
parent
d60e32bce7
commit
d5aae2097d
2
.gitignore
vendored
2
.gitignore
vendored
@ -6,7 +6,7 @@ sites
|
||||
|
||||
development/*
|
||||
!development/README.md
|
||||
!development/installer.sh
|
||||
!development/installer.py
|
||||
!development/apps-example.json
|
||||
!development/vscode-example/
|
||||
|
||||
|
@ -1,15 +1,6 @@
|
||||
{
|
||||
"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"
|
||||
}
|
||||
]
|
||||
}
|
||||
[
|
||||
{
|
||||
"url": "https://github.com/frappe/erpnext.git",
|
||||
"branch": "version-14"
|
||||
}
|
||||
]
|
||||
|
201
development/installer.py
Executable file
201
development/installer.py
Executable file
@ -0,0 +1,201 @@
|
||||
#!/usr/bin/env python3
|
||||
import argparse
|
||||
import os
|
||||
import subprocess
|
||||
|
||||
|
||||
def cprint(*args, level: int = 1):
|
||||
"""
|
||||
logs colorful messages
|
||||
level = 1 : RED
|
||||
level = 2 : GREEN
|
||||
level = 3 : YELLOW
|
||||
|
||||
default level = 1
|
||||
"""
|
||||
CRED = "\033[31m"
|
||||
CGRN = "\33[92m"
|
||||
CYLW = "\33[93m"
|
||||
reset = "\033[0m"
|
||||
message = " ".join(map(str, args))
|
||||
if level == 1:
|
||||
print(CRED, message, reset) # noqa: T001, T201
|
||||
if level == 2:
|
||||
print(CGRN, message, reset) # noqa: T001, T201
|
||||
if level == 3:
|
||||
print(CYLW, message, reset) # noqa: T001, T201
|
||||
|
||||
|
||||
def main():
|
||||
parser = get_args_parser()
|
||||
args = parser.parse_args()
|
||||
init_bench_if_not_exist(args)
|
||||
create_site_in_bench(args)
|
||||
|
||||
|
||||
def get_args_parser():
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument(
|
||||
"-j",
|
||||
"--apps-json",
|
||||
action="store",
|
||||
type=str,
|
||||
help="Path to apps.json, default: apps-example.json",
|
||||
default="apps-example.json",
|
||||
) # noqa: E501
|
||||
parser.add_argument(
|
||||
"-b",
|
||||
"--bench-name",
|
||||
action="store",
|
||||
type=str,
|
||||
help="Bench directory name, default: frappe-bench",
|
||||
default="frappe-bench",
|
||||
) # noqa: E501
|
||||
parser.add_argument(
|
||||
"-s",
|
||||
"--site-name",
|
||||
action="store",
|
||||
type=str,
|
||||
help="Site name, should end with .localhost, default: development.localhost", # noqa: E501
|
||||
default="development.localhost",
|
||||
)
|
||||
parser.add_argument(
|
||||
"-r",
|
||||
"--frappe-repo",
|
||||
action="store",
|
||||
type=str,
|
||||
help="frappe repo to use, default: https://github.com/frappe/frappe", # noqa: E501
|
||||
default="https://github.com/frappe/frappe",
|
||||
)
|
||||
parser.add_argument(
|
||||
"-t",
|
||||
"--frappe-branch",
|
||||
action="store",
|
||||
type=str,
|
||||
help="frappe repo to use, default: version-14", # noqa: E501
|
||||
default="version-14",
|
||||
)
|
||||
parser.add_argument(
|
||||
"-p",
|
||||
"--py-version",
|
||||
action="store",
|
||||
type=str,
|
||||
help="python version, default: Not Set", # noqa: E501
|
||||
default=None,
|
||||
)
|
||||
parser.add_argument(
|
||||
"-n",
|
||||
"--node-version",
|
||||
action="store",
|
||||
type=str,
|
||||
help="node version, default: Not Set", # noqa: E501
|
||||
default=None,
|
||||
)
|
||||
parser.add_argument(
|
||||
"-v",
|
||||
"--verbose",
|
||||
action="store_true",
|
||||
help="verbose output", # noqa: E501
|
||||
)
|
||||
return parser
|
||||
|
||||
|
||||
def init_bench_if_not_exist(args):
|
||||
if os.path.exists(args.bench_name):
|
||||
cprint("Bench already exists. Only site will be created", level=3)
|
||||
return
|
||||
|
||||
try:
|
||||
env = os.environ.copy()
|
||||
if args.py_version:
|
||||
env["PYENV_VERSION"] = args.py_version
|
||||
init_command = ""
|
||||
if args.node_version:
|
||||
init_command = f"nvm use {args.node_version};"
|
||||
if args.py_version:
|
||||
init_command += f"PYENV_VERSION={args.py_version} "
|
||||
init_command += "bench init "
|
||||
init_command += "--skip-redis-config-generation "
|
||||
init_command += "--verbose " if args.verbose else " "
|
||||
init_command += f"--frappe-path={args.frappe_repo} "
|
||||
init_command += f"--frappe-branch={args.frappe_branch} "
|
||||
init_command += f"--apps_path={args.apps_json} "
|
||||
init_command += args.bench_name
|
||||
command = [
|
||||
"/bin/bash",
|
||||
"-i",
|
||||
"-c",
|
||||
init_command,
|
||||
]
|
||||
subprocess.call(command, env=env, cwd=os.getcwd())
|
||||
cprint("Configuring Bench ...", level=2)
|
||||
cprint("Set db_host to mariadb", level=3)
|
||||
subprocess.call(
|
||||
["bench", "set-config", "-g", "db_host", "mariadb"],
|
||||
cwd=os.getcwd() + "/" + args.bench_name,
|
||||
)
|
||||
cprint("Set redis_cache to redis://redis-cache:6379", level=3)
|
||||
subprocess.call(
|
||||
[
|
||||
"bench",
|
||||
"set-config",
|
||||
"-g",
|
||||
"redis_cache",
|
||||
"redis://redis-cache:6379",
|
||||
],
|
||||
cwd=os.getcwd() + "/" + args.bench_name,
|
||||
)
|
||||
cprint("Set redis_queue to redis://redis-queue:6379", level=3)
|
||||
subprocess.call(
|
||||
[
|
||||
"bench",
|
||||
"set-config",
|
||||
"-g",
|
||||
"redis_queue",
|
||||
"redis://redis-queue:6379",
|
||||
],
|
||||
cwd=os.getcwd() + "/" + args.bench_name,
|
||||
)
|
||||
cprint("Set redis_socketio to redis://redis-socketio:6379", level=3)
|
||||
subprocess.call(
|
||||
[
|
||||
"bench",
|
||||
"set-config",
|
||||
"-g",
|
||||
"redis_socketio",
|
||||
"redis://redis-socketio:6379",
|
||||
],
|
||||
cwd=os.getcwd() + "/" + args.bench_name,
|
||||
)
|
||||
cprint("Set developer_mode", level=3)
|
||||
subprocess.call(
|
||||
["bench", "set-config", "-gp", "developer_mode", "1"],
|
||||
cwd=os.getcwd() + "/" + args.bench_name,
|
||||
)
|
||||
except subprocess.CalledProcessError as e:
|
||||
cprint(e.output, level=1)
|
||||
|
||||
|
||||
def create_site_in_bench(args):
|
||||
new_site_cmd = [
|
||||
"bench",
|
||||
"new-site",
|
||||
"--no-mariadb-socket",
|
||||
"--mariadb-root-password=123",
|
||||
"--admin-password=admin",
|
||||
]
|
||||
apps = os.listdir(f"{os.getcwd()}/{args.bench_name}/apps")
|
||||
apps.remove("frappe")
|
||||
for app in apps:
|
||||
new_site_cmd.append(f"--install-app={app}")
|
||||
|
||||
new_site_cmd.append(args.site_name)
|
||||
|
||||
subprocess.call(
|
||||
new_site_cmd,
|
||||
cwd=os.getcwd() + "/" + args.bench_name,
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
@ -1,160 +0,0 @@
|
||||
#!/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" = true ]; 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" = true ] && [ "$app" == "frappe" ]; then
|
||||
init_bench
|
||||
fi
|
||||
if [ "$initialize_bench" = false ]; 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" = false ]; 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: frappe-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 false
|
||||
|
||||
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
|
@ -238,27 +238,38 @@ Most developers work with numerous clients and versions. Moreover, apps may be r
|
||||
|
||||
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).
|
||||
Sample `apps-example.json` is used by default, it installs erpnext on current stable release. To install custom apps, copy the `apps-example.json` to custom json file and make changes to list of apps. Pass this file to the `installer.py` script.
|
||||
|
||||
> 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
|
||||
python installer.py
|
||||
```
|
||||
|
||||
The script will ask for the following information:
|
||||
For command help
|
||||
|
||||
- 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`).
|
||||
```shell
|
||||
python installer.py --help
|
||||
usage: installer.py [-h] [-j APPS_JSON] [-b BENCH_NAME] [-s SITE_NAME] [-r FRAPPE_REPO] [-t FRAPPE_BRANCH] [-p PY_VERSION] [-n NODE_VERSION] [-v]
|
||||
|
||||
options:
|
||||
-h, --help show this help message and exit
|
||||
-j APPS_JSON, --apps-json APPS_JSON
|
||||
Path to apps.json, default: apps-example.json
|
||||
-b BENCH_NAME, --bench-name BENCH_NAME
|
||||
Bench directory name, default: frappe-bench
|
||||
-s SITE_NAME, --site-name SITE_NAME
|
||||
Site name, should end with .localhost, default: development.localhost
|
||||
-r FRAPPE_REPO, --frappe-repo FRAPPE_REPO
|
||||
frappe repo to use, default: https://github.com/frappe/frappe
|
||||
-t FRAPPE_BRANCH, --frappe-branch FRAPPE_BRANCH
|
||||
frappe repo to use, default: version-14
|
||||
-p PY_VERSION, --py-version PY_VERSION
|
||||
python version, default: Not Set
|
||||
-n NODE_VERSION, --node-version NODE_VERSION
|
||||
node version, default: Not Set
|
||||
-v, --verbose verbose output
|
||||
```
|
||||
|
||||
A new bench and / or site is created for the client with following defaults.
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user