#!/usr/bin/env bash set -euo pipefail # Robustness: ensure we are in the project root cd "$(dirname "$0")/.." LOG_DIR="$(pwd)/ci-logs" mkdir -p "$LOG_DIR" # Use a subshell for tee to avoid issues with some shell environments exec > >(tee "$LOG_DIR/run.log") 2>&1 echo "Starting E2E verification at $(date)" # Install VoxVera if [ -n "${VOXVERA_BIN:-}" ] && [ -f "$VOXVERA_BIN" ]; then voxvera_cmd="$VOXVERA_BIN" echo "Using provided VoxVera binary: $voxvera_cmd" >&2 else echo "Installing VoxVera in editable mode..." python3 -m pip install --break-system-packages -e ".[e2e]" voxvera_cmd="$(command -v voxvera || echo "$HOME/.local/bin/voxvera")" fi echo "VoxVera command: $voxvera_cmd" # Generate demo flyer echo "Initializing demo flyer..." "$voxvera_cmd" --lang en init --template voxvera <&2 ls -R voxvera/host/ || true exit 1 fi ls -R "$host_dir" >>"$LOG_DIR/tree.txt" # Verify essential files for f in index.html config.json; do if [ ! -f "$host_dir/$f" ]; then echo "CRITICAL: Missing $f in $host_dir" >&2 exit 1 fi done echo "Build output verified in $host_dir" # Run pytest unit tests echo "Running pytest unit tests..." python3 -m pytest tests/ -v 2>&1 | tee "$LOG_DIR/pytest.log" # Optional network tests if [ "${VOXVERA_E2E_OFFLINE:-}" != "1" ]; then echo "Starting network-dependent tests..." # GitHub Actions Ubuntu runners have Tor pre-installed and running as a service. # We stop it to ensure we can run our own instance with known configuration on default ports. echo "Stopping system Tor service if running..." sudo systemctl stop tor || true # Kill any lingering tor processes sudo pkill -x tor || true echo "Starting a fresh Tor instance on default ports (9050/9051)..." mkdir -p "$LOG_DIR/tor_data" tor --SocksPort 9050 --ControlPort 9051 --CookieAuthentication 0 --DataDirectory "$LOG_DIR/tor_data" >"$LOG_DIR/tor.log" 2>&1 & TOR_PID=$! # Wait for Tor to bootstrap echo "Waiting for Tor to bootstrap (up to 120s)..." BOOTSTRAPPED=0 for i in {1..120}; do if grep -q "Bootstrapped 100%" "$LOG_DIR/tor.log"; then echo "Tor bootstrapped successfully." BOOTSTRAPPED=1 break fi [ $((i % 10)) -eq 0 ] && echo "... still bootstrapping Tor ($i s) ..." sleep 1 done if [ $BOOTSTRAPPED -eq 0 ]; then echo "CRITICAL: Tor failed to bootstrap after 120s" >&2 tail -n 20 "$LOG_DIR/tor.log" kill ${TOR_PID:-} || true exit 1 fi # Start OnionShare echo "Starting OnionShare..." # Explicitly set environment variables that OnionShare-cli respects export TOR_SOCKS_PORT=9050 export TOR_CONTROL_PORT=9051 onionshare-cli --website --public \ --persistent "$host_dir/.onionshare-session" \ -v \ "$host_dir" >"$LOG_DIR/onionshare.log" 2>&1 & OS_PID=$! # Check if OnionShare process is still alive after a few seconds sleep 5 if ! kill -0 $OS_PID 2>/dev/null; then echo "CRITICAL: OnionShare-cli failed to start" >&2 cat "$LOG_DIR/onionshare.log" kill ${TOR_PID:-} || true exit 1 fi # Wait for URL with timeout and feedback echo "Waiting for OnionShare to generate URL (up to 120s)..." URL="" for i in {1..120}; do # Use -a to process as text even if there are binary chars (ANSI codes) if grep -aEo 'http[s]?://[a-z2-7]{56}\.onion' "$LOG_DIR/onionshare.log" | head -n1 >"$LOG_DIR/url.txt"; then URL=$(cat "$LOG_DIR/url.txt" | tr -d '\r\n ') if [ -n "$URL" ]; then echo "Successfully generated Onion URL: $URL" break fi fi [ $((i % 10)) -eq 0 ] && echo "... still waiting ($i s) ..." sleep 1 done if [ -z "$URL" ]; then echo "CRITICAL: Onion URL not found after 120s" >&2 echo "--- Last 20 lines of OnionShare log ---" tail -n 20 "$LOG_DIR/onionshare.log" kill $OS_PID || true kill ${TOR_PID:-} || true exit 1 fi # Robustness: Manually update the config.json with the URL so verification passes # and the site is actually using the live onion address. echo "Updating $host_dir/config.json with live URL: $URL" python3 <&2 cat "$host_dir/config.json" kill $OS_PID || true kill ${TOR_PID:-} || true exit 1 fi # Re-build to update QR codes with live onion URL echo "Re-building site with live URL..." "$voxvera_cmd" --lang en build --config "$host_dir/config.json" # Fetch page via Tor (retry a few times as circuits can be flaky) echo "Verifying reachability via Tor (on port 9050)..." FETCHED=0 for attempt in {1..5}; do echo "Attempt $attempt..." if curl --socks5-hostname 127.0.0.1:9050 -fsSL "$URL" | grep -q ''; then echo "Success: Site is reachable via Tor." FETCHED=1 break fi sleep 10 done if [ $FETCHED -eq 0 ]; then echo "WARNING: Site could not be reached via Tor after 5 attempts, but OnionShare is running." # In CI, we might skip hard failure if Tor network is exceptionally slow/blocked fi # Clean up echo "Cleaning up..." kill $OS_PID || true kill ${TOR_PID:-} || true wait $OS_PID 2>/dev/null || true else echo "Skipping network-dependent tests (VOXVERA_E2E_OFFLINE=1)" >&2 fi echo "E2E verification complete at $(date)" exit 0