mirror of
https://github.com/PR0M3TH3AN/VoxVera.git
synced 2026-10-27 09:40:40 +00:00
219 lines
6.4 KiB
Bash
Executable File
219 lines
6.4 KiB
Bash
Executable File
#!/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
|
|
elif command -v voxvera >/dev/null 2>&1; then
|
|
voxvera_cmd="$(command -v voxvera)"
|
|
echo "Using existing VoxVera on PATH: $voxvera_cmd" >&2
|
|
else
|
|
echo "Installing VoxVera in editable mode..."
|
|
python3 -m pip install --break-system-packages --no-build-isolation -e ".[e2e]"
|
|
voxvera_cmd="$(command -v voxvera || echo "$HOME/.local/bin/voxvera")"
|
|
fi
|
|
|
|
echo "VoxVera command: $voxvera_cmd"
|
|
|
|
echo "Checking platform contract before workflow..."
|
|
bash scripts/platform-smoke.sh linux-cli
|
|
|
|
# Generate demo flyer
|
|
echo "Initializing demo flyer..."
|
|
"$voxvera_cmd" --lang en init --template voxvera <<EOI
|
|
DemoUser
|
|
voxvera
|
|
EOI
|
|
|
|
config_path="$HOME/host/voxvera/config.json"
|
|
if [ ! -f "$config_path" ]; then
|
|
echo "CRITICAL: Expected config file not found after init: $config_path" >&2
|
|
exit 1
|
|
fi
|
|
|
|
echo "Building demo flyer..."
|
|
"$voxvera_cmd" --lang en --config "$config_path" build
|
|
|
|
# Verify build output exists in host/
|
|
folder_name="voxvera"
|
|
host_dir="$HOME/host/$folder_name"
|
|
|
|
if [ ! -d "$host_dir" ]; then
|
|
echo "CRITICAL: Host directory $host_dir not found!" >&2
|
|
ls -R "$HOME/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
|
|
|
|
echo "Checking platform contract with live Tor..."
|
|
VOXVERA_REQUIRE_TOR=1 bash scripts/platform-smoke.sh linux-cli
|
|
|
|
# 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 <<EOF
|
|
import json
|
|
import os
|
|
path = "$host_dir/config.json"
|
|
with open(path, 'r') as f:
|
|
data = json.load(f)
|
|
data['url'] = "$URL"
|
|
with open(path + '.new', 'w') as f:
|
|
json.dump(data, f, indent=2)
|
|
os.replace(path + '.new', path)
|
|
EOF
|
|
|
|
echo "Verifying content of $host_dir/config.json:"
|
|
cat "$host_dir/config.json"
|
|
|
|
# Verify URL in config
|
|
if ! grep -Fq "$URL" "$host_dir/config.json"; then
|
|
echo "CRITICAL: URL $URL not found in $host_dir/config.json" >&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 '<title>'; 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
|