[ADD]Devcontainer template
This commit is contained in:
32
devcontainer/devcontainer.json
Normal file
32
devcontainer/devcontainer.json
Normal file
@@ -0,0 +1,32 @@
|
||||
{
|
||||
"name": "Frappe Bench",
|
||||
"forwardPorts": [8000, 9000, 6787],
|
||||
"remoteUser": "frappe",
|
||||
"customizations": {
|
||||
"vscode": {
|
||||
"extensions": [
|
||||
"ms-python.python",
|
||||
"ms-vscode.live-server",
|
||||
"grapecity.gc-excelviewer",
|
||||
"mtxr.sqltools",
|
||||
"visualstudioexptteam.vscodeintellicode"
|
||||
],
|
||||
"settings": {
|
||||
"terminal.integrated.profiles.linux": {
|
||||
"frappe bash": {
|
||||
"path": "/bin/bash"
|
||||
}
|
||||
},
|
||||
"terminal.integrated.defaultProfile.linux": "frappe bash",
|
||||
"debug.node.autoAttach": "disabled"
|
||||
}
|
||||
}
|
||||
},
|
||||
"dockerComposeFile": "./docker-compose.yml",
|
||||
"service": "frappe",
|
||||
"workspaceFolder": "/workspace/development",
|
||||
"shutdownAction": "stopCompose",
|
||||
"mounts": [
|
||||
"source=${localEnv:HOME}${localEnv:USERPROFILE}/.ssh,target=/home/frappe/.ssh,type=bind,consistency=cached"
|
||||
]
|
||||
}
|
||||
90
devcontainer/docker-compose.yml
Normal file
90
devcontainer/docker-compose.yml
Normal file
@@ -0,0 +1,90 @@
|
||||
version: "3.7"
|
||||
services:
|
||||
mariadb:
|
||||
image: docker.io/mariadb:11.8
|
||||
command:
|
||||
- --character-set-server=utf8mb4
|
||||
- --collation-server=utf8mb4_unicode_ci
|
||||
- --skip-character-set-client-handshake
|
||||
- --skip-innodb-read-only-compressed # Temporary fix for MariaDB 10.6
|
||||
environment:
|
||||
MYSQL_ROOT_PASSWORD: 123
|
||||
MARIADB_AUTO_UPGRADE: 1
|
||||
volumes:
|
||||
- mariadb-data:/var/lib/mysql
|
||||
|
||||
# Enable PostgreSQL only if you use it, see development/README.md for more information.
|
||||
# postgresql:
|
||||
# image: postgres:14
|
||||
# environment:
|
||||
# POSTGRES_PASSWORD: 123
|
||||
# volumes:
|
||||
# - postgresql-data:/var/lib/postgresql/data
|
||||
|
||||
# Enable Mailpit if you need to test outgoing mail services
|
||||
# See https://mailpit.axllent.org/
|
||||
# mailpit:
|
||||
# image: axllent/mailpit
|
||||
# volumes:
|
||||
# - mailpit-data:/data
|
||||
# ports:
|
||||
# - 8025:8025
|
||||
# - 1025:1025
|
||||
# environment:
|
||||
# MP_MAX_MESSAGES: 5000
|
||||
# MP_DATA_FILE: /data/mailpit.db
|
||||
# MP_SMTP_AUTH_ACCEPT_ANY: 1
|
||||
# MP_SMTP_AUTH_ALLOW_INSECURE: 1
|
||||
|
||||
redis-cache:
|
||||
image: docker.io/redis:alpine
|
||||
|
||||
redis-queue:
|
||||
image: docker.io/redis:alpine
|
||||
|
||||
frappe:
|
||||
image: docker.io/frappe/bench:latest
|
||||
# If you want to build the current bench image the Containerfile is in this Repo.
|
||||
# build: ../images/bench
|
||||
command: sleep infinity
|
||||
environment:
|
||||
- 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
|
||||
- 9000-9005:9000-9005
|
||||
# enable the below service if you need Cypress UI Tests to be executed
|
||||
# Before enabling ensure install_x11_deps.sh has been executed and display variable is exported.
|
||||
# Run install_x11_deps.sh again if DISPLAY is not set
|
||||
# ui-tester:
|
||||
# # pass custom command to start Cypress otherwise it will use the entrypoint
|
||||
# # specified in the Cypress Docker image.
|
||||
# # also pass "--project <folder>" so that when Cypress opens
|
||||
# # it can find file "cypress.json" and show integration specs
|
||||
# # https://on.cypress.io/command-line#cypress-open
|
||||
# entrypoint: 'sleep infinity'
|
||||
# image: "docker.io/cypress/included:latest"
|
||||
# environment:
|
||||
# - SHELL=/bin/bash
|
||||
# # get the IP address of the host machine and allow X11 to accept
|
||||
# # incoming connections from that IP address
|
||||
# # IP=$(ipconfig getifaddr en0) or mac or \
|
||||
# # IP=$($(hostname -I | awk '{print $1}') ) for Ubuntu
|
||||
# # /usr/X11/bin/xhost + $IP
|
||||
# # then pass the environment variable DISPLAY to show Cypress GUI on the host system
|
||||
# # DISPLAY=$IP:0
|
||||
# - DISPLAY
|
||||
# volumes:
|
||||
# # for Cypress to communicate with the X11 server pass this socket file
|
||||
# # in addition to any other mapped volumes
|
||||
# - /tmp/.X11-unix:/tmp/.X11-unix
|
||||
# - ..:/workspace:z,cached
|
||||
# network_mode: "host"
|
||||
volumes:
|
||||
mariadb-data:
|
||||
#postgresql-data:
|
||||
#mailpit-data:
|
||||
77
development/.vscode/launch.json
vendored
Normal file
77
development/.vscode/launch.json
vendored
Normal file
@@ -0,0 +1,77 @@
|
||||
{
|
||||
// Use IntelliSense to learn about possible attributes.
|
||||
// Hover to view descriptions of existing attributes.
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Bench Web",
|
||||
"type": "debugpy",
|
||||
"request": "launch",
|
||||
"program": "${workspaceFolder}/frappe-bench/apps/frappe/frappe/utils/bench_helper.py",
|
||||
"args": [
|
||||
"frappe",
|
||||
"serve",
|
||||
"--port",
|
||||
"8000",
|
||||
"--noreload",
|
||||
"--nothreading"
|
||||
],
|
||||
"cwd": "${workspaceFolder}/frappe-bench/sites",
|
||||
"env": {
|
||||
"DEV_SERVER": "1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Bench Short Worker",
|
||||
"type": "debugpy",
|
||||
"request": "launch",
|
||||
"program": "${workspaceFolder}/frappe-bench/apps/frappe/frappe/utils/bench_helper.py",
|
||||
"args": ["frappe", "worker", "--queue", "short"],
|
||||
"cwd": "${workspaceFolder}/frappe-bench/sites",
|
||||
"env": {
|
||||
"DEV_SERVER": "1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Bench Default Worker",
|
||||
"type": "debugpy",
|
||||
"request": "launch",
|
||||
"program": "${workspaceFolder}/frappe-bench/apps/frappe/frappe/utils/bench_helper.py",
|
||||
"args": ["frappe", "worker", "--queue", "default"],
|
||||
"cwd": "${workspaceFolder}/frappe-bench/sites",
|
||||
"env": {
|
||||
"DEV_SERVER": "1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Bench Long Worker",
|
||||
"type": "debugpy",
|
||||
"request": "launch",
|
||||
"program": "${workspaceFolder}/frappe-bench/apps/frappe/frappe/utils/bench_helper.py",
|
||||
"args": ["frappe", "worker", "--queue", "long"],
|
||||
"cwd": "${workspaceFolder}/frappe-bench/sites",
|
||||
"env": {
|
||||
"DEV_SERVER": "1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Honcho SocketIO Watch Schedule Worker",
|
||||
"type": "debugpy",
|
||||
"request": "launch",
|
||||
"python": "/home/frappe/.pyenv/shims/python",
|
||||
"program": "/home/frappe/.local/bin/honcho",
|
||||
"cwd": "${workspaceFolder}/frappe-bench",
|
||||
"console": "internalConsole",
|
||||
"args": ["start", "socketio", "watch", "schedule", "worker"],
|
||||
"postDebugTask": "Clean Honcho SocketIO Watch Schedule Worker"
|
||||
}
|
||||
],
|
||||
"compounds": [
|
||||
{
|
||||
"name": "Honcho + Web debug",
|
||||
"configurations": ["Bench Web", "Honcho SocketIO Watch Schedule Worker"],
|
||||
"stopAll": true
|
||||
}
|
||||
]
|
||||
}
|
||||
3
development/.vscode/settings.json
vendored
Normal file
3
development/.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"python.defaultInterpreterPath": "${workspaceFolder}/frappe-bench/env/bin/python"
|
||||
}
|
||||
22
development/.vscode/tasks.json
vendored
Normal file
22
development/.vscode/tasks.json
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
{
|
||||
// See https://go.microsoft.com/fwlink/?LinkId=733558
|
||||
// for the documentation about the tasks.json format
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"label": "Clean Honcho SocketIO Watch Schedule Worker",
|
||||
"detail": "When stopping the debug process from vscode window, the honcho won't receive the SIGINT signal. This task will send the SIGINT signal to the honcho processes.",
|
||||
"type": "shell",
|
||||
"command": "pkill -SIGINT -f bench; pkill -SIGINT -f socketio",
|
||||
"isBackground": false,
|
||||
"presentation": {
|
||||
"echo": true,
|
||||
"reveal": "silent",
|
||||
"focus": false,
|
||||
"panel": "shared",
|
||||
"showReuseMessage": false,
|
||||
"close": true
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
6
development/apps-example.json
Normal file
6
development/apps-example.json
Normal file
@@ -0,0 +1,6 @@
|
||||
[
|
||||
{
|
||||
"url": "https://github.com/frappe/erpnext.git",
|
||||
"branch": "version-15"
|
||||
}
|
||||
]
|
||||
245
development/installer.py
Executable file
245
development/installer.py
Executable file
@@ -0,0 +1,245 @@
|
||||
#!/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-15", # noqa: E501
|
||||
default="version-15",
|
||||
)
|
||||
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
|
||||
)
|
||||
parser.add_argument(
|
||||
"-a",
|
||||
"--admin-password",
|
||||
action="store",
|
||||
type=str,
|
||||
help="admin password for site, default: admin", # noqa: E501
|
||||
default="admin",
|
||||
)
|
||||
parser.add_argument(
|
||||
"-d",
|
||||
"--db-type",
|
||||
action="store",
|
||||
type=str,
|
||||
help="Database type to use (e.g., mariadb or postgres)",
|
||||
default="mariadb", # Set your default database type here
|
||||
)
|
||||
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", level=3)
|
||||
if args.db_type:
|
||||
cprint(f"Setting db_type to {args.db_type}", level=3)
|
||||
subprocess.call(
|
||||
["bench", "set-config", "-g", "db_type", args.db_type],
|
||||
cwd=os.path.join(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-queue:6379 for backward compatibility", # noqa: E501
|
||||
level=3,
|
||||
)
|
||||
subprocess.call(
|
||||
[
|
||||
"bench",
|
||||
"set-config",
|
||||
"-g",
|
||||
"redis_socketio",
|
||||
"redis://redis-queue: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):
|
||||
if "mariadb" == args.db_type:
|
||||
cprint("Set db_host", level=3)
|
||||
subprocess.call(
|
||||
["bench", "set-config", "-g", "db_host", "mariadb"],
|
||||
cwd=os.getcwd() + "/" + args.bench_name,
|
||||
)
|
||||
new_site_cmd = [
|
||||
"bench",
|
||||
"new-site",
|
||||
f"--db-root-username=root",
|
||||
f"--db-host=mariadb", # Should match the compose service name
|
||||
f"--db-type={args.db_type}", # Add the selected database type
|
||||
f"--mariadb-user-host-login-scope=%",
|
||||
f"--db-root-password=123", # Replace with your MariaDB password
|
||||
f"--admin-password={args.admin_password}",
|
||||
]
|
||||
else:
|
||||
cprint("Set db_host", level=3)
|
||||
subprocess.call(
|
||||
["bench", "set-config", "-g", "db_host", "postgresql"],
|
||||
cwd=os.getcwd() + "/" + args.bench_name,
|
||||
)
|
||||
new_site_cmd = [
|
||||
"bench",
|
||||
"new-site",
|
||||
f"--db-root-username=root",
|
||||
f"--db-host=postgresql", # Should match the compose service name
|
||||
f"--db-type={args.db_type}", # Add the selected database type
|
||||
f"--db-root-password=123", # Replace with your PostgreSQL password
|
||||
f"--admin-password={args.admin_password}",
|
||||
]
|
||||
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)
|
||||
cprint(f"Creating Site {args.site_name} ...", level=2)
|
||||
subprocess.call(
|
||||
new_site_cmd,
|
||||
cwd=os.getcwd() + "/" + args.bench_name,
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user