From a8dcbd7a1906c5e68ae4e4a104bc70bfbdabcd5d Mon Sep 17 00:00:00 2001 From: Varun Date: Wed, 25 Oct 2023 16:10:42 +1100 Subject: [PATCH] #1247 #1248 Feat: Cypress UI testing + Postgres Arg for installer --- README.md | 1 - devcontainer-example/docker-compose.yml | 62 +++++++++----- development/installer.py | 60 +++++++++++--- docs/development.md | 30 ++++++- install_x11_deps.sh | 106 ++++++++++++++++++++++++ 5 files changed, 224 insertions(+), 35 deletions(-) create mode 100755 install_x11_deps.sh diff --git a/README.md b/README.md index 436e3f4a..11538c2f 100644 --- a/README.md +++ b/README.md @@ -46,7 +46,6 @@ Wait for 5 minutes for ERPNext site to be created or check `create-site` contain - [Development using containers](docs/development.md) - [Bench Console and VSCode Debugger](docs/bench-console-and-vscode-debugger.md) - [Connect to localhost services](docs/connect-to-localhost-services-from-containers-for-local-app-development.md) - ### [Troubleshoot](docs/troubleshoot.md) # Contributing diff --git a/devcontainer-example/docker-compose.yml b/devcontainer-example/docker-compose.yml index c2b02bc6..4fe52586 100644 --- a/devcontainer-example/docker-compose.yml +++ b/devcontainer-example/docker-compose.yml @@ -1,24 +1,24 @@ version: "3.7" services: - mariadb: - image: mariadb:10.6 - 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 - volumes: - - mariadb-data:/var/lib/mysql + # mariadb: + # image: mariadb:10.6 + # 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 + # volumes: + # - mariadb-data:/var/lib/mysql # Enable PostgreSQL only if you use it, see development/README.md for more information. - # postgresql: - # image: postgres:11.8 - # environment: - # POSTGRES_PASSWORD: 123 - # volumes: - # - postgresql-data:/var/lib/postgresql/data + postgresql: + image: postgres:11.8 + environment: + POSTGRES_PASSWORD: 123 + volumes: + - postgresql-data:/var/lib/postgresql/data redis-cache: image: redis:alpine @@ -39,7 +39,31 @@ services: ports: - 8000-8005:8000-8005 - 9000-9005:9000-9005 - + ui-tester: + # pass custom command to start Cypress otherwise it will use the entrypoint + # specified in the Cypress Docker image. + # also pass "--project " 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: "cypress/included:latest" + #command: sleep infinity + 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: + #mariadb-data: postgresql-data: diff --git a/development/installer.py b/development/installer.py index 34686051..4c33ce46 100755 --- a/development/installer.py +++ b/development/installer.py @@ -105,6 +105,13 @@ def get_args_parser(): help="admin password for site, default: admin", # noqa: E501 default="admin", ) + parser.add_argument( + "--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 @@ -128,7 +135,9 @@ def init_bench_if_not_exist(args): 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 += f"--db_type={args.db_type} " #--db-type postgres init_command += args.bench_name + print(init_command) command = [ "/bin/bash", "-i", @@ -137,11 +146,14 @@ def init_bench_if_not_exist(args): ] 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 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( [ @@ -188,13 +200,37 @@ def init_bench_if_not_exist(args): def create_site_in_bench(args): - new_site_cmd = [ - "bench", - "new-site", - "--no-mariadb-socket", - "--mariadb-root-password=123", - f"--admin-password={args.admin_password}", - ] + mariadb_socket_option="" + 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-host=mariadb", # Should match the compose service name + f"--db-type={args.db_type}", # Add the selected database type + f"--no-mariadb-socket ", + f"--db-root-password=123", # Replace with your PostgreSQL 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-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}", + ] + print(new_site_cmd) apps = os.listdir(f"{os.getcwd()}/{args.bench_name}/apps") apps.remove("frappe") for app in apps: diff --git a/docs/development.md b/docs/development.md index 3919b644..344b3523 100644 --- a/docs/development.md +++ b/docs/development.md @@ -241,15 +241,14 @@ Sample `apps-example.json` is used by default, it installs erpnext on current st > 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). ```shell -python installer.py +python installer.py #pass --db-type postgres for postgresdb ``` For command help ```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] - +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] [-a ADMIN_PASSWORD] [--db-type DB_TYPE] options: -h, --help show this help message and exit -j APPS_JSON, --apps-json APPS_JSON @@ -269,6 +268,7 @@ options: -v, --verbose verbose output -a ADMIN_PASSWORD, --admin-password ADMIN_PASSWORD admin password for site, default: admin + --db-type DB_TYPE Database type to use (e.g., mariadb or postgres) ``` A new bench and / or site is created for the client with following defaults. @@ -276,6 +276,8 @@ A new bench and / or site is created for the client with following defaults. - MariaDB root password: `123` - Admin password: `admin` +> To use Postegres DB, comment the mariabdb service and uncomment postegres service. + ### 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: @@ -381,3 +383,25 @@ volumes: ``` Access the service by service name from the `frappe` development container. The above service will be accessible via hostname `postgresql`. If ports are published on to host, access it via `localhost:5432`. + +## Using Cypress UI tests + +To run cypress based UI tests in a docker environment, follow the below steps: + +1. Install and setup X11 tooling on VM using the script `install_x11_deps.sh` + +```shell + sudo ./install_x11_deps.sh +``` +This script will install required deps, enable X11Forwarding and restart SSH daemon and export `DISPLAY` variable. + +2. Run X11 service `startx` or `xquartz` +3. Start docker compose services. +4. SSH into ui-tester service using `docker exec.. ` command +5. Export CYPRESS_baseUrl and other required env variables +6. Start Cypress UI console by issuing `cypress run command` + +> More references : [Cypress Official Documentation](https://www.cypress.io/blog/2019/05/02/run-cypress-with-a-single-docker-command) + +> Ensure DISPLAY enviroment is always exported. + diff --git a/install_x11_deps.sh b/install_x11_deps.sh new file mode 100755 index 00000000..a88606a0 --- /dev/null +++ b/install_x11_deps.sh @@ -0,0 +1,106 @@ +#!/bin/bash +set -e +# This script configures X11 forwarding for Linux and macOS systems. +# It installs X11, Openbox (on Linux), and checks for XQuartz (on macOS). +# It also updates the sshd_config file to enable X11Forwarding and restarts the SSH service. + +# Check if the script is running with root privileges +if [ "$EUID" -ne 0 ]; then + echo "Error: This script requires root privileges. Please run it as a superuser" + exit 1 +fi + +# Function to restart SSH service (Linux) +restart_ssh_linux() { + if command -v service >/dev/null 2>&1; then + sudo service ssh restart + else + sudo systemctl restart ssh + fi +} + +# Function to restart SSH service (macOS) +restart_ssh_macos() { + launchctl stop com.openssh.sshd + launchctl start com.openssh.sshd +} + +update_x11_forwarding() { + if grep -q "X11Forwarding yes" /etc/ssh/sshd_config; then + echo "X11Forwarding is already set to 'yes' in ssh_config." + else + if [[ "$OSTYPE" == "linux-gnu" ]]; then + # Linux: Use sed for Linux + sudo sed -i 's/#\?X11Forwarding.*/X11Forwarding yes/' /etc/ssh/sshd_config + elif [[ "$OSTYPE" == "darwin"* ]]; then + # macOS: Use sed for macOS + sudo sed -i -E 's/#X11Forwarding.*/X11Forwarding yes/' /etc/ssh/sshd_config + restart_ssh_macos + fi + if [[ "$OSTYPE" == "linux-gnu" ]]; then + restart_ssh_linux + fi + fi +} + +# Determine the operating system +if [[ "$OSTYPE" == "linux-gnu" ]]; then + # Linux + if command -v startx >/dev/null 2>&1; then + echo "X11 is already installed." + else + # Check which package manager is available + if command -v apt-get >/dev/null 2>&1; then + package_manager="apt" + elif command -v dnf >/dev/null 2>&1; then + package_manager="dnf" + else + echo "Error: Unable to determine the package manager. Manual installation required." + exit 1 + fi + + # Install X11 and Openbox based on the package manager + if [ "$package_manager" = "apt" ]; then + sudo apt-get update + sudo apt-get install xorg openbox + elif [ "$package_manager" = "dnf" ]; then + sudo dnf install xorg-x11-server-Xorg openbox + fi + + # Check if X11 and Openbox were installed successfully + if [ $? -eq 0 ]; then + echo "X11 and Openbox have been successfully installed." + else + echo "Error: Failed to install X11 and Openbox." + exit 1 + fi + fi + + # Call the function to update X11Forwarding + update_x11_forwarding + + # Get the IP address of the host dynamically + host_ip=$(hostname -I | awk '{print $1}') + xhost + $host_ip && xhost + local: + # Set the DISPLAY variable to the host IP + export DISPLAY="$host_ip:0.0" + echo "DISPLAY variable set to $DISPLAY" +elif [[ "$OSTYPE" == "darwin"* ]]; then + # macOS + if command -v xquartz >/dev/null 2>&1; then + echo "XQuartz is already installed." + else + echo "Error: XQuartz is required for X11 forwarding on macOS. Please install XQuartz manually." + exit 1 + fi + + # Call the function to update X11Forwarding + update_x11_forwarding + + # Export the DISPLAY variable for macOS + export DISPLAY=:0 + echo "DISPLAY variable set to $DISPLAY" +else + echo "Error: Unsupported operating system." + exit 1 +fi