diff --git a/Dockerfile b/Dockerfile index 54510c7..d54890d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,36 +1,47 @@ -# Start with a minimal Ubuntu image FROM ubuntu:22.04 -# Set non-interactive front-end for installing dependencies +# Set non-interactive frontend to avoid prompts during package installation ENV DEBIAN_FRONTEND=noninteractive -# for using chrome on your host machine -# ENV DISPLAY=:0 -# ENV XAUTHORITY=/root/.Xauthority -# šŸ”„šŸ”„ TODO install chrome in docker container šŸ”„šŸ”„ - -# Install required dependencies +# Update package list and install essential dependencies RUN apt-get update && apt-get install -y \ - curl \ - wget \ - sudo \ - bash \ - tzdata \ - gnupg \ - build-essential \ - git && \ - rm -rf /var/lib/apt/lists/* - -# Set up a working directory -WORKDIR /app - -# Copy the scripts into the container -COPY install_tools.sh /app/install_tools.sh -COPY install_android_sdk.sh /app/install_android_sdk.sh - -# Make the script executable -RUN chmod +x /app/install_tools.sh -RUN chmod +x /app/install_android_sdk.sh - -# Run bash as the default shell -CMD ["/bin/bash"] \ No newline at end of file + curl \ + wget \ + unzip \ + zip \ + sudo \ + bash \ + ca-certificates \ + git \ + && rm -rf /var/lib/apt/lists/* + +# Create a test user with sudo privileges +RUN useradd -m -s /bin/bash appiumuser && \ + echo "appiumuser ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers + +# Set working directory +WORKDIR /home/appiumuser + +# Copy the installation script, startup script, and Appium config +COPY setup_environment.sh ./ + +COPY appium/ ./appium/ + +# Make scripts executable and change ownership +RUN chmod +x setup_environment.sh appium/start-appium.sh && \ + chown appiumuser:appiumuser setup_environment.sh appium/ + +# Switch to test user +USER appiumuser + +# Run the setup script during build time +RUN ./setup_environment.sh + +# Set environment variables for interactive shells +ENV NVM_DIR=/home/appiumuser/.nvm \ + SDKMAN_DIR=/home/appiumuser/.sdkman \ + ANDROID_SDK_ROOT=/home/appiumuser/android_sdk \ + TERM=xterm + +# start appium +CMD ["./appium/start-appium.sh"] \ No newline at end of file diff --git a/README.md b/README.md index 530bc94..d719bac 100644 --- a/README.md +++ b/README.md @@ -1,91 +1,97 @@ -# Workshop Setup - -# Prerequisites -Install Java for your OS (recommended Version 21 or above) - -make the script executable via `chmod u+x install_tools.sh` and execute it afterwards via `./install_tools.sh` - - -### Android SDK and build-tools - -make the script executable via `chmod u+x install_android_sdk.sh` and execute it afterwards via `./install_android_sdk.sh`. -It will download all necessary files and edit your `~/.bashrc` or `~/.zshrc` or `~/.profile` with following env-variables. +### Build Image ```shell +# Build locally +docker build -t workshop-env:latest . -export ANDROID_HOME=$HOME/installed/android_sdk -export ANDROID_PLATFORM_TOOLS=$ANDROID_HOME/platform-tools -export ANDROID_CMD_LINE_TOOLS=$ANDROID_HOME/cmdline-tools/latest -export ANDROID_BUILD_TOOLS_34=$ANDROID_HOME/build-tools/34.0.0 - -export PATH=$ANDROID_HOME:$ANDROID_PLATFORM_TOOLS:$ANDROID_CMD_LINE_TOOLS/bin:$ANDROID_BUILD_TOOLS_34 +# Build on NAS and monitor output +docker --context ubuntu-nas build --progress=plain -t workshop-env:latest . 2>&1 | tee /tmp/docker_build.log +# Build locally and monitor output +docker --context default build --progress=plain -t workshop-env:latest . 2>&1 | tee /tmp/docker_build.log ``` -## Installation for Windows +**Build time:** 5-15 minutes (setup runs during build) +**Image size:** ~2-3GB (all tools pre-installed) -### node installation -https://nodejs.org/en/download/ +### Run Image +The container automatically starts Appium server on port 4723 when launched: -e.g. -### Android SDK with Android Studio -https://developer.android.com/studio/index.html -Goto Configure environment variables: - -```System Properties -> Environment Variables -> System Variables -> New -> ANDROID_HOME``` +```shell +# Run locally: USB + port + daemon mode +docker run -d --name appium-server --privileged -p 4723:4723 -v /dev/bus/usb:/dev/bus/usb workshop-env:latest -and set value as **C:Users\YourUser\AppData\Local\Android\SDK** (path where SDK is installed) +# Run on NAS context +docker --context ubuntu-nas run -d --name appium-server --privileged -p 4723:4723 -v /dev/bus/usb:/dev/bus/usb workshop-env:latest +``` -Add the Android SDK paths into your existing PATH variable value as `%ANDROID_HOME%\tools;%ANDROID_HOME%\platform-tools;%ANDROID_HOME%\build-tools` +**Startup:** Instant - Appium server starts automatically! ---- +### Verify Appium Server -## fallback for nvm (https://www.freecodecamp.org/news/node-version-manager-nvm-install-guide/) +```shell +# Check if container is running +docker ps -execute in terminal +# Check Appium server logs +docker logs appium-server -``` -brew install nvm -# or via -curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.1/install.sh | bash +# Test Appium server endpoint +curl http://localhost:4723/status ``` -if not automatically added during installation, do manually after install +### Container Management -``` -export NVM_DIR="$([ -z "${XDG_CONFIG_HOME-}" ] && printf %s "${HOME}/.nvm" || printf %s "${XDG_CONFIG_HOME}/nvm")" -[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" -``` +```shell +# Stop the server +docker stop appium-server -## fallback for sdkman (https://sdkman.io/install/) +# Restart the server +docker start appium-server -``` -curl -s "https://get.sdkman.io" | bash +# Remove container (to recreate) +docker rm -f appium-server ``` -Follow the on-screen instructions to wrap up the installation. Afterward, open a new terminal or run the following in the same shell: +### Interactive Access (Optional) -``` -source "$HOME/.sdkman/bin/sdkman-init.sh" -``` +If you need to access the container shell for debugging: -### working mvn command running the tests -``` -mvn test -Dbrowser=chrome -DbaseUrl="https://www.wikipedia.org" -Dcucumber.filter.tags=@all -Dcucumber.glue=at.ucaat.demo.stepdefinitions -Dcucumber.features=src/test/resources/features -``` - -### selenium-server download +```shell +# Execute bash in running container +docker exec -it appium-server bash +# Or run a new container in interactive mode +docker run -it --rm --privileged -p 4723:4723 -v /dev/bus/usb:/dev/bus/usb workshop-env:latest bash ``` -java -jar selenium-server-4.30.0.jar standalone -``` +## Technical Info + +### Script Features +`setup_environment.sh` works on both bare metal Ubuntu and Docker containers: ---- +āœ… **Color-coded output** - Uses tput with ANSI fallback for Docker builds +āœ… **Smart terminal detection** - Automatically handles missing TERM variable +āœ… **Package manager support** - Works with apt-get and yum +āœ… **Shell detection** - Configures bash/zsh appropriately +āœ… **Dynamic version detection** - Automatically installs latest Android build-tools +āœ… **User-level installation** - Installs to $HOME (NVM, SDKMAN, Android SDK) +āœ… **Sudo support** - Uses sudo only for system packages +āœ… **Idempotent** - Safe to run multiple times +### Docker Build +- **Build time:** 5-15 minutes (setup runs during `docker build`) +- **Image size:** ~2-3GB (all tools pre-installed) +- **Container startup:** Instant (no runtime setup) +- **Tools included:** Node.js, Appium, Java 23, Maven, Android SDK +### Bare Metal Installation +Works on any Linux system with a standard package manager. Run as a regular user with sudo privileges: +```bash +./setup_environment.sh +``` \ No newline at end of file diff --git a/SETUP_DOCUMENTATION.md b/SETUP_DOCUMENTATION.md new file mode 100644 index 0000000..b7e7cb7 --- /dev/null +++ b/SETUP_DOCUMENTATION.md @@ -0,0 +1,1405 @@ +# Workshop Environment Setup Documentation + +## Overview + +This documentation covers the complete setup environment for the mobile testing workshop, including: +- Automated environment setup script (`setup_environment.sh`) +- Docker containerized environment (`Dockerfile`) +- Configuration files and dependencies +- Build and deployment instructions + +--- + +## Table of Contents + +1. [Architecture Overview](#architecture-overview) +2. [Setup Script (`setup_environment.sh`)](#setup-script-setup_environmentsh) +3. [Docker Configuration](#docker-configuration) +4. [Appium Configuration](#appium-configuration) +5. [Build Instructions](#build-instructions) +6. [Usage Instructions](#usage-instructions) +7. [Troubleshooting](#troubleshooting) + +--- + +## Architecture Overview + +The workshop environment provides a complete mobile testing stack with the following components: + +### Core Components + +| Component | Version | Purpose | +|-----------|---------|---------| +| **Ubuntu** | 22.04 | Base operating system | +| **Node.js** | Latest LTS | JavaScript runtime for Appium | +| **NVM** | 0.39.5 | Node Version Manager | +| **Appium** | Latest | Mobile automation framework | +| **Java** | 23 (OpenJDK) | Required for Android SDK tools | +| **Maven** | 3.9.5 | Build automation tool | +| **Android SDK** | Latest | Android development tools | +| **SDKMAN** | Latest | Java/Maven version manager | + +### Directory Structure + +``` +workshop_setup/ +ā”œā”€ā”€ setup_environment.sh # Unified installation script +ā”œā”€ā”€ start-appium.sh # Appium server startup script with validation +ā”œā”€ā”€ appium.conf.json # Appium server configuration +ā”œā”€ā”€ Dockerfile # Docker container definition (runs setup at build time) +ā”œā”€ā”€ SETUP_DOCUMENTATION.md # This file +ā”œā”€ā”€ README.md # Quick start guide +└── legacy/ # Legacy installation scripts + ā”œā”€ā”€ install_android_sdk.sh + ā”œā”€ā”€ install_tools.sh + ā”œā”€ā”€ README.md + └── Dockerfile +``` + +--- + +## Setup Script (`setup_environment.sh`) + +### Purpose + +The `setup_environment.sh` script is a unified, automated installation script that sets up the complete workshop environment. It can be used both: +- **Inside Docker containers** (automated during container build time) +- **On bare metal Ubuntu machines** (manual installation) + +### Output Functions + +The script uses color-coded emoji output for better readability: + +```bash +# Color definitions +RED=$(tput setaf 1) # Error messages +GREEN=$(tput setaf 2) # Success messages +YELLOW=$(tput setaf 3) # Warning messages +BLUE=$(tput setaf 4) # Info messages + +# Helper functions +ok() # āœ” Green checkmark for success +warn() # ⚠ Yellow warning symbol +error() # āœ– Red X for errors +info() # ℹ Blue info symbol +``` + +### Script Flow + +```mermaid +graph TD + A[Start] --> B[Install Prerequisites] + B --> C[Install NVM] + C --> D[Install Node.js & npm] + D --> E[Install Appium] + E --> F[Configure Appium] + F --> G[Install SDKMAN] + G --> H[Install Java 23 & Maven] + H --> I[Download Android SDK] + I --> J[Configure Android Environment] + J --> K[Install SDK Components] + K --> L[Source Shell Config] + L --> M[Display Version Summary] + M --> N[End] +``` + +### Key Functions + +#### 1. **Prerequisites Installation** (`install_prerequisites`) + +```bash +# Installs essential tools +- curl (for downloading) +- wget (for downloading) +- unzip (for extracting archives) +``` + +**Features:** +- Auto-detects package manager (apt-get/yum) +- Uses sudo for system-wide installation +- Validates each tool after installation + +#### 2. **NVM Installation** (`install_nvm`) + +```bash +# Installs Node Version Manager +- Downloads from official GitHub repository +- Configures shell integration (.bashrc/.zshrc) +- Loads NVM in current session +``` + +**Why NVM?** +- Allows easy Node.js version switching +- User-level installation (no sudo needed) +- Automatically manages npm versions + +#### 3. **Node.js & npm** (`install_node_and_npm`) + +```bash +# Installs latest LTS Node.js +- Uses NVM to install Node.js +- Automatically includes npm +- Verifies installation +``` + +#### 4. **Appium Installation** (`install_appium`) + +```bash +# Installs Appium globally +- Uses npm for installation +- Installs latest stable version +- Verifies command availability +``` + +#### 5. **Appium Configuration** (`configure_appium`) + +```bash +# Configures Appium with custom settings +- Creates ~/.appium directory +- Copies appium.conf.json +- Creates chromedriver storage directory +``` + +**Configuration Details:** +- Config location: `~/.appium/appium.conf.json` +- Chromedriver storage: `~/secugrow/chromedrivers` +- Automatically picked up by Appium server + +#### 6. **SDKMAN Installation** (`install_sdkman`) + +```bash +# Installs SDKMAN for Java/Maven management +- Downloads from official source +- Configures shell integration +- Loads SDKMAN in current session +``` + +**Why SDKMAN?** +- Manages multiple Java versions +- User-level installation +- Easy version switching +- Includes Maven management + +#### 7. **Java & Maven Installation** (`install_maven_and_java`) + +```bash +# Installs Java 23 and Maven 3.9.5 +- Uses SDKMAN for installation +- Sets Java 23 as default +- Configures JAVA_HOME +- Verifies installations +``` + +**Java Version:** +- Java 23.0.2-librca (LibericaJDK) +- Required for Android SDK tools +- Automatically configured in PATH + +#### 8. **Android SDK Download** (`download_and_extract_sdk`) + +```bash +# Downloads and extracts Android SDK +- Fetches latest version from Google repository +- Falls back to known version if fetch fails +- Extracts to proper directory structure +``` + +**SDK Structure:** +``` +android_sdk/ +└── cmdline-tools/ + └── latest/ + ā”œā”€ā”€ bin/ + │ └── sdkmanager + └── lib/ +``` + +**Version Detection:** +- Queries Google's repository2-3.xml +- Automatically gets latest commandlinetools +- Fallback version: 11076708 + +#### 9. **Android Environment Configuration** (`configure_android_environment`) + +```bash +# Configures Android environment variables +- Detects shell type (bash/zsh) +- Adds ANDROID_SDK_ROOT to shell config +- Configures PATH for Android tools +``` + +**Environment Variables Set:** +```bash +ANDROID_SDK_ROOT=/android_sdk +ANDROID_CMDLINE_TOOLS=$ANDROID_SDK_ROOT/cmdline-tools/latest +ANDROID_PLATFORM_TOOLS=$ANDROID_SDK_ROOT/platform-tools +ANDROID_BUILD_TOOLS=$(ls -d $ANDROID_SDK_ROOT/build-tools/* 2>/dev/null | head -1) +PATH=$ANDROID_CMDLINE_TOOLS/bin:$ANDROID_PLATFORM_TOOLS:$ANDROID_BUILD_TOOLS:$PATH +``` + +#### 10. **SDK Components Installation** (`install_sdk_components`) + +```bash +# Installs required Android SDK components +- platform-tools (adb, fastboot) +- platforms;android-33 (Android 13 platform) +- build-tools (latest version detected automatically) +``` + +**Process:** +- Sources SDKMAN to access Java +- Queries sdkmanager to get latest build-tools version +- Falls back to version 34.0.0 if detection fails +- Runs sdkmanager with auto-accept +- Exports build-tools version for later use +- Verifies installation success + +**Dynamic Version Detection:** +The script automatically detects and installs the latest available build-tools version instead of hardcoding a version number. + +### Shell Detection + +The script automatically detects the user's shell and configures the appropriate file: + +| Shell | Config File | Priority | +|-------|-------------|----------| +| **bash** (Linux) | `~/.bashrc` | Primary | +| **bash** (Linux) | `~/.profile` | Fallback | +| **zsh** | `~/.zshrc` | Primary | +| **Other** | `~/.bashrc` | Default | + +### Error Handling + +```bash +set -e # Exit on any error +``` + +**Safety Features:** +- Exits immediately on command failure +- Validates each installation step +- Provides clear error messages +- Checks prerequisites before proceeding + +### Version Summary Output + +At the end of execution, the script displays: + +``` +====================================== + Installed Component Versions +====================================== + +Node.js: v22.x.x +npm: 10.x.x +Appium: 2.x.x +Java: openjdk 23.0.2 +Maven: Apache Maven 3.9.5 +Android SDK: Installed at /path/to/android_sdk + +====================================== +``` + +--- + +## Appium Startup Script (`start-appium.sh`) + +### Purpose + +The `start-appium.sh` script is the container entry point that automatically starts the Appium server with proper environment configuration and validation. + +### Script Features + +#### Environment Loading +```bash +# Load all environment configurations +source ~/.bashrc +source ~/.nvm/nvm.sh +source ~/.sdkman/bin/sdkman-init.sh +``` + +#### Pre-flight Validation +- **Appium availability check**: Verifies Appium is installed and accessible +- **Driver validation**: Lists all installed drivers and specifically checks for UIAutomator2 +- **Configuration display**: Shows the contents of appium.conf.json if present +- **Error handling**: Provides detailed error messages if components are missing + +#### Automatic Server Startup +- **Configuration detection**: Automatically loads ~/.appium/appium.conf.json if present +- **Fallback parameters**: Uses command-line parameters if no config file found +- **Network binding**: Starts server on 0.0.0.0 to accept external connections +- **Process replacement**: Uses `exec` to replace the script process with Appium server + +### Script Output Example +``` +āœ“ Appium found: 3.1.0 +Checking installed Appium drivers... +āœ“ UIAutomator2 driver is installed +āœ“ Found Appium configuration file: /home/appiumuser/.appium/appium.conf.json +Configuration contents: +{ + "server": { + "port": 4723, + "allow-cors": true, + ... + } +} +--- End of configuration --- +Starting Appium server with configuration file (auto-loaded)... +[Appium] Welcome to Appium v3.1.0 +``` + +--- + +## Docker Configuration + +### Dockerfile Overview + +The `Dockerfile` creates a complete Ubuntu environment with all tools pre-installed at build time, and includes an automatic Appium server startup script. + +### Dockerfile Breakdown + +```dockerfile +FROM ubuntu:22.04 +``` +**Base Image:** Ubuntu 22.04 LTS (Jammy Jellyfish) +- Long-term support until 2027 +- Stable package repositories +- Wide compatibility + +--- + +```dockerfile +ENV DEBIAN_FRONTEND=noninteractive +``` +**Purpose:** Prevents interactive prompts during package installation +- Essential for automated builds +- Prevents build hanging on user input + +--- + +```dockerfile +RUN apt-get update && apt-get install -y \ + curl \ + wget \ + unzip \ + zip \ + sudo \ + bash \ + ca-certificates \ + git \ + && rm -rf /var/lib/apt/lists/* +``` +**Package Installation:** +- `curl`, `wget`: Download tools +- `unzip`, `zip`: Archive utilities (required for SDKMAN) +- `sudo`: Privilege escalation +- `bash`: Shell (some scripts require bash features) +- `ca-certificates`: SSL/TLS certificates for HTTPS +- `git`: Version control (optional, for future use) + +**Cleanup:** `rm -rf /var/lib/apt/lists/*` reduces image size + +--- + +```dockerfile +RUN useradd -m -s /bin/bash appiumuser && \ + echo "appiumuser ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers +``` +**User Creation:** +- Creates non-root user `appiumuser` +- `-m`: Creates home directory +- `-s /bin/bash`: Sets bash as default shell +- Grants passwordless sudo access + +**Security Note:** This is for workshop/testing only. Production environments should use proper authentication. + +--- + +```dockerfile +WORKDIR /home/appiumuser +``` +**Working Directory:** Sets default directory for subsequent commands and container entry point + +--- + +```dockerfile +COPY setup_environment.sh start-appium.sh appium.conf.json ./ +``` +**File Copying:** +- Copies setup script to container +- Copies Appium startup script to container +- Copies Appium configuration +- Files owned by root initially + +--- + +```dockerfile +RUN chmod +x setup_environment.sh start-appium.sh && \ + chown appiumuser:appiumuser setup_environment.sh start-appium.sh appium.conf.json +``` +**Permissions:** +- Makes both scripts executable +- Changes ownership to appiumuser +- Ensures user can read config file + +--- + +```dockerfile +USER appiumuser +``` +**Switch User:** All subsequent commands run as `appiumuser`, not root + +**Security Benefit:** Limits potential damage from vulnerabilities + +--- + +```dockerfile +RUN ./setup_environment.sh +``` +**Build-Time Setup:** +- Runs the complete setup script during `docker build` +- Installs NVM, Node.js, Appium, SDKMAN, Java, Maven, Android SDK +- All tools baked into the image +- Container startup is instant + +**Why at build time?** +- āœ… Faster container startup (no setup delay) +- āœ… Consistent environment (setup runs once) +- āœ… Easier debugging (build fails early if issues) +- āŒ Larger image size (~2-3GB) + +--- + +```dockerfile +ENV NVM_DIR=/home/appiumuser/.nvm \ + SDKMAN_DIR=/home/appiumuser/.sdkman \ + ANDROID_SDK_ROOT=/home/appiumuser/android_sdk +``` +**Environment Variables:** +- Sets paths for installed tools +- Makes tools accessible in container +- Required for interactive shells + +--- + +```dockerfile +ENV PATH="${NVM_DIR}/versions/node/$(ls ${NVM_DIR}/versions/node 2>/dev/null | head -1)/bin:${SDKMAN_DIR}/candidates/java/current/bin:${ANDROID_SDK_ROOT}/cmdline-tools/latest/bin:${ANDROID_SDK_ROOT}/platform-tools:$(ls -d ${ANDROID_SDK_ROOT}/build-tools/* 2>/dev/null | head -1):${PATH}" +``` +**PATH Configuration:** +- Adds Node.js binaries (dynamically determined version) +- Adds Java binaries from SDKMAN +- Adds Android SDK tools (cmdline-tools, platform-tools) +- Adds build-tools (dynamically determined latest version) + +**Dynamic version detection:** Uses `ls` to automatically find installed versions, no hardcoded paths + +--- + +```dockerfile +CMD ["./start-appium.sh"] +``` +**Container Startup:** +- Automatically starts Appium server on port 4723 +- All tools already installed and available +- No setup delay, server ready immediately + +**Server Features:** +- Loads environment configurations automatically +- Validates driver installations +- Displays configuration and status information + +--- + +## Appium Configuration + +### appium.conf.json + +```json +{ + "server": { + "port": 4723, + "allow-cors": true, + "use-plugins": ["devtools"], + "plugin": { + "devtools": {} + }, + "allow-insecure": ["chromedriver_autodownload", "adb_shell"], + "relaxed-security": true, + "driver": { + "uiautomator2": { + "chromedriver-executable-dir": "/home/appiumuser/secugrow/chromedrivers", + "chromedriverStorageDir": "/home/appiumuser/secugrow/chromedrivers" + } + } + } +} +``` + +### Configuration Explained + +#### Server Settings + +| Setting | Value | Purpose | +|---------|-------|---------| +| `port` | 4723 | Default Appium server port | +| `allow-cors` | true | Enables CORS for web-based clients | +| `relaxed-security` | true | Allows insecure features (workshop only) | + +#### Plugins + +```json +"use-plugins": ["devtools"] +``` +- Enables Chrome DevTools protocol +- Allows web browser automation +- Provides advanced debugging features + +#### Security Settings + +```json +"allow-insecure": ["chromedriver_autodownload", "adb_shell"] +``` +- **chromedriver_autodownload**: Automatically downloads matching chromedriver versions +- **adb_shell**: Allows execution of adb shell commands through Appium +- **Workshop Only**: Both features should be disabled in production + +āš ļø **Security Warning:** `relaxed-security` and `allow-insecure` are for testing only! + +#### Driver Configuration + +```json +"driver": { + "uiautomator2": { + "chromedriver-executable-dir": "/home/appiumuser/secugrow/chromedrivers", + "chromedriverStorageDir": "/home/appiumuser/secugrow/chromedrivers" + } +} +``` + +**UIAutomator2 Driver:** +- Default Android automation driver +- Stores chromedrivers in custom location +- Persists across Appium versions + +**Chromedriver Storage:** +- Location: `/home/appiumuser/secugrow/chromedrivers` (Docker) or `~/secugrow/chromedrivers` (bare metal) +- Created by `setup_environment.sh` +- Caches downloaded chromedrivers + +--- + +## Build Instructions + +### Prerequisites + +- Docker installed and running +- Docker daemon accessible +- Sufficient disk space (~3-4GB for final image) +- Good internet connection (downloads ~500MB during build) + +### Building the Docker Image + +#### Navigate to Directory + +```bash +cd /path/to/secugrow/workshop_setup +``` + +#### Build Command + +```bash +docker build -t workshop-env:latest . +``` + +**Command Breakdown:** +- `docker build`: Build a Docker image +- `-t workshop-env:latest`: Tag image as "workshop-env" with "latest" version +- `.`: Build context is current directory (uses `Dockerfile` by default) + +#### Build Process + +The build process will: +1. Pull Ubuntu 22.04 base image +2. Install system packages (curl, wget, unzip, etc.) +3. Create appiumuser with sudo privileges +4. Copy setup script and Appium config +5. **Run complete setup script** (takes 5-10 minutes): + - Install NVM and Node.js + - Install Appium globally + - Configure Appium with custom settings + - Install SDKMAN + - Install Java 23 and Maven 3.9.5 + - Download and extract Android SDK (latest version) + - Install Android SDK components (platform-tools, build-tools) +6. Set environment variables +7. Configure PATH with all tools + +**Build Time:** Expect 5-15 minutes depending on internet speed + +**Expected Output:** +``` +[+] Building 456.3s (12/12) FINISHED + => [internal] load build definition from Dockerfile + => [internal] load .dockerignore + => [internal] load metadata for docker.io/library/ubuntu:22.04 + => [1/7] FROM docker.io/library/ubuntu:22.04 + => [2/7] RUN apt-get update && apt-get install -y... + => [3/7] RUN useradd -m -s /bin/bash appiumuser... + => [4/7] COPY setup_environment.sh appium.conf.json ./ + => [5/7] RUN chmod +x setup_environment.sh... + => [6/7] RUN ./setup_environment.sh # <- This takes 5-10 minutes + => [7/7] ENV PATH=... + => exporting to image + => => naming to docker.io/library/workshop-env:latest +``` + +During step [6/7], you'll see colorful output: +``` +ℹ Starting complete environment setup... +ℹ Checking prerequisites... +āœ” Prerequisites confirmed +ℹ Installing NVM... +āœ” NVM installed successfully +ℹ Installing Node.js and npm using NVM... +āœ” Node.js and npm installed successfully +ℹ Installing the latest version of Appium... +āœ” Appium installed successfully. Version: 2.x.x +... +āœ” All installations completed successfully +āœ” Setup complete! All tools are now available. +====================================== + Installed Component Versions +====================================== +... +``` + +#### Verify Image + +```bash +docker images | grep workshop-env +``` + +**Expected Output:** +``` +workshop-env latest a1b2c3d4e5f6 2 minutes ago 2.8GB +``` + +**Note:** Image size is larger (~2-3GB) because all tools are pre-installed + +--- + +## Usage Instructions + +### Running the Container + +#### Basic Run Command + +```bash +docker run --rm -it workshop-env:latest +``` + +**Options:** +- `--rm`: Remove container after exit +- `-it`: Interactive terminal + +#### Run with USB Device Access + +For connecting Android devices: + +```bash +docker run --rm -it \ + --privileged \ + -v /dev/bus/usb:/dev/bus/usb \ + workshop-env:latest +``` + +**Options:** +- `--privileged`: Grant extended privileges +- `-v /dev/bus/usb:/dev/bus/usb`: Mount USB devices + +#### Run with Port Mapping + +To access Appium from host machine: + +```bash +docker run --rm -it \ + -p 4723:4723 \ + workshop-env:latest +``` + +**Port Mapping:** +- `-p 4723:4723`: Maps container port 4723 to host port 4723 +- Allows external Appium client connections + +#### Run as Daemon (Background) + +```bash +docker run -d \ + --name workshop-container \ + -p 4723:4723 \ + -v /dev/bus/usb:/dev/bus/usb \ + --privileged \ + workshop-env:latest +``` + +**Options:** +- `-d`: Detached mode (background) +- `--name workshop-container`: Named container for easy reference + +**Attach to Running Container:** +```bash +docker exec -it workshop-container /bin/bash +``` + +#### Full Production Command + +```bash +docker run -d \ + --name appium-server \ + --restart unless-stopped \ + -p 4723:4723 \ + -v /dev/bus/usb:/dev/bus/usb \ + -v appium-data:/home/appiumuser \ + --privileged \ + workshop-env:latest +``` + +**Additional Options:** +- `--restart unless-stopped`: Auto-restart on failure +- `-v appium-data:/home/appiumuser`: Persistent volume + +### Container Startup Process + +When the container starts, it will: + +1. **Open interactive bash shell immediately** - No setup delay! +2. All tools are already installed and available +3. Environment variables already configured + +**Why so fast?** Setup ran during `docker build`, not at container startup. + +### Using the Environment + +You immediately have access to all tools: + +```bash +# Check Node.js +node -v +npm -v + +# Check Appium +appium --version +appium driver list + +# Check Java +java -version +mvn -v + +# Check Android SDK +echo $ANDROID_SDK_ROOT +adb --version +``` + +### Starting Appium Server + +#### With Default Config + +```bash +appium +``` + +#### With Custom Config + +```bash +appium --config ~/.appium/appium.conf.json +``` + +#### In Background + +```bash +appium > /tmp/appium.log 2>&1 & +``` + +### Connecting Android Devices + +#### List Connected Devices + +```bash +adb devices +``` + +**Expected Output:** +``` +List of devices attached +ABC123456789 device +``` + +#### Troubleshooting Device Connection + +If no devices appear: + +1. **Check USB connection:** + ```bash + lsusb + ``` + +2. **Restart ADB server:** + ```bash + adb kill-server + adb start-server + ``` + +3. **Check device permissions:** + ```bash + ls -l /dev/bus/usb/*/* + ``` + +--- + +## Bare Metal Installation + +### Prerequisites + +- Ubuntu 22.04 (or compatible Linux distribution) +- User account with sudo privileges +- Internet connection + +### Installation Steps + +#### 1. Download Files + +```bash +cd ~ +mkdir workshop-setup +cd workshop-setup + +# Download setup script +wget https://path-to-your-repo/setup_environment.sh + +# Download Appium config +wget https://path-to-your-repo/appium.conf.json + +# Make executable +chmod +x setup_environment.sh +``` + +#### 2. Run Setup Script + +```bash +./setup_environment.sh +``` + +#### 3. Activate Environment + +The script automatically sources the shell config, but for new terminals: + +```bash +source ~/.bashrc +# or +source ~/.zshrc +``` + +#### 4. Verify Installation + +```bash +# Check all tools +node -v +npm -v +appium --version +java -version +mvn -v +echo $ANDROID_SDK_ROOT +``` + +### Post-Installation + +#### Add User to plugdev Group (for USB access) + +```bash +sudo usermod -aG plugdev $USER +``` + +Log out and log back in for changes to take effect. + +#### Configure udev Rules for Android Devices + +Create `/etc/udev/rules.d/51-android.rules`: + +```bash +sudo tee /etc/udev/rules.d/51-android.rules > /dev/null <> ~/.bashrc +``` + +#### 2. Android SDK Not Found + +**Symptom:** +``` +sdkmanager: command not found +``` + +**Solution:** +```bash +# Check if ANDROID_SDK_ROOT is set +echo $ANDROID_SDK_ROOT + +# If not set, source shell config +source ~/.bashrc + +# Verify PATH includes Android tools +echo $PATH | grep android +``` + +#### 3. NVM Command Not Found + +**Symptom:** +``` +nvm: command not found +``` + +**Solution:** +```bash +# Load NVM manually +export NVM_DIR="$HOME/.nvm" +[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" + +# Verify +nvm --version +``` + +#### 4. Appium Can't Find Chromedriver + +**Symptom:** +``` +An unknown server-side error occurred while processing the command. +Original error: Could not find a driver for your browser +``` + +**Solution:** +```bash +# Check chromedriver directory exists +ls -la ~/secugrow/chromedrivers + +# If not, create it +mkdir -p ~/secugrow/chromedrivers + +# Download chromedriver manually +appium driver install uiautomator2 +``` + +#### 5. Permission Denied on USB Device + +**Symptom:** +``` +adb: insufficient permissions for device +``` + +**Solution:** +```bash +# Check USB permissions +ls -l /dev/bus/usb/*/* + +# Add user to plugdev group +sudo usermod -aG plugdev $USER + +# Restart udev +sudo systemctl restart udev + +# Re-login required +``` + +#### 6. Docker Build Fails + +**Symptom:** +``` +failed to solve: process "/bin/sh -c ..." did not complete successfully +``` + +**Solution:** +```bash +# Check Docker disk space +docker system df + +# Clean up if needed +docker system prune -a + +# Rebuild with no cache +docker build --no-cache -t workshop-env:latest . +``` + +#### 7. Container Exits Immediately + +**Symptom:** +Container stops right after starting + +**Solution:** +```bash +# Check logs +docker logs + +# Run interactively to see errors +docker run --rm -it workshop-env:latest /bin/bash + +# Check if setup script fails +./setup_environment.sh +``` + +### Debug Mode + +Enable debug output in `setup_environment.sh`: + +```bash +# Add at the beginning of the script +set -x # Print each command before execution +set -e # Exit on error +``` + +### Getting Help + +If issues persist: + +1. **Check logs**: Review complete output of `setup_environment.sh` +2. **Verify prerequisites**: Ensure all base packages are installed +3. **Test components individually**: Install each tool manually to identify failing step +4. **Check network**: Ensure internet access for downloads +5. **Review permissions**: Verify user has sudo access + +--- + +## Advanced Configuration + +### Customizing Java Version + +Edit `setup_environment.sh`: + +```bash +# Change this line: +sdk install java 23.0.2-librca + +# To: +sdk install java 17.0.9-librca # For Java 17 +``` + +### Customizing Node.js Version + +```bash +# After NVM installation, specify version: +nvm install 20.11.0 +nvm use 20.11.0 +``` + +### Adding Additional Android SDK Packages + +Edit `install_sdk_components()` function: + +```bash +yes | "$ANDROID_CMDLINE_TOOLS/bin/sdkmanager" \ + --sdk_root="$ANDROID_SDK_ROOT_DIR" \ + --install \ + "platform-tools" \ + "platforms;android-33" \ + "platforms;android-34" \ # Add Android 14 + "$LATEST_BUILD_TOOLS" \ # Uses dynamically detected version + "system-images;android-33;google_apis;x86_64" # Add emulator image +``` + +### Persistent Docker Volumes + +Create named volumes for persistence: + +```bash +# Create volume +docker volume create appium-home + +# Run with volume +docker run -d \ + -v appium-home:/home/appiumuser \ + workshop-env:latest +``` + +**Benefits:** +- Data persists across container restarts +- No need to reconfigure on container recreation + +**Note:** With build-time setup, the environment is already configured in the image, so volumes are mainly useful for persisting user data, not setup state. + +--- + +## Performance Optimization + +### Docker Build Optimization + +#### Use Build Cache + +```bash +# First build (slow, 5-15 minutes) +docker build -t workshop-env:latest . + +# Subsequent builds use cache (fast, <1 minute if no changes) +docker build -t workshop-env:latest . +``` + +**Cache Benefits:** +- Docker caches each layer +- Only re-runs changed steps +- Modifying `setup_environment.sh` only re-runs from that step onwards + +#### Multi-stage Builds (Advanced) + +For smaller final images: + +```dockerfile +# Stage 1: Setup +FROM ubuntu:22.04 AS setup +# ... run setup_environment.sh ... + +# Stage 2: Runtime +FROM ubuntu:22.04 +COPY --from=setup /home/appiumuser /home/appiumuser +# ... only copy what's needed ... +``` + +### Container Resource Limits + +```bash +docker run \ + --memory="2g" \ + --cpus="2" \ + workshop-env:latest +``` + +--- + +## Security Considerations + +### Workshop vs Production + +āš ļø **This setup is designed for workshops/testing, NOT production!** + +#### Insecure Settings + +| Setting | Risk | Production Fix | +|---------|------|----------------| +| `relaxed-security: true` | Allows dangerous features | Remove or set to `false` | +| `allow-insecure` | Auto-downloads executables | Remove completely | +| NOPASSWD sudo | Full root access | Use proper authentication | +| `--privileged` flag | Container escape risk | Use `--device` instead | + +### Production Recommendations + +1. **Remove relaxed security**: + ```json + { + "server": { + "port": 4723, + "allow-cors": false, + "relaxed-security": false + } + } + ``` + +2. **Use specific device permissions**: + ```bash + docker run --device=/dev/bus/usb/001/002 ... + ``` + +3. **Run as non-root without sudo**: + Remove `echo "appiumuser ALL=(ALL) NOPASSWD: ALL"` from Dockerfile + +4. **Use secrets management**: + Don't hardcode passwords or API keys + +--- + +## Maintenance + +### Updating Components + +#### Update Node.js + +```bash +nvm install node # Latest version +nvm use node +nvm alias default node +``` + +#### Update Appium + +```bash +npm update -g appium +``` + +#### Update Java + +```bash +sdk list java +sdk install java +sdk default java +``` + +#### Update Android SDK + +```bash +sdkmanager --update +``` + +### Backup Configuration + +```bash +# Backup shell config +cp ~/.bashrc ~/.bashrc.backup + +# Backup Appium config +cp ~/.appium/appium.conf.json ~/appium.conf.json.backup + +# Backup Android SDK +tar -czf android_sdk_backup.tar.gz ~/android_sdk +``` + +--- + +## Appendix + +### File Locations + +| Component | Location | +|-----------|----------| +| Node.js | `~/.nvm/versions/node/` | +| Appium | `~/.nvm/versions/node//lib/node_modules/appium` | +| Java | `~/.sdkman/candidates/java/` | +| Maven | `~/.sdkman/candidates/maven/` | +| Android SDK | `$(pwd)/android_sdk` or custom location | +| Appium Config | `~/.appium/appium.conf.json` | +| Chromedrivers | `~/secugrow/chromedrivers` | + +### Environment Variables + +```bash +# Node.js / NVM +NVM_DIR=$HOME/.nvm + +# SDKMAN +SDKMAN_DIR=$HOME/.sdkman + +# Java +JAVA_HOME=~/.sdkman/candidates/java/current + +# Android +ANDROID_SDK_ROOT=/android_sdk +ANDROID_CMDLINE_TOOLS=$ANDROID_SDK_ROOT/cmdline-tools/latest +ANDROID_PLATFORM_TOOLS=$ANDROID_SDK_ROOT/platform-tools +ANDROID_BUILD_TOOLS=$(ls -d $ANDROID_SDK_ROOT/build-tools/* 2>/dev/null | head -1) + +# PATH additions +PATH=$NVM_DIR/versions/node//bin:$PATH +PATH=$JAVA_HOME/bin:$PATH +PATH=$ANDROID_CMDLINE_TOOLS/bin:$PATH +PATH=$ANDROID_PLATFORM_TOOLS:$PATH +PATH=$ANDROID_BUILD_TOOLS:$PATH +``` + +### Useful Commands + +```bash +# Docker +docker ps # List running containers +docker images # List images +docker logs # View logs +docker exec -it bash # Enter container +docker stop # Stop container +docker rm # Remove container +docker rmi # Remove image + +# Appium +appium --version # Version +appium driver list # List drivers +appium driver install uiautomator2 # Install driver +appium plugin list # List plugins + +# Android +adb devices # List devices +adb logcat # View device logs +adb shell # Device shell +adb install app.apk # Install app +adb uninstall com.package.name # Uninstall app + +# SDKMAN +sdk list java # Available Java versions +sdk list maven # Available Maven versions +sdk current # Current versions +sdk use java # Switch version + +# NVM +nvm list # Installed versions +nvm list-remote # Available versions +nvm use # Switch version +``` + +--- + +## Changelog + +### Version 1.0 (2025-10-12) +- Initial documentation +- Unified setup script +- Docker containerization +- Appium configuration + +--- + +## License + +See LICENSE file in repository root. + +--- + +## Support + +For issues or questions: +1. Check [Troubleshooting](#troubleshooting) section +2. Review script output logs +3. Contact workshop administrators + +--- + +**Document Version:** 1.0 +**Last Updated:** 2025-10-12 +**Author:** Workshop Team diff --git a/appium/appium.conf.json b/appium/appium.conf.json new file mode 100644 index 0000000..d532aeb --- /dev/null +++ b/appium/appium.conf.json @@ -0,0 +1,18 @@ +{ + "server": { + "port": 4723, + "allow-cors": true, + "use-plugins": ["devtools"], + "plugin": { + "devtools": {} + }, + "allow-insecure": ["chromedriver_autodownload", "adb_shell"], + "relaxed-security": true, + "driver": { + "uiautomator2": { + "chromedriver-executable-dir": "${HOME}/chromedrivers", + "chromedriverStorageDir": "${HOME}/chromedrivers" + } + } + } +} diff --git a/appium/start-appium.sh b/appium/start-appium.sh new file mode 100644 index 0000000..3eed451 --- /dev/null +++ b/appium/start-appium.sh @@ -0,0 +1,75 @@ +#!/bin/bash + +# Set TERM for Docker environment +export TERM=${TERM:-xterm} + +# Color definitions and helper functions +RED=$(tput setaf 1) +GREEN=$(tput setaf 2) +YELLOW=$(tput setaf 3) +BLUE=$(tput setaf 4) +CYAN=$(tput setaf 6) +MAGENTA=$(tput setaf 5) +RESET=$(tput sgr0) + +ok() { printf "%sāœ” %s%s\n" "$GREEN" "$*" "$RESET"; } +warn() { printf "%s⚠ %s%s\n" "$YELLOW" "$*" "$RESET"; } +error() { printf "%sāœ– %s%s\n" "$RED" "$*" "$RESET"; } +info() { printf "%sℹ %s%s\n" "$BLUE" "$*" "$RESET"; } +section() { printf "\n%s%s%s\n" "$CYAN" "$*" "$RESET"; } + +# Load all environment configurations +source ~/.bashrc +source ~/.nvm/nvm.sh +source ~/.sdkman/bin/sdkman-init.sh + +# Verify appium is available +if ! command -v appium &> /dev/null; then + error "Appium not found in PATH" + info "Available commands: $(which node npm || echo 'none')" + info "NODE_PATH: $(which node || echo 'not found')" + info "PATH: $PATH" + exit 1 +fi + +# Display Appium version and driver information +ok "Appium found: $(appium --version)" + +# List installed drivers +section "Checking installed Appium drivers..." +DRIVER_LIST=$(appium driver list 2>&1) + +# Debug: show the raw output +info "Raw driver list output:" +echo "$DRIVER_LIST" + +# Debug: show what grep finds +info "Searching for uiautomator2 lines:" +echo "$DRIVER_LIST" | grep "uiautomator2" || info "No matches found" + +# Check if UIAutomator2 is installed +if echo "$DRIVER_LIST" | grep -q "uiautomator2.*\[installed"; then + ok "UIAutomator2 driver is installed" +else + error "UIAutomator2 driver is NOT installed" + warn "UIAutomator2 driver not found. Server will start but Android automation may not work." +fi + +# Check if Appium configuration file exists +CONFIG_FILE="$HOME/appium/appium.conf.json" + +if [ -f "$CONFIG_FILE" ]; then + ok "Found Appium configuration file: $CONFIG_FILE" + section "Configuration contents:" + cat "$CONFIG_FILE" + info "--- End of configuration ---" + + # Start Appium server - configuration will be automatically loaded from ~/.appium/ + section "Starting Appium server with configuration file (auto-loaded)..." + exec appium --address 0.0.0.0 +else + warn "No Appium configuration file found at $CONFIG_FILE" + section "Starting Appium server with command line parameters..." + # Fallback to command line parameters + exec appium --allow-cors --allow-insecure=*:adb_shell --address 0.0.0.0 --port 4723 +fi \ No newline at end of file diff --git a/legacy/Dockerfile b/legacy/Dockerfile new file mode 100644 index 0000000..8531880 --- /dev/null +++ b/legacy/Dockerfile @@ -0,0 +1,117 @@ +FROM ubuntu:22.04 + +ENV DEBIAN_FRONTEND=noninteractive +ENV DISPLAY=:0 +ENV XAUTHORITY=/root/.Xauthority + +# Workaround: Ignore missing GPG signatures (for testing/lab only) +RUN set -eux; \ + echo 'Acquire::AllowInsecureRepositories "true";' > /etc/apt/apt.conf.d/80insecure; \ + echo 'Acquire::AllowDowngradeToInsecureRepositories "true";' >> /etc/apt/apt.conf.d/80insecure; \ + echo 'APT::Get::AllowUnauthenticated "true";' >> /etc/apt/apt.conf.d/80insecure + +# Run update/upgrade ignoring missing signatures; install key base packages at the same time +RUN apt-get update || true && \ + apt-get upgrade -y || true && \ + apt-get install -y --allow-unauthenticated \ + ca-certificates \ + sudo \ + curl \ + wget \ + bash \ + tzdata \ + unzip \ + xvfb \ + zip \ + ffmpeg \ + gnupg \ + libgconf-2-4 \ + libqt5webkit5 \ + openjdk-17-jdk \ + zip \ + unzip \ + build-essential \ + git \ + android-sdk-platform-tools \ + && rm -rf /var/lib/apt/lists/* + +ARG USER_PASS=appiumtest +RUN groupadd appiumuser --gid 1401 && \ + useradd appiumuser --uid 1400 --gid 1401 --create-home --shell /bin/bash && \ + usermod -aG sudo appiumuser && \ + echo appiumuser:${USER_PASS} | chpasswd && \ + echo 'appiumuser ALL=(ALL) NOPASSWD: ALL' >> /etc/sudoers + +WORKDIR /home/appiumuser + +# Install SDKMAN and Java 23 +RUN curl -s "https://get.sdkman.io" | bash && \ + bash -c "source /root/.sdkman/bin/sdkman-init.sh && \ + sdk install java 23-open && \ + sdk default java 23-open" + +ENV JAVA_HOME=/root/.sdkman/candidates/java/current +ENV PATH=$PATH:$JAVA_HOME/bin + +# Set Android SDK variables +ENV SDK_VERSION=commandlinetools-linux-11076708_latest +ENV ANDROID_BUILD_TOOLS_VERSION=34.0.0 +ENV ANDROID_FOLDER_NAME=cmdline-tools +ENV ANDROID_DOWNLOAD_PATH=/home/appiumuser/${ANDROID_FOLDER_NAME} +ENV ANDROID_HOME=/opt/android +ENV ANDROID_TOOL_HOME=/opt/android/${ANDROID_FOLDER_NAME} + +# Download and unpack Android command-line tools (universal) +RUN wget -O tools.zip https://dl.google.com/android/repository/${SDK_VERSION}.zip && \ + unzip tools.zip && rm tools.zip && \ + chmod a+x -R ${ANDROID_DOWNLOAD_PATH} && \ + chown -R 1400:1401 ${ANDROID_DOWNLOAD_PATH} && \ + mkdir -p ${ANDROID_TOOL_HOME} && \ + mv ${ANDROID_DOWNLOAD_PATH} ${ANDROID_TOOL_HOME}/tools +ENV PATH=$PATH:${ANDROID_TOOL_HOME}/tools:${ANDROID_TOOL_HOME}/tools/bin + +# Install SDK components EXCEPT platform-tools (already present as arm64 via apt) +RUN bash -c "mkdir -p ~/.android && \ + touch ~/.android/repositories.cfg && \ + echo y | sdkmanager 'build-tools;$ANDROID_BUILD_TOOLS_VERSION'" && \ + mv ~/.android .android && \ + chown -R 1400:1401 .android + +ENV PATH=$PATH:$ANDROID_HOME/platform-tools:$ANDROID_HOME/build-tools + +# Symlink native adb/fastboot to Android SDK structure for compatibility +RUN mkdir -p $ANDROID_HOME/platform-tools && \ + ln -sf /usr/lib/android-sdk/platform-tools/adb $ANDROID_HOME/platform-tools/adb && \ + ln -sf /usr/lib/android-sdk/platform-tools/fastboot $ANDROID_HOME/platform-tools/fastboot + +# NodeSource signing also broken sometimes: Download/install NodeJS directly from official tarball +ENV NODE_VERSION=22.2.0 +RUN cd /tmp && \ + curl -O https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION-linux-x64.tar.xz && \ + tar -xJf node-v$NODE_VERSION-linux-x64.tar.xz && \ + mv node-v$NODE_VERSION-linux-x64 /opt/node && \ + ln -sf /opt/node/bin/node /usr/local/bin/node && \ + ln -sf /opt/node/bin/npm /usr/local/bin/npm && \ + ln -sf /opt/node/bin/npx /usr/local/bin/npx && \ + rm node-v$NODE_VERSION-linux-x64.tar.xz + +ENV PATH=$PATH:/opt/node/bin + +# Install Appium globally +ENV APPIUM_VERSION=2.16.2 +RUN npm install -g appium@${APPIUM_VERSION} \ + && npm cache clean --force + +RUN chown -R 1400:1401 /opt/node /usr/local/bin/node /usr/local/bin/npm /usr/local/bin/npx /usr/lib/node_modules/appium || true + +USER 1400:1401 + +# Install basic Android drivers via Appium CLI +ENV APPIUM_DRIVER_UIAUTOMATOR2_VERSION="4.0.2" +# Only install uiautomator2 Appium driver +ENV APPIUM_DRIVER_UIAUTOMATOR2_VERSION="4.0.2" +RUN appium driver install --source=npm appium-uiautomator2-driver@${APPIUM_DRIVER_UIAUTOMATOR2_VERSION} + +EXPOSE 4723 + +CMD ["appium", "--allow-insecure", "chromedriver_autodownload", "--address", "0.0.0.0"] \ No newline at end of file diff --git a/legacy/README.md b/legacy/README.md new file mode 100644 index 0000000..20c40d4 --- /dev/null +++ b/legacy/README.md @@ -0,0 +1,121 @@ +# Workshop Setup + + +## latest Dockerfile update + +build the image with provided Dockerfile + +```shell +docker build -t appium/appium:secugrow . +``` + +starting the docker image and running appium + +```shell +docker run --privileged -d -it -p 4723:4723 -v /dev/bus/usb:/dev/bus/usb --name appium-container appium/appium:secugrow +``` + + +# Prerequisites +Install Java for your OS (recommended Version 21 or above) + +make the script executable via `chmod u+x install_tools.sh` and execute it afterwards via `./install_tools.sh` + + +### Android SDK and build-tools + +make the script executable via `chmod u+x install_android_sdk.sh` and execute it afterwards via `./install_android_sdk.sh`. +It will download all necessary files and edit your `~/.bashrc` or `~/.zshrc` or `~/.profile` with following env-variables. + +```shell + +export ANDROID_HOME=$HOME/installed/android_sdk +export ANDROID_PLATFORM_TOOLS=$ANDROID_HOME/platform-tools +export ANDROID_CMD_LINE_TOOLS=$ANDROID_HOME/cmdline-tools/latest +export ANDROID_BUILD_TOOLS_34=$ANDROID_HOME/build-tools/34.0.0 + +export PATH=$ANDROID_HOME:$ANDROID_PLATFORM_TOOLS:$ANDROID_CMD_LINE_TOOLS/bin:$ANDROID_BUILD_TOOLS_34 + +``` + +## Installation for Windows + +### node installation +https://nodejs.org/en/download/ + + +e.g. +### Android SDK with Android Studio +https://developer.android.com/studio/index.html +Goto Configure environment variables: + +```System Properties -> Environment Variables -> System Variables -> New -> ANDROID_HOME``` + +and set value as **C:Users\YourUser\AppData\Local\Android\SDK** (path where SDK is installed) + +Add the Android SDK paths into your existing PATH variable value as `%ANDROID_HOME%\tools;%ANDROID_HOME%\platform-tools;%ANDROID_HOME%\build-tools` + +--- + +## fallback for nvm (https://www.freecodecamp.org/news/node-version-manager-nvm-install-guide/) + +execute in terminal + +``` +brew install nvm +# or via +curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.1/install.sh | bash +``` + +if not automatically added during installation, do manually after install + +``` +export NVM_DIR="$([ -z "${XDG_CONFIG_HOME-}" ] && printf %s "${HOME}/.nvm" || printf %s "${XDG_CONFIG_HOME}/nvm")" +[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" +``` + +## fallback for sdkman (https://sdkman.io/install/) + +``` +curl -s "https://get.sdkman.io" | bash +``` + +Follow the on-screen instructions to wrap up the installation. Afterward, open a new terminal or run the following in the same shell: + +``` +source "$HOME/.sdkman/bin/sdkman-init.sh" +``` + +### working mvn command running the tests +``` +mvn test -Dbrowser=chrome -DbaseUrl="https://www.wikipedia.org" -Dcucumber.filter.tags=@all -Dcucumber.glue=at.ucaat.demo.stepdefinitions -Dcucumber.features=src/test/resources/features +``` + +### selenium-server download + +``` +java -jar selenium-server-4.30.0.jar standalone +``` + + +### appium plugins (i.e.: devtools-plugin) nachtraeglich installieren + +quelle: https://github.com/mykola-mokhnach/appium-devtools-plugin + +``` +appium plugin install --source npm appium-devtools-plugin +``` + +### starte appium mit spezifischen plugins + +``` +appium --use-plugins=devtools,element-wait +``` + + +--- + + + + + diff --git a/install_android_sdk.sh b/legacy/install_android_sdk.sh similarity index 66% rename from install_android_sdk.sh rename to legacy/install_android_sdk.sh index 36b38ba..73afc79 100755 --- a/install_android_sdk.sh +++ b/legacy/install_android_sdk.sh @@ -39,14 +39,7 @@ install_prerequisites() { # Check if unzip is installed if ! command -v unzip &> /dev/null; then print_msg "unzip could not be found, installing..." - if [[ "$OSTYPE" == "darwin"* ]]; then - if command -v brew &> /dev/null; then - brew install unzip - else - print_err_msg "Homebrew is not installed. Please install it first (https://brew.sh)." - exit 1 - fi - elif [[ "$OSTYPE" == "linux-gnu"* ]]; then + if [[ "$OSTYPE" == "linux-gnu"* ]]; then sudo apt-get update sudo apt-get install -y unzip else @@ -62,30 +55,32 @@ install_prerequisites() { download_and_extract_sdk() { print_msg "Downloading Android SDK..." - # Determine the URL based on the operating system - if [[ "$OSTYPE" == "darwin"* ]]; then - URL="https://dl.google.com/android/repository/commandlinetools-mac-11076708_latest.zip" - OUTPUT="commandlinetools-mac-11076708_latest.zip" - elif [[ "$OSTYPE" == "msys" || "$OSTYPE" == "cygwin" ]]; then - URL="https://dl.google.com/android/repository/commandlinetools-win-11076708_latest.zip" - OUTPUT="commandlinetools-win-11076708_latest.zip" - elif [[ "$OSTYPE" == "linux-gnu"* ]]; then - URL="https://dl.google.com/android/repository/commandlinetools-linux-11076708_latest.zip" - OUTPUT="commandlinetools-linux-11076708_latest.zip" - else - print_err_msg "Unsupported OS: $OSTYPE" - exit 1 + # Fetch the latest version from Android's repository XML + print_msg "Fetching latest commandlinetools version..." + REPO_XML=$(wget -qO- https://dl.google.com/android/repository/repository2-3.xml) + LATEST_VERSION=$(echo "$REPO_XML" | grep -oP 'commandlinetools-linux-[0-9]+_latest\.zip' | head -1) + + if [[ -z "$LATEST_VERSION" ]]; then + print_err_msg "Failed to fetch latest version. Falling back to known version." + LATEST_VERSION="commandlinetools-linux-11076708_latest.zip" fi + print_msg "Using version: $LATEST_VERSION" + URL="https://dl.google.com/android/repository/$LATEST_VERSION" + OUTPUT="$LATEST_VERSION" + ANDROID_SDK_ROOT_DIR="$(pwd)/android_sdk" if [[ -d "$ANDROID_SDK_ROOT_DIR" ]]; then - print_msg "Directory $ANDROID_SDK_ROOT_DIR already exists." - #exit 1 + print_err_msg "Directory $ANDROID_SDK_ROOT_DIR already exists. Please delete and run script again." + exit 1 else wget -O "$OUTPUT" "$URL" print_msg "Unzipping downloaded package..." - unzip -q "$OUTPUT" -d "$ANDROID_SDK_ROOT_DIR" + mkdir -p "$ANDROID_SDK_ROOT_DIR/cmdline-tools" + unzip -q "$OUTPUT" -d "$ANDROID_SDK_ROOT_DIR/cmdline-tools" + # Restructure to proper SDK layout: cmdline-tools/latest/ + mv "$ANDROID_SDK_ROOT_DIR/cmdline-tools/cmdline-tools" "$ANDROID_SDK_ROOT_DIR/cmdline-tools/latest" rm "$OUTPUT" # Clean up the downloaded ZIP file after unzipping fi } @@ -95,7 +90,7 @@ configure_environment() { print_msg "Configuring environment variables..." # Detect the current shell - CURRENT_SHELL=$(ps -p $(ps -o ppid= -p $$) -o comm= | sed 's/^-//') + CURRENT_SHELL=$(ps -p $(ps -o ppid= -p $$) -o comm=) # Determine the shell configuration file dynamically case "$CURRENT_SHELL" in @@ -103,14 +98,7 @@ configure_environment() { SHELL_CONFIG_FILE="$HOME/.zshrc" ;; bash) - if [[ "$OSTYPE" == "darwin"* ]]; then - # macOS: Prefer ~/.bash_profile, fallback to ~/.profile - if [[ -f "$HOME/.bash_profile" ]]; then - SHELL_CONFIG_FILE="$HOME/.bash_profile" - else - SHELL_CONFIG_FILE="$HOME/.profile" - fi - elif [[ "$OSTYPE" == "linux-gnu"* ]]; then + if [[ "$OSTYPE" == "linux-gnu"* ]]; then # Linux: Prefer ~/.bashrc, fallback to ~/.profile if [[ -f "$HOME/.bashrc" ]]; then SHELL_CONFIG_FILE="$HOME/.bashrc" @@ -154,8 +142,7 @@ configure_environment() { NR == insert_line { print "##### Android SDK Environment Variables (added on " current_date ") #####" print "export ANDROID_SDK_ROOT='"$ANDROID_SDK_ROOT_DIR"'" - print "export ANDROID_HOME='"$ANDROID_SDK_ROOT_DIR"'" - print "export ANDROID_CMDLINE_TOOLS=$ANDROID_SDK_ROOT/cmdline-tools" + print "export ANDROID_CMDLINE_TOOLS=$ANDROID_SDK_ROOT/cmdline-tools/latest" print "export ANDROID_PLATFORM_TOOLS=$ANDROID_SDK_ROOT/platform-tools" print "export ANDROID_BUILD_TOOLS=$ANDROID_SDK_ROOT/build-tools/34.0.0" print "export PATH=$ANDROID_CMDLINE_TOOLS/bin:$ANDROID_PLATFORM_TOOLS:$ANDROID_BUILD_TOOLS:$PATH" @@ -169,18 +156,23 @@ configure_environment() { install_sdk_components() { print_msg "Installing Android SDK components..." - ANDROID_CMDLINE_TOOLS="$ANDROID_SDK_ROOT_DIR/cmdline-tools" - if echo "$PATH" | grep -q "$ANDROID_SDK_ROOT_DIR"; then - yes | "$ANDROID_CMDLINE_TOOLS/bin/sdkmanager" --sdk_root="$ANDROID_SDK_ROOT_DIR" --install "platform-tools" "platforms;android-33" "build-tools;34.0.0" - print_msg "Android SDK installation completed successfully." - else - print_msg_multiline </dev/null || true + fi + + yes | "$ANDROID_CMDLINE_TOOLS/bin/sdkmanager" --sdk_root="$ANDROID_SDK_ROOT_DIR" --install "platform-tools" "platforms;android-33" "build-tools;34.0.0" + print_msg "Android SDK installation completed successfully." } # Main script execution diff --git a/install_tools.sh b/legacy/install_tools.sh similarity index 87% rename from install_tools.sh rename to legacy/install_tools.sh index 3aab663..a210317 100755 --- a/install_tools.sh +++ b/legacy/install_tools.sh @@ -16,6 +16,32 @@ print_err_msg() { printf "$(tput setaf 1)-> %s <-\n$(tput sgr0)" "$1" } +# Install prerequisites +install_prerequisites() { + print_msg "Checking prerequisites..." + + # Check if curl is installed + if ! command -v curl &> /dev/null; then + print_msg "curl could not be found, installing..." + if [[ "$OSTYPE" == "linux-gnu"* ]]; then + if command -v apt-get >/dev/null 2>&1; then + sudo apt-get update + sudo apt-get install -y curl + elif command -v yum >/dev/null 2>&1; then + sudo yum install -y curl + else + print_err_msg "Error: Unsupported package manager. Please install curl manually." + exit 1 + fi + else + print_err_msg "Error: Unsupported OS. Please install curl manually." + exit 1 + fi + fi + + print_msg "Prerequisites confirmed." +} + # Install NVM (Node Version Manager) install_nvm() { if command -v nvm >/dev/null 2>&1; then @@ -142,11 +168,11 @@ install_maven_and_java() { if command -v java >/dev/null 2>&1; then print_msg "Java is already installed" else - print_msg "Installing Java 21 via SDKMAN..." - # Install Java 21 - sdk install java 21.0.6-librca || print_msg "Java 21 is already installed." + print_msg "Installing Java 23 via SDKMAN..." + # Install Java 23 + sdk install java 23.0.2-librca || print_msg "Java 23 is already installed." - # Set Java 21 as the default version + # Set Java 23 as the default version sdk default java $(ls -A1 $SDKMAN_CANDIDATES_DIR/java | head -n 1) fi @@ -191,7 +217,7 @@ install_maven_and_java() { #source $SHELL_CONFIG_FILE if [ -z "$(java -version 2>&1 | grep '21')" ]; then - print_err_msg "Error: Java 21 was not installed or set properly or you need to source your $SHELL_CONFIG_FILE" + print_err_msg "Error: Java 23 was not installed or set properly or you need to source your $SHELL_CONFIG_FILE" exit 1 fi @@ -218,6 +244,7 @@ install_maven_and_java() { # Main script execution main() { + install_prerequisites install_nvm install_node_and_npm install_appium diff --git a/maveninfo/lifecycles.png b/maveninfo/lifecycles.png deleted file mode 100644 index adcce21..0000000 Binary files a/maveninfo/lifecycles.png and /dev/null differ diff --git a/setup_environment.sh b/setup_environment.sh new file mode 100644 index 0000000..5389928 --- /dev/null +++ b/setup_environment.sh @@ -0,0 +1,468 @@ +#!/bin/bash + +# Author: chris +# Reason: Set up complete environment for workshop +# Usage: chmod u+x setup_environment.sh && ./setup_environment.sh +# Description: This script installs all necessary tools including Node.js, Appium, Java, Maven, and Android SDK + +# Exit on error +set -e + +# Set default TERM if not set (for Docker builds) +export TERM=${TERM:-xterm} + +# Colors via tput (with fallback for environments without tput) +if command -v tput >/dev/null 2>&1 && tput setaf 1 >/dev/null 2>&1; then + RED=$(tput setaf 1) + GREEN=$(tput setaf 2) + YELLOW=$(tput setaf 3) + BLUE=$(tput setaf 4) + BOLD=$(tput bold) + RESET=$(tput sgr0) +else + # Fallback to ANSI escape codes if tput doesn't work + RED='\033[0;31m' + GREEN='\033[0;32m' + YELLOW='\033[0;33m' + BLUE='\033[0;34m' + BOLD='\033[1m' + RESET='\033[0m' +fi + +# Helper functions using printf +ok() { printf "${GREEN}āœ” %s${RESET}\n" "$*"; } +warn() { printf "${YELLOW}⚠ %s${RESET}\n" "$*"; } +error() { printf "${RED}āœ– %s${RESET}\n" "$*"; } +info() { printf "${BLUE}ℹ %s${RESET}\n" "$*"; } + +# Multiline output function for heredocs +print_multiline() { + printf "${BLUE}" + while IFS= read -r line; do + printf "%s\n" "$line" + done + printf "${RESET}" +} + +# Detect shell configuration file +detect_shell_config() { + CURRENT_SHELL=$(ps -p $(ps -o ppid= -p $$) -o comm= | sed 's/^-//') + + case "$CURRENT_SHELL" in + zsh) + SHELL_CONFIG_FILE="$HOME/.zshrc" + ;; + bash) + if [[ "$OSTYPE" == "linux-gnu"* ]]; then + if [[ -f "$HOME/.bashrc" ]]; then + SHELL_CONFIG_FILE="$HOME/.bashrc" + else + SHELL_CONFIG_FILE="$HOME/.profile" + fi + else + SHELL_CONFIG_FILE="$HOME/.bashrc" + fi + ;; + *) + SHELL_CONFIG_FILE="$HOME/.bashrc" + ;; + esac +} + +# Install basic prerequisites +install_prerequisites() { + info "Checking prerequisites..." + + # Check if curl is installed + if ! command -v curl &> /dev/null; then + warn "curl could not be found, installing..." + if [[ "$OSTYPE" == "linux-gnu"* ]]; then + if command -v apt-get >/dev/null 2>&1; then + sudo apt-get update + sudo apt-get install -y curl + elif command -v yum >/dev/null 2>&1; then + sudo yum install -y curl + else + error "Unsupported package manager. Please install curl manually." + exit 1 + fi + else + error "Unsupported OS. Please install curl manually." + exit 1 + fi + fi + + # Check if wget is installed + if ! command -v wget &> /dev/null; then + error "wget is not installed. Please install wget manually and rerun the script." + exit 1 + fi + + # Check if unzip is installed + if ! command -v unzip &> /dev/null; then + warn "unzip could not be found, installing..." + if [[ "$OSTYPE" == "linux-gnu"* ]]; then + sudo apt-get update + sudo apt-get install -y unzip + else + error "Unable to install unzip. Please install it manually." + exit 1 + fi + fi + + ok "Prerequisites confirmed" +} + +# Install NVM (Node Version Manager) +install_nvm() { + if command -v nvm >/dev/null 2>&1; then + ok "NVM is already installed" + else + info "Installing NVM..." + NVM_INSTALL_URL="https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.5/install.sh" + if command -v curl >/dev/null 2>&1; then + curl -o- "$NVM_INSTALL_URL" | bash + elif command -v wget >/dev/null 2>&1; then + wget -qO- "$NVM_INSTALL_URL" | bash + else + error "curl or wget is required to download NVM." + exit 1 + fi + # Load NVM in the current shell session + export NVM_DIR="$HOME/.nvm" + [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" + [ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion" + ok "NVM installed successfully" + fi +} + +# Install Node.js and npm +install_node_and_npm() { + if command -v npm >/dev/null 2>&1; then + ok "npm is already installed" + else + info "Installing Node.js and npm using NVM..." + + if [ -z "$(command -v nvm)" ]; then + error "NVM is not installed. Please check the installation." + exit 1 + fi + + # Install the latest LTS version of Node.js + nvm install --lts + nvm use --lts + + # Verify installation + if [ -z "$(command -v node)" ] || [ -z "$(command -v npm)" ]; then + error "Node.js or npm was not installed properly." + exit 1 + fi + + info "Node.js version: $(node -v)" + info "npm version: $(npm -v)" + ok "Node.js and npm installed successfully" + fi +} + +# Install the latest version of Appium +install_appium() { + info "Installing the latest version of Appium..." + if command -v npm >/dev/null 2>&1; then + npm install -g appium + else + error "npm is not installed. Appium installation failed." + exit 1 + fi + + # Verify Appium installation + if [ -z "$(command -v appium)" ]; then + error "Appium was not installed properly." + exit 1 + fi + ok "Appium installed successfully. Version: $(appium --version)" + + # Install UIAutomator2 driver + info "Installing UIAutomator2 driver..." + if appium driver install uiautomator2; then + ok "UIAutomator2 driver installed successfully" + else + error "Failed to install UIAutomator2 driver" + exit 1 + fi +} + +# Configure Appium +configure_appium() { + info "Configuring Appium..." + + # Create Appium config directory + APPIUM_CONFIG_DIR="$HOME/.appium" + mkdir -p "$APPIUM_CONFIG_DIR" + + # Check if appium.conf.json exists in the same directory as the script + SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + if [ -f "$SCRIPT_DIR/appium.conf.json" ]; then + info "Copying appium.conf.json to $APPIUM_CONFIG_DIR" + cp "$SCRIPT_DIR/appium.conf.json" "$APPIUM_CONFIG_DIR/appium.conf.json" + + # Create chromedriver directory referenced in config + CHROMEDRIVER_DIR="$HOME/secugrow/chromedrivers" + mkdir -p "$CHROMEDRIVER_DIR" + ok "Created chromedriver storage directory at $CHROMEDRIVER_DIR" + else + warn "No appium.conf.json found in script directory. Skipping Appium configuration." + fi +} + +# Install SDKMAN +install_sdkman() { + if [ -d "$HOME/.sdkman" ]; then + ok "SDKMAN is already installed. Skipping installation..." + # Load SDKMAN in the current shell session + export SDKMAN_DIR="$HOME/.sdkman" + [ -s "$SDKMAN_DIR/bin/sdkman-init.sh" ] && \. "$SDKMAN_DIR/bin/sdkman-init.sh" + else + if command -v zip >/dev/null 2>&1 && command -v unzip >/dev/null 2>&1; then + ok "zip and unzip are already installed" + else + info "Installing zip, unzip, and dependencies for SDKMAN..." + if command -v apt-get >/dev/null 2>&1; then + sudo apt-get update && sudo apt-get install -y zip unzip + elif command -v yum >/dev/null 2>&1; then + sudo yum install -y zip unzip + else + error "Unsupported package manager. Please install zip and unzip manually." + exit 1 + fi + fi + + info "Installing SDKMAN..." + SDKMAN_INSTALL_URL="https://get.sdkman.io" + if command -v curl >/dev/null 2>&1; then + curl -s "$SDKMAN_INSTALL_URL" | bash + elif command -v wget >/dev/null 2>&1; then + wget -qO- "$SDKMAN_INSTALL_URL" | bash + else + error "curl or wget is required to download SDKMAN." + exit 1 + fi + + # Load SDKMAN in the current shell session + export SDKMAN_DIR="$HOME/.sdkman" + [ -s "$SDKMAN_DIR/bin/sdkman-init.sh" ] && \. "$SDKMAN_DIR/bin/sdkman-init.sh" + + # Verify installation + if [ -z "$(command -v sdk)" ]; then + error "SDKMAN was not installed properly." + exit 1 + fi + ok "SDKMAN installed successfully" + fi +} + +# Install Maven and Java using SDKMAN +install_maven_and_java() { + info "Ensuring SDKMAN is loaded..." + # Ensure SDKMAN is loaded + [ -s "$HOME/.sdkman/bin/sdkman-init.sh" ] && . "$HOME/.sdkman/bin/sdkman-init.sh" + + if command -v java >/dev/null 2>&1; then + ok "Java is already installed" + else + info "Installing Java 23 via SDKMAN..." + # Install Java 23 + sdk install java 23.0.2-librca || ok "Java 23 is already installed" + + # Set Java 23 as the default version + sdk default java $(ls -A1 $SDKMAN_CANDIDATES_DIR/java | head -n 1) + fi + + detect_shell_config + info "Using shell configuration file: $SHELL_CONFIG_FILE" + + if [ -z "$(java -version 2>&1 | grep '23')" ]; then + error "Java 23 was not installed or set properly or you need to source your $SHELL_CONFIG_FILE" + exit 1 + fi + + ok "Java installed successfully: $(java -version 2>&1 | head -n 1)" + + if command -v mvn >/dev/null 2>&1;then + ok "Maven already installed" + else + info "Installing Maven 3.9.5 via SDKMAN..." + # Install Maven 3.9.5 + sdk install maven 3.9.5 || ok "Maven 3.9.5 is already installed" + sdk default maven $(ls -A1 $SDKMAN_CANDIDATES_DIR/maven | head -n 1) + fi + + if [ -z "$(command -v mvn)" ]; then + error "Maven 3.9.5 was not installed properly." + exit 1 + fi + + ok "Maven installed. Version: $(mvn -v | head -n 1)" +} + +# Download and extract Android SDK +download_and_extract_sdk() { + info "Downloading Android SDK..." + + # Fetch the latest version from Android's repository XML + info "Fetching latest commandlinetools version..." + REPO_XML=$(wget -qO- https://dl.google.com/android/repository/repository2-3.xml) + LATEST_VERSION=$(echo "$REPO_XML" | grep -oP 'commandlinetools-linux-[0-9]+_latest\.zip' | head -1) + + if [[ -z "$LATEST_VERSION" ]]; then + error "Failed to fetch latest version. Falling back to known version." + LATEST_VERSION="commandlinetools-linux-11076708_latest.zip" + fi + + info "Using version: $LATEST_VERSION" + URL="https://dl.google.com/android/repository/$LATEST_VERSION" + OUTPUT="$LATEST_VERSION" + + ANDROID_SDK_ROOT_DIR="$(pwd)/android_sdk" + + if [[ -d "$ANDROID_SDK_ROOT_DIR" ]]; then + error "Directory $ANDROID_SDK_ROOT_DIR already exists. Please delete and run script again." + exit 1 + else + info "Downloading Android SDK (~160MB, please wait)..." + if wget --progress=dot:mega -O "$OUTPUT" "$URL" 2>&1 | grep --line-buffered -E "[0-9]+%" | sed -u 's/.* \([0-9]\+%\).*/ [\1]/' | grep -E "(25%|50%|75%|100%)"; then + ok "Download complete" + else + error "Download failed" + exit 1 + fi + info "Unzipping downloaded package..." + mkdir -p "$ANDROID_SDK_ROOT_DIR/cmdline-tools" + unzip -q "$OUTPUT" -d "$ANDROID_SDK_ROOT_DIR/cmdline-tools" + # Restructure to proper SDK layout: cmdline-tools/latest/ + mv "$ANDROID_SDK_ROOT_DIR/cmdline-tools/cmdline-tools" "$ANDROID_SDK_ROOT_DIR/cmdline-tools/latest" + rm "$OUTPUT" # Clean up the downloaded ZIP file after unzipping + fi +} + +# Configure environment variables +configure_android_environment() { + info "Configuring Android environment variables..." + + detect_shell_config + info "Using shell configuration file: $SHELL_CONFIG_FILE" + + if grep -q "ANDROID_SDK_ROOT=" "$SHELL_CONFIG_FILE"; then + warn "ANDROID_SDK_ROOT is already configured in $SHELL_CONFIG_FILE. Skipping addition." + else + info "Adding ANDROID_SDK_ROOT and PATH modifications to $SHELL_CONFIG_FILE" + + # Find the line number of the last occurrence of 'export PATH=' + last_path_line=$(awk '/export PATH=/ { last_match=NR } END { print last_match }' "$SHELL_CONFIG_FILE") + + # If no 'export PATH=' is found, find the first occurrence of SDKMAN installation + if [[ -z "$last_path_line" ]]; then + sdkman_line=$(awk '/sdkman-init.sh/ { print NR; exit }' "$SHELL_CONFIG_FILE") + if [[ -z "$sdkman_line" ]]; then + # If no SDKMAN installation is found, append to the end of the file + sdkman_line=$(wc -l < "$SHELL_CONFIG_FILE") + fi + last_path_line=$((sdkman_line - 3)) + fi + + # Insert environment variables above the determined line + awk -v insert_line="$last_path_line" -v current_date="$(date '+%Y-%m-%d %H:%M:%S')" ' + { print } + NR == insert_line { + print "##### Android SDK Environment Variables (added on " current_date ") #####" + print "export ANDROID_SDK_ROOT='"$ANDROID_SDK_ROOT_DIR"'" + print "export ANDROID_CMDLINE_TOOLS=$ANDROID_SDK_ROOT/cmdline-tools/latest" + print "export ANDROID_PLATFORM_TOOLS=$ANDROID_SDK_ROOT/platform-tools" + print "# Build tools path uses wildcard to automatically find installed version" + print "export ANDROID_BUILD_TOOLS=$(ls -d $ANDROID_SDK_ROOT/build-tools/* 2>/dev/null | head -1)" + print "export PATH=$ANDROID_CMDLINE_TOOLS/bin:$ANDROID_PLATFORM_TOOLS:$ANDROID_BUILD_TOOLS:$PATH" + }' "$SHELL_CONFIG_FILE" > "$SHELL_CONFIG_FILE.tmp" && mv "$SHELL_CONFIG_FILE.tmp" "$SHELL_CONFIG_FILE" + + ok "ANDROID_SDK_ROOT and PATH modifications added to $SHELL_CONFIG_FILE" + fi +} + +# Install Android SDK components +install_sdk_components() { + info "Installing Android SDK components..." + + ANDROID_CMDLINE_TOOLS="$ANDROID_SDK_ROOT_DIR/cmdline-tools/latest" + + # Ensure SDKMAN is loaded to access Java + if [ -d "$HOME/.sdkman" ]; then + export SDKMAN_DIR="$HOME/.sdkman" + [ -s "$SDKMAN_DIR/bin/sdkman-init.sh" ] && source "$SDKMAN_DIR/bin/sdkman-init.sh" + fi + + # Verify Java is available + if ! command -v java &> /dev/null; then + error "Java is not available. Cannot proceed with SDK installation." + exit 1 + fi + + # Get latest build-tools version + LATEST_BUILD_TOOLS=$(yes | "$ANDROID_CMDLINE_TOOLS/bin/sdkmanager" --sdk_root="$ANDROID_SDK_ROOT_DIR" --list 2>/dev/null | grep "build-tools;" | head -1 | awk '{print $1}') + + if [[ -z "$LATEST_BUILD_TOOLS" ]]; then + warn "Could not detect latest build-tools, using fallback version 34.0.0" + LATEST_BUILD_TOOLS="build-tools;34.0.0" + else + info "Installing latest build-tools: $LATEST_BUILD_TOOLS" + fi + + yes | "$ANDROID_CMDLINE_TOOLS/bin/sdkmanager" --sdk_root="$ANDROID_SDK_ROOT_DIR" --install "platform-tools" "platforms;android-33" "$LATEST_BUILD_TOOLS" + + # Export build-tools version for later use + export ANDROID_BUILD_TOOLS_VERSION=$(echo "$LATEST_BUILD_TOOLS" | cut -d';' -f2) + + ok "Android SDK installation completed successfully." + info "Build tools version: $ANDROID_BUILD_TOOLS_VERSION" +} + +# Main script execution +main() { + info "Starting complete environment setup..." + + install_prerequisites + install_nvm + install_node_and_npm + install_appium + configure_appium + install_sdkman + install_maven_and_java + download_and_extract_sdk + configure_android_environment + install_sdk_components + + ok "All installations completed successfully." + + # Source the shell config to make everything available immediately + detect_shell_config + info "Sourcing $SHELL_CONFIG_FILE to activate all installed tools..." + source "$SHELL_CONFIG_FILE" + + ok "Setup complete! All tools are now available." + + # Display versions of all installed components + print_multiline </dev/null || echo "Not available") +$(tput setaf 6)npm:$(tput sgr0) $(npm -v 2>/dev/null || echo "Not available") +$(tput setaf 6)Appium:$(tput sgr0) $(appium --version 2>/dev/null || echo "Not available") +$(tput setaf 6)Java:$(tput sgr0) $(java -version 2>&1 | head -n 1 || echo "Not available") +$(tput setaf 6)Maven:$(tput sgr0) $(mvn -v 2>/dev/null | head -n 1 | sed 's/Apache Maven //' || echo "Not available") +$(tput setaf 6)Android SDK:$(tput sgr0) $([ -d "$ANDROID_SDK_ROOT_DIR" ] && echo "Installed at $ANDROID_SDK_ROOT_DIR" || echo "Not available") + +$(tput bold)======================================$(tput sgr0) +EOF +} + +main +exit 0