Skip to main content
Glama

gbox

by babelcloud
install.sh42.3 kB
#!/bin/bash # GBOX Installation Script # This script installs GBOX CLI and its dependencies # Usage: # curl -fsSL https://raw.githubusercontent.com/babelcloud/gbox/main/install.sh | bash # curl -fsSL https://raw.githubusercontent.com/babelcloud/gbox/main/install.sh | bash -s -- -y --with-deps --update set -e # Colors for output RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' DIM='\033[2m' # Dim/faint text NC='\033[0m' # No Color BOLD='\033[1m' # Non-interactive mode flag NON_INTERACTIVE=false # Install dependencies flag WITH_DEPS=false # Update CLI flag (empty means not specified, true means update, false means no update) UPDATE_CLI="" # Detect OS OS="$(uname -s)" ARCH="$(uname -m)" # Parse command line arguments parse_args() { while [[ $# -gt 0 ]]; do case $1 in -y | --yes | --non-interactive) NON_INTERACTIVE=true shift ;; --with-deps) WITH_DEPS=true shift ;; --update) # Check if next argument is a value (false/true) if [[ $# -gt 1 ]] && [[ "$2" == "false" || "$2" == "true" ]]; then UPDATE_CLI="$2" shift 2 else UPDATE_CLI="true" shift fi ;; --update=*) # Handle --update=false or --update=true UPDATE_CLI="${1#*=}" shift ;; -h | --help) echo "GBOX Installation Script" echo "" echo "Usage: $0 [OPTIONS]" echo "" echo "Options:" echo " -y, --yes, --non-interactive Run in non-interactive mode (use all defaults)" echo " --with-deps Install all command dependencies (adb, frpc, appium)" echo " --update [true|false] Update GBOX CLI to the latest version (default: true)" echo " --update=false Skip update even if already installed" echo " -h, --help Show this help message" echo "" echo "Default behavior:" echo " By default, only GBOX CLI is installed." echo " Use --with-deps to also install all command dependencies." echo "" echo "Examples:" echo " # Install GBOX CLI only (default)" echo " $0" echo "" echo " # Install GBOX CLI with all dependencies" echo " $0 --with-deps" echo "" echo " # Update GBOX CLI to latest version" echo " $0 --update" echo "" echo " # Non-interactive installation" echo " $0 -y" echo "" echo " # Non-interactive with all dependencies" echo " $0 -y --with-deps" echo "" echo " # Using curl (CLI only)" echo " curl -fsSL https://raw.githubusercontent.com/babelcloud/gbox/main/install.sh | bash" echo "" echo " # Using curl with dependencies" echo " curl -fsSL https://raw.githubusercontent.com/babelcloud/gbox/main/install.sh | bash -s -- --with-deps" echo "" echo " # Using curl to update" echo " curl -fsSL https://raw.githubusercontent.com/babelcloud/gbox/main/install.sh | bash -s -- --update" exit 0 ;; *) print_error "Unknown option: $1" echo "Use -h or --help for usage information" exit 1 ;; esac done } print_header() { echo -e "${BLUE}${BOLD}" echo "╔════════════════════════════════════════╗" echo "║ ║" echo "║ GBOX Installation Script ║" echo "║ ║" echo "╚════════════════════════════════════════╝" echo -e "${NC}" } print_success() { echo -e "${GREEN}✅ ${NC}$1" } print_warning() { echo -e "${YELLOW}⚠️ ${NC}$1" } print_error() { echo -e "${RED}❌ ${NC}$1" } print_info() { echo -e "${BLUE}ℹ️ ${NC}$1" } # Check if command exists command_exists() { command -v "$1" >/dev/null 2>&1 } # Execute command with sudo if available and needed run_as_root() { # If already root, no need for sudo if [ "$(id -u)" = "0" ]; then "$@" # If sudo is available, use it elif command_exists sudo; then sudo "$@" # Otherwise, try to run directly else "$@" fi } # Detect OS and set installation method detect_os() { case "$OS" in Linux*) OS_TYPE="linux" if command_exists apt-get; then PKG_MANAGER="apt" elif command_exists yum; then PKG_MANAGER="yum" elif command_exists dnf; then PKG_MANAGER="dnf" else PKG_MANAGER="unknown" fi ;; Darwin*) OS_TYPE="macos" PKG_MANAGER="brew" ;; MINGW* | MSYS* | CYGWIN*) OS_TYPE="windows" PKG_MANAGER="choco" ;; *) OS_TYPE="unknown" PKG_MANAGER="unknown" ;; esac } # Check Node.js installation check_nodejs() { if command_exists node && command_exists npm; then NODE_VERSION=$(node --version) NPM_VERSION=$(npm --version) print_success "Node.js $NODE_VERSION and npm $NPM_VERSION are installed" return 0 else return 1 fi } # Install Node.js using different methods install_nodejs_nvm() { print_info "Installing Node.js using nvm (Node Version Manager)..." # Install nvm if ! command_exists nvm; then curl -so- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.3/install.sh | bash # Load nvm export NVM_DIR="$HOME/.nvm" [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" fi # Install LTS version nvm install --lts nvm use --lts print_success "Node.js installed via nvm" } install_nodejs_brew() { print_info "Installing Node.js using Homebrew..." if ! command_exists brew; then print_error "Homebrew is not installed. Installing Homebrew first..." /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" fi brew install node print_success "Node.js installed via Homebrew" } install_nodejs_apt() { print_info "Installing Node.js using apt..." # Install Node.js 20.x LTS curl -fsSL https://deb.nodesource.com/setup_20.x | run_as_root bash - run_as_root apt-get install -y nodejs print_success "Node.js installed via apt" } install_nodejs_yum() { print_info "Installing Node.js using yum..." # Install Node.js 20.x LTS curl -fsSL https://rpm.nodesource.com/setup_20.x | run_as_root bash - run_as_root yum install -y nodejs print_success "Node.js installed via yum" } install_nodejs_windows() { print_info "Installing Node.js on Windows..." print_warning "Please download and install Node.js manually from https://nodejs.org/" print_warning "After installation, restart your terminal and re-run this script." exit 1 } # Interactive Node.js installation prompt_install_nodejs() { echo "" echo -e "${YELLOW}${BOLD}Node.js is required for Appium automation${NC}" echo "" # Non-interactive mode: use default option (Homebrew on macOS, package manager on Linux) if [ "$NON_INTERACTIVE" = true ]; then print_info "Non-interactive mode: Using default installation method" case "$OS_TYPE" in macos) install_nodejs_brew ;; linux) if [ "$PKG_MANAGER" = "apt" ]; then install_nodejs_apt elif [ "$PKG_MANAGER" = "yum" ] || [ "$PKG_MANAGER" = "dnf" ]; then install_nodejs_yum else print_error "Unsupported package manager: $PKG_MANAGER" return 1 fi ;; windows) install_nodejs_windows ;; *) print_error "Unsupported operating system: $OS_TYPE" return 1 ;; esac return 0 fi # Interactive mode case "$OS_TYPE" in macos) echo "Choose installation method:" echo " 1) Homebrew (recommended)" echo " 2) nvm (Node Version Manager)" echo " 3) Skip Node.js installation" echo "" read -p "Enter choice [1-3]: " choice case $choice in 1) install_nodejs_brew ;; 2) install_nodejs_nvm ;; 3) print_warning "Skipping Node.js installation" return 1 ;; *) print_error "Invalid choice" return 1 ;; esac ;; linux) echo "Choose installation method:" echo " 1) Package Manager ($PKG_MANAGER)" echo " 2) nvm (Node Version Manager)" echo " 3) Skip Node.js installation" echo "" read -p "Enter choice [1-3]: " choice case $choice in 1) if [ "$PKG_MANAGER" = "apt" ]; then install_nodejs_apt elif [ "$PKG_MANAGER" = "yum" ] || [ "$PKG_MANAGER" = "dnf" ]; then install_nodejs_yum else print_error "Unsupported package manager: $PKG_MANAGER" return 1 fi ;; 2) install_nodejs_nvm ;; 3) print_warning "Skipping Node.js installation" return 1 ;; *) print_error "Invalid choice" return 1 ;; esac ;; windows) install_nodejs_windows ;; *) print_error "Unsupported operating system: $OS_TYPE" return 1 ;; esac return 0 } # Check if GBOX is installed and get version info (fast, local check only) check_gbox_installed() { if command_exists gbox; then # Use gbox version for fast local check (works on all platforms) local installed_version=$(gbox version -o json 2>/dev/null | grep '"Version"' | head -1 | sed 's/.*: "\(.*\)".*/\1/' || echo "unknown") if [ -n "$installed_version" ] && [ "$installed_version" != "unknown" ]; then echo "installed|$installed_version" return 0 fi fi echo "not_installed" return 0 } # Install GBOX CLI install_gbox() { print_info "Installing GBOX CLI..." case "$OS_TYPE" in macos) if command_exists brew; then brew install gbox print_success "GBOX CLI installed via Homebrew" else print_error "Homebrew is required for GBOX installation on macOS" print_info "Install Homebrew: /bin/bash -c \"\$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)\"" return 1 fi ;; linux | windows) npm install -g @gbox.ai/cli print_success "GBOX CLI installed via npm" ;; *) print_error "Unsupported operating system: $OS_TYPE" return 1 ;; esac } # Update GBOX CLI update_gbox() { print_info "Updating GBOX CLI..." case "$OS_TYPE" in macos) if command_exists brew; then # Update Homebrew first to get latest package info print_info "Updating Homebrew repository..." if brew update >/dev/null 2>&1; then print_success "Homebrew repository updated" else print_warning "Homebrew update failed, continuing anyway..." fi # Check which tap is installed print_info "Upgrading GBOX CLI..." if brew list --formula | grep -q "babelcloud/gru/gbox"; then # Using custom tap brew upgrade babelcloud/gru/gbox 2>&1 | tail -5 else # Using official formula brew upgrade gbox 2>&1 | tail -5 fi # Get updated version local new_version=$(gbox version -o json 2>/dev/null | grep '"Version"' | head -1 | sed 's/.*: "\(.*\)".*/\1/' || echo "unknown") if [ "$new_version" != "unknown" ]; then print_success "GBOX CLI updated to v$new_version" else print_success "GBOX CLI updated via Homebrew" fi else print_error "Homebrew is required for GBOX update on macOS" return 1 fi ;; linux | windows) print_info "Updating GBOX CLI via npm package @gbox.ai/cli..." npm install -g @gbox.ai/cli@latest # Get updated version local new_version=$(gbox version -o json 2>/dev/null | grep '"Version"' | head -1 | sed 's/.*: "\(.*\)".*/\1/' || echo "unknown") if [ "$new_version" != "unknown" ]; then print_success "GBOX CLI updated to v$new_version" else print_success "GBOX CLI updated via npm" fi ;; *) print_error "Unsupported operating system: $OS_TYPE" return 1 ;; esac } # Install frpc from GitHub releases install_frpc_from_github() { local os_type="" local arch_type="" # Ensure jq is installed for JSON parsing if ! command_exists jq; then print_info "Installing jq for JSON parsing..." case "$OS_TYPE" in macos) if command_exists brew; then brew install jq >/dev/null 2>&1 || { print_error "Failed to install jq" return 1 } else print_error "Homebrew not found, cannot install jq" return 1 fi ;; linux) if command -v apt-get >/dev/null 2>&1; then run_as_root apt-get update >/dev/null 2>&1 run_as_root apt-get install -y jq >/dev/null 2>&1 || { print_error "Failed to install jq via apt-get" return 1 } elif command -v yum >/dev/null 2>&1; then run_as_root yum install -y jq >/dev/null 2>&1 || { print_error "Failed to install jq via yum" return 1 } else print_error "No package manager found, cannot install jq" return 1 fi ;; *) print_error "Unsupported OS for jq installation" return 1 ;; esac if ! command_exists jq; then print_error "jq installation failed, cannot proceed" return 1 fi print_success "jq installed successfully" fi # Get latest frpc version from GitHub API print_info "Fetching latest frpc version from GitHub..." local frpc_version if command_exists curl; then frpc_version=$(curl -fsS https://api.github.com/repos/fatedier/frp/releases/latest | jq -r '.tag_name' | sed 's/^v//') elif command_exists wget; then frpc_version=$(wget -qO- https://api.github.com/repos/fatedier/frp/releases/latest | jq -r '.tag_name' | sed 's/^v//') else print_error "Neither curl nor wget found" return 1 fi if [ -z "$frpc_version" ] || [ "$frpc_version" = "null" ]; then print_error "Failed to fetch frpc version from GitHub" return 1 fi # Detect OS case "$OS" in Linux*) os_type="linux" ;; Darwin*) os_type="darwin" ;; *) print_error "Unsupported OS for frpc installation: $OS" return 1 ;; esac # Detect architecture case "$ARCH" in x86_64 | amd64) arch_type="amd64" ;; aarch64 | arm64) arch_type="arm64" ;; armv7l | armhf) arch_type="arm" ;; *) print_error "Unsupported architecture for frpc installation: $ARCH" return 1 ;; esac local download_url="https://github.com/fatedier/frp/releases/download/v${frpc_version}/frp_${frpc_version}_${os_type}_${arch_type}.tar.gz" local temp_dir=$(mktemp -d) local tar_file="${temp_dir}/frp.tar.gz" print_info "Downloading frpc v${frpc_version} for ${os_type}_${arch_type}..." # Download if command_exists curl; then if ! curl -fsSL -o "$tar_file" "$download_url" 2>&1; then print_error "Failed to download frpc" rm -rf "$temp_dir" return 1 fi elif command_exists wget; then if ! wget -O "$tar_file" "$download_url" 2>&1; then print_error "Failed to download frpc" rm -rf "$temp_dir" return 1 fi else print_error "Neither curl nor wget found. Please install one of them first." rm -rf "$temp_dir" return 1 fi # Extract print_info "Extracting frpc..." if ! tar -xzf "$tar_file" -C "$temp_dir" 2>&1; then print_error "Failed to extract frpc" rm -rf "$temp_dir" return 1 fi # Find and install frpc binary local frpc_binary=$(find "$temp_dir" -name "frpc" -type f | head -1) if [ -z "$frpc_binary" ]; then print_error "frpc binary not found in extracted files" rm -rf "$temp_dir" return 1 fi # Install to /usr/local/bin print_info "Installing frpc to /usr/local/bin..." if run_as_root install -m 755 "$frpc_binary" /usr/local/bin/frpc 2>&1; then print_success "frpc installed successfully" else print_error "Failed to install frpc to /usr/local/bin" rm -rf "$temp_dir" return 1 fi # Cleanup rm -rf "$temp_dir" return 0 } # Install additional dependencies install_dependencies() { echo "" echo -e "${BLUE}${BOLD}🔧 Required Dependencies${NC}" echo "──────────────────────────────────────────" echo "" # Check and install ADB (required, no prompt) if command_exists adb; then ADB_VERSION=$(adb version 2>/dev/null | head -1 || echo "unknown") print_success "ADB: $ADB_VERSION" else print_info "Installing Android Debug Bridge (ADB)..." case "$OS_TYPE" in macos) if brew install android-platform-tools; then print_success "ADB installed successfully" else echo "" print_error "Failed to install ADB" echo "" echo "Please install ADB manually:" echo " brew install android-platform-tools" echo "" exit 1 fi ;; linux) if [ "$PKG_MANAGER" = "apt" ]; then if run_as_root apt-get install -y android-tools-adb; then print_success "ADB installed successfully" else echo "" print_error "Failed to install ADB" echo "" echo "Please install ADB manually:" echo " apt-get install android-tools-adb" echo "" exit 1 fi else echo "" print_error "Unsupported package manager for ADB installation" echo "" echo "Please install ADB manually for your system" echo "" exit 1 fi ;; *) echo "" print_error "Unsupported OS for automatic ADB installation" echo "" echo "Please install ADB manually from:" echo " https://developer.android.com/tools/releases/platform-tools" echo "" exit 1 ;; esac fi # Check and install frpc if command_exists frpc; then FRPC_VERSION=$(frpc -v 2>/dev/null | head -1 || echo "installed") print_success "frpc: $FRPC_VERSION" else print_info "Installing FRP Client (frpc)..." # Try Homebrew first on macOS if [ "$OS_TYPE" = "macos" ] && command_exists brew; then if brew install frpc 2>&1; then print_success "frpc installed successfully via Homebrew" else print_warning "Homebrew installation failed, trying GitHub releases..." if ! install_frpc_from_github; then echo "" print_error "Failed to install frpc" echo "" echo "Please install frpc manually from:" echo " https://github.com/fatedier/frp/releases" echo "" exit 1 fi fi else # For Linux and other systems, download from GitHub if ! install_frpc_from_github; then echo "" print_error "Failed to install frpc" echo "" echo "Please install frpc manually from:" echo " https://github.com/fatedier/frp/releases" echo "" exit 1 fi fi fi echo "" } # Detect and setup JSON parser (jq) setup_json_parser() { # Check if jq is already installed if command -v jq >/dev/null 2>&1; then JSON_PARSER="jq" return 0 fi # Try to install jq print_info "jq not found, installing..." case "$OS_TYPE" in macos) if brew install jq 2>&1; then JSON_PARSER="jq" print_success "jq installed successfully" return 0 fi ;; linux) if command -v apt-get >/dev/null 2>&1; then if run_as_root apt-get install -y jq; then JSON_PARSER="jq" print_success "jq installed successfully" return 0 fi elif command -v yum >/dev/null 2>&1; then if run_as_root yum install -y jq; then JSON_PARSER="jq" print_success "jq installed successfully" return 0 fi fi ;; esac # If jq installation failed, use grep fallback print_warning "jq installation failed, will use grep fallback" JSON_PARSER="grep" return 0 } # Extract version from JSON using jq or grep fallback extract_json_version() { local json_data="$1" local key="$2" if [ "$JSON_PARSER" = "jq" ]; then # Use jq for accurate JSON parsing echo "$json_data" | jq -r ".${key}.version // empty" 2>/dev/null else # Fallback to grep method echo "$json_data" | grep -A 20 "\"$key\"" | grep '"version"' | head -1 | sed 's/.*: "\(.*\)".*/\1/' fi } # Spinner animation for background processes spinner() { local pid=$1 local message=$2 local spinstr='⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏' local i=0 while kill -0 $pid 2>/dev/null; do local temp=${spinstr:i++%${#spinstr}:1} printf "\r ${BLUE}%s${NC} %s..." "$temp" "$message" sleep 0.1 done printf "\r%80s\r" "" } # Install Appium and components with beautiful formatting install_appium_components() { echo "" echo -e "${BLUE}${BOLD}🚀 Installing Appium Automation${NC}" echo "──────────────────────────────────────────" echo "" APPIUM_PATH="$HOME/.gbox/device-proxy/appium" APPIUM_BIN="$APPIUM_PATH/node_modules/.bin/appium" # Use default configuration DRIVERS="${GBOX_APPIUM_DRIVERS:-uiautomator2}" PLUGINS="${GBOX_APPIUM_PLUGINS:-inspector}" # Create directory mkdir -p "$APPIUM_PATH" # Install Appium Server if [ -f "$APPIUM_BIN" ]; then APPIUM_VERSION=$("$APPIUM_BIN" --version 2>/dev/null || echo "unknown") echo -e " ${GREEN}✓${NC} Appium Server ${DIM}v${APPIUM_VERSION}${NC}" else npm install appium --prefix "$APPIUM_PATH" --silent & spinner $! "Installing Appium Server" wait $! if [ $? -eq 0 ]; then APPIUM_VERSION=$("$APPIUM_BIN" --version 2>/dev/null || echo "unknown") echo -e " ${GREEN}✓${NC} Appium Server ${DIM}v${APPIUM_VERSION}${NC}" else echo -e " ${RED}✗${NC} Appium Server ${DIM}(failed)${NC}" return 1 fi fi # Install Drivers if [ -n "$DRIVERS" ]; then echo "" echo -e "${DIM} Drivers:${NC}" IFS=',' read -ra DRIVER_ARRAY <<<"$DRIVERS" for driver in "${DRIVER_ARRAY[@]}"; do driver=$(echo "$driver" | xargs) if [ -z "$driver" ]; then continue; fi # Check if already installed DRIVER_INFO=$(APPIUM_HOME="$APPIUM_PATH" "$APPIUM_BIN" driver list --installed --json 2>/dev/null || echo "{}") if echo "$DRIVER_INFO" | grep -q "\"$driver\""; then DRIVER_VERSION=$(extract_json_version "$DRIVER_INFO" "$driver") echo -e " ${GREEN}✓${NC} ${driver} ${DIM}v${DRIVER_VERSION}${NC}" else APPIUM_HOME="$APPIUM_PATH" "$APPIUM_BIN" driver install "$driver" >/dev/null 2>&1 & spinner $! "Installing ${driver}" wait $! if [ $? -eq 0 ]; then DRIVER_INFO=$(APPIUM_HOME="$APPIUM_PATH" "$APPIUM_BIN" driver list --installed --json 2>/dev/null || echo "{}") DRIVER_VERSION=$(extract_json_version "$DRIVER_INFO" "$driver") echo -e " ${GREEN}✓${NC} ${driver} ${DIM}v${DRIVER_VERSION}${NC}" else echo -e " ${RED}✗${NC} ${driver} ${DIM}(failed)${NC}" fi fi done fi # Install Plugins if [ -n "$PLUGINS" ]; then echo "" echo -e "${DIM} Plugins:${NC}" IFS=',' read -ra PLUGIN_ARRAY <<<"$PLUGINS" for plugin in "${PLUGIN_ARRAY[@]}"; do plugin=$(echo "$plugin" | xargs) if [ -z "$plugin" ]; then continue; fi # Check if already installed PLUGIN_INFO=$(APPIUM_HOME="$APPIUM_PATH" "$APPIUM_BIN" plugin list --installed --json 2>/dev/null || echo "{}") if echo "$PLUGIN_INFO" | grep -q "\"$plugin\""; then PLUGIN_VERSION=$(extract_json_version "$PLUGIN_INFO" "$plugin") echo -e " ${GREEN}✓${NC} ${plugin} ${DIM}v${PLUGIN_VERSION}${NC}" else APPIUM_HOME="$APPIUM_PATH" "$APPIUM_BIN" plugin install "$plugin" >/dev/null 2>&1 & spinner $! "Installing ${plugin}" wait $! if [ $? -eq 0 ]; then PLUGIN_INFO=$(APPIUM_HOME="$APPIUM_PATH" "$APPIUM_BIN" plugin list --installed --json 2>/dev/null || echo "{}") PLUGIN_VERSION=$(extract_json_version "$PLUGIN_INFO" "$plugin") echo -e " ${GREEN}✓${NC} ${plugin} ${DIM}v${PLUGIN_VERSION}${NC}" else echo -e " ${RED}✗${NC} ${plugin} ${DIM}(failed)${NC}" fi fi done fi echo "" echo "──────────────────────────────────────────" echo -e " ${GREEN}✓${NC} Installation completed" echo -e " ${DIM}Location: ${APPIUM_PATH}${NC}" echo "" } # Check Appium installation status (populates global MISSING_COMPONENTS array) check_appium_status() { APPIUM_PATH="$HOME/.gbox/device-proxy/appium" APPIUM_BIN="$APPIUM_PATH/node_modules/.bin/appium" REQUIRED_DRIVERS="${GBOX_APPIUM_DRIVERS:-uiautomator2}" REQUIRED_PLUGINS="${GBOX_APPIUM_PLUGINS:-inspector}" # Use global variable so it's accessible outside the function MISSING_COMPONENTS=() # Check Appium Server if [ ! -f "$APPIUM_BIN" ]; then MISSING_COMPONENTS+=("Appium Server") fi # Check Drivers (only if Appium is installed) if [ -f "$APPIUM_BIN" ]; then IFS=',' read -ra DRIVER_ARRAY <<<"$REQUIRED_DRIVERS" for driver in "${DRIVER_ARRAY[@]}"; do driver=$(echo "$driver" | xargs) if [ -z "$driver" ]; then continue; fi DRIVER_INFO=$(APPIUM_HOME="$APPIUM_PATH" "$APPIUM_BIN" driver list --installed --json 2>/dev/null || echo "{}") if ! echo "$DRIVER_INFO" | grep -q "\"$driver\""; then MISSING_COMPONENTS+=("Driver: $driver") fi done # Check Plugins IFS=',' read -ra PLUGIN_ARRAY <<<"$REQUIRED_PLUGINS" for plugin in "${PLUGIN_ARRAY[@]}"; do plugin=$(echo "$plugin" | xargs) if [ -z "$plugin" ]; then continue; fi PLUGIN_INFO=$(APPIUM_HOME="$APPIUM_PATH" "$APPIUM_BIN" plugin list --installed --json 2>/dev/null || echo "{}") if ! echo "$PLUGIN_INFO" | grep -q "\"$plugin\""; then MISSING_COMPONENTS+=("Plugin: $plugin") fi done fi # Return status if [ ${#MISSING_COMPONENTS[@]} -eq 0 ]; then return 0 # All components installed else return 1 # Missing components fi } # Display Appium installation status display_appium_status() { APPIUM_PATH="$HOME/.gbox/device-proxy/appium" APPIUM_BIN="$APPIUM_PATH/node_modules/.bin/appium" echo "" echo -e "${BLUE}${BOLD}🚀 Appium Status${NC}" echo "──────────────────────────────────────────" echo "" if [ -f "$APPIUM_BIN" ]; then APPIUM_VERSION=$("$APPIUM_BIN" --version 2>/dev/null || echo "unknown") echo -e " ${GREEN}✓${NC} Appium Server ${DIM}v${APPIUM_VERSION}${NC}" # Show drivers DRIVERS="${GBOX_APPIUM_DRIVERS:-uiautomator2}" IFS=',' read -ra DRIVER_ARRAY <<<"$DRIVERS" if [ ${#DRIVER_ARRAY[@]} -gt 0 ]; then echo "" echo -e "${DIM} Drivers:${NC}" for driver in "${DRIVER_ARRAY[@]}"; do driver=$(echo "$driver" | xargs) if [ -z "$driver" ]; then continue; fi DRIVER_INFO=$(APPIUM_HOME="$APPIUM_PATH" "$APPIUM_BIN" driver list --installed --json 2>/dev/null || echo "{}") if echo "$DRIVER_INFO" | grep -q "\"$driver\""; then DRIVER_VERSION=$(extract_json_version "$DRIVER_INFO" "$driver") if [ -n "$DRIVER_VERSION" ]; then echo -e " ${GREEN}✓${NC} ${driver} ${DIM}v${DRIVER_VERSION}${NC}" else echo -e " ${RED}✗${NC} ${driver} ${DIM}(failed)${NC}" fi fi done fi # Show plugins PLUGINS="${GBOX_APPIUM_PLUGINS:-inspector}" IFS=',' read -ra PLUGIN_ARRAY <<<"$PLUGINS" if [ ${#PLUGIN_ARRAY[@]} -gt 0 ]; then echo "" echo -e "${DIM} Plugins:${NC}" for plugin in "${PLUGIN_ARRAY[@]}"; do plugin=$(echo "$plugin" | xargs) if [ -z "$plugin" ]; then continue; fi PLUGIN_INFO=$(APPIUM_HOME="$APPIUM_PATH" "$APPIUM_BIN" plugin list --installed --json 2>/dev/null || echo "{}") if echo "$PLUGIN_INFO" | grep -q "\"$plugin\""; then PLUGIN_VERSION=$(extract_json_version "$PLUGIN_INFO" "$plugin") if [ -n "$PLUGIN_VERSION" ]; then echo -e " ${GREEN}✓${NC} ${plugin} ${DIM}v${PLUGIN_VERSION}${NC}" else echo -e " ${RED}✗${NC} ${plugin} ${DIM}(failed)${NC}" fi fi done fi echo "" echo "──────────────────────────────────────────" echo -e " ${DIM}Location: ${APPIUM_PATH}${NC}" fi echo "" } # Configure Appium installation configure_appium() { echo "" echo -e "${BLUE}${BOLD}🚀 Appium Automation Setup${NC}" echo "───────────────────────────────────────────" # Check if Appium is disabled via environment variable if [ "${GBOX_APPIUM_DISABLED}" = "true" ]; then echo "" print_info "Appium installation is disabled (GBOX_APPIUM_DISABLED=true)" print_warning "Device automation features will not be available" echo "" return 0 fi # Set default configuration export GBOX_APPIUM_DRIVERS="${GBOX_APPIUM_DRIVERS:-uiautomator2}" export GBOX_APPIUM_PLUGINS="${GBOX_APPIUM_PLUGINS:-inspector}" # Export APPIUM_HOME for user convenience export APPIUM_HOME="$HOME/.gbox/device-proxy/appium" echo "" print_info "Required components:" echo " 📦 Appium Server" echo " 🔧 Driver: ${GBOX_APPIUM_DRIVERS}" echo " 🔌 Plugin: ${GBOX_APPIUM_PLUGINS}" # Check current installation status echo "" if check_appium_status; then print_success "All Appium components are already installed!" display_appium_status export GBOX_INSTALL_APPIUM=true return 0 fi # List missing components echo "" echo -e "${YELLOW}Missing components detected:${NC}" for component in "${MISSING_COMPONENTS[@]}"; do echo " ⚠️ $component" done # Automatically install missing components echo "" print_info "Installing missing components automatically..." export GBOX_INSTALL_APPIUM=true if install_appium_components; then echo "" print_success "Appium installation completed successfully!" else echo "" echo -e "${RED}${BOLD}╔════════════════════════════════════════════════════╗${NC}" echo -e "${RED}${BOLD}║ ⚠️ WARNING: Installation Failed ║${NC}" echo -e "${RED}${BOLD}╚════════════════════════════════════════════════════╝${NC}" echo "" echo -e "${YELLOW}Some components failed to install. You may experience:${NC}" echo -e " ${RED}❌${NC} Device connection issues" echo -e " ${RED}❌${NC} Automation test failures" echo "" echo -e "${YELLOW}To skip Appium installation, set:${NC}" echo -e " ${BLUE}export GBOX_APPIUM_DISABLED=true${NC}" echo "" echo -e "${YELLOW}To retry installation, run:${NC}" echo -e " ${BLUE}curl -fsSL https://raw.githubusercontent.com/babelcloud/gbox/main/install.sh | bash${NC}" echo "" return 1 fi } # Save configuration to profile save_config() { SHELL_RC="" if [ -n "$BASH_VERSION" ]; then SHELL_RC="$HOME/.bashrc" elif [ -n "$ZSH_VERSION" ]; then SHELL_RC="$HOME/.zshrc" fi if [ -n "$SHELL_RC" ] && [ -f "$SHELL_RC" ]; then # Check if config already exists if ! grep -q "GBOX Appium Configuration" "$SHELL_RC"; then echo "" >>"$SHELL_RC" echo "# GBOX Appium Configuration" >>"$SHELL_RC" echo "export GBOX_INSTALL_APPIUM=${GBOX_INSTALL_APPIUM:-true}" >>"$SHELL_RC" echo "export GBOX_APPIUM_DRIVERS=${GBOX_APPIUM_DRIVERS:-uiautomator2}" >>"$SHELL_RC" echo "export GBOX_APPIUM_PLUGINS=${GBOX_APPIUM_PLUGINS:-inspector}" >>"$SHELL_RC" echo "export APPIUM_HOME=\"\$HOME/.gbox/device-proxy/appium\"" >>"$SHELL_RC" print_success "Configuration saved to $SHELL_RC" else print_info "Configuration already exists in $SHELL_RC" fi fi } # Print next steps print_next_steps() { echo "" echo -e "${GREEN}${BOLD}╔════════════════════════════════════════╗${NC}" echo -e "${GREEN}${BOLD}║ ║${NC}" echo -e "${GREEN}${BOLD}║ ✅ Installation Complete! ║${NC}" echo -e "${GREEN}${BOLD}║ ║${NC}" echo -e "${GREEN}${BOLD}╚════════════════════════════════════════╝${NC}" echo "" echo "──────────────────────────────────────────" echo "" echo -e "${BOLD}📋 Next Steps:${NC}" echo "" echo "1️⃣ Reload your shell configuration:" echo -e " ${YELLOW}source ~/.bashrc${NC} (or ~/.zshrc)" echo "" echo "2️⃣ Login to GBOX:" echo -e " ${YELLOW}gbox login${NC}" echo "" echo "3️⃣ Connect your device:" echo -e " ${YELLOW}gbox device-connect${NC}" echo "" echo "4️⃣ Export MCP config (optional):" echo -e " ${YELLOW}gbox mcp export --merge-to cursor${NC}" echo "" echo -e "${BLUE}ℹ️ For more information, visit: https://docs.gbox.ai${NC}" echo "" } # Main installation flow main() { print_header if [ "$NON_INTERACTIVE" = true ]; then print_info "Running in non-interactive mode (all defaults will be used)" echo "" fi if [ "$WITH_DEPS" = true ]; then print_info "Installing GBOX CLI with all dependencies" else print_info "Installing GBOX CLI only (use --with-deps for dependencies)" fi echo "" # Detect OS first detect_os print_info "Detected OS: $OS_TYPE ($OS $ARCH)\n" print_info "Package Manager: $PKG_MANAGER" echo "" echo "───────────────────────────────────────" echo "" # Only check Node.js if --with-deps is specified (required for Appium) if [ "$WITH_DEPS" = true ]; then # Setup JSON parser for Appium version extraction setup_json_parser if ! check_nodejs; then echo "" print_warning "Node.js is not installed" echo "" if ! prompt_install_nodejs; then echo "" echo -e "${RED}${BOLD}╔═════════════════════════════════════════════════════╗${NC}" echo -e "${RED}${BOLD}║ ❌ Installation Cancelled ║${NC}" echo -e "${RED}${BOLD}╚════════════════════════════════════════════════════╝${NC}" echo "" echo -e "${YELLOW}Node.js is required for Appium automation features.${NC}" echo "" echo "Please install Node.js first:" echo " 🍎 macOS: brew install node" echo " 🐧 Ubuntu/Debian: sudo apt-get install nodejs npm" echo " 🪟 Windows: Download from https://nodejs.org/" echo "" echo "Or use our installation script with Node.js pre-installed." echo "" exit 1 fi fi fi # Install GBOX CLI echo "" GBOX_STATUS=$(check_gbox_installed) if [[ "$GBOX_STATUS" == "not_installed" ]]; then # GBOX not installed, install it install_gbox else # GBOX is already installed IFS='|' read -ra STATUS_PARTS <<<"$GBOX_STATUS" INSTALLED_VERSION="${STATUS_PARTS[1]}" print_success "GBOX CLI is already installed: v$INSTALLED_VERSION" echo "" # Handle update based on UPDATE_CLI flag if [ "$UPDATE_CLI" = "true" ]; then # Explicitly requested update print_info "Updating GBOX CLI to the latest version..." update_gbox elif [ "$UPDATE_CLI" = "false" ]; then # Explicitly disabled update print_info "Update skipped (--update=false)" elif [ "$UPDATE_CLI" = "" ]; then # No --update flag specified if [ "$NON_INTERACTIVE" = true ]; then print_info "Non-interactive mode: Skipping update" else # Interactive mode: ask if user wants to update read -p "Update GBOX CLI to the latest version? [y/N]: " update_choice if [[ "$update_choice" =~ ^[Yy]$ ]]; then update_gbox fi fi fi fi # Only install dependencies if --with-deps is specified if [ "$WITH_DEPS" = true ]; then # Install additional dependencies (ADB, frpc) before Appium install_dependencies # Configure and install Appium automation components if [ "$GBOX_INSTALL_APPIUM" != "false" ] && [ "${GBOX_APPIUM_DISABLED}" != "true" ]; then configure_appium elif [ "${GBOX_APPIUM_DISABLED}" = "true" ]; then echo "" print_info "Appium installation is disabled (GBOX_APPIUM_DISABLED=true)" fi # Save configuration save_config else echo "" print_info "GBOX CLI installation completed. Use 'gbox setup' to install command dependencies." fi # Print next steps print_next_steps } # Parse arguments and run main parse_args "$@" main

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/babelcloud/gru-sandbox'

If you have feedback or need assistance with the MCP directory API, please join our Discord server