131 lines
4.5 KiB
Bash
Executable File
131 lines
4.5 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
|
|
# Backend-only local smoke test.
|
|
#
|
|
# Validates the Python backend and local API server from THIS checkout without
|
|
# building the web UI, configuring provider credentials, creating sessions, or
|
|
# running agents. Useful for a quick server/API smoke check on your working
|
|
# copy or current `main`.
|
|
#
|
|
# Everything (toolchain, project venv, config, data, database, artifacts, logs,
|
|
# caches) lives under one disposable runtime directory that is removed on exit,
|
|
# so the run never touches your real ~/.omnigent, ~/.config / ~/Library, or
|
|
# package caches.
|
|
#
|
|
# Usage:
|
|
# scripts/backend-smoke.sh # uses port 18080
|
|
# PORT=18090 scripts/backend-smoke.sh # override the port if 18080 is busy
|
|
#
|
|
# Requires: bash, python3 (3.12+), git, curl, and network access to PyPI. No
|
|
# provider credentials needed. Works on Linux and macOS.
|
|
|
|
set -euo pipefail
|
|
|
|
PORT="${PORT:-18080}"
|
|
repo_root="$(git -C "$(dirname "$0")" rev-parse --show-toplevel)"
|
|
|
|
runtime_root="$(mktemp -d "${TMPDIR:-/tmp}/omnigent_backend_XXXXXX")"
|
|
toolchain_venv="$runtime_root/toolchain_venv"
|
|
project_venv="$runtime_root/project_venv"
|
|
runtime_home="$runtime_root/home"
|
|
runtime_tmp="$runtime_root/tmp"
|
|
runtime_config="$runtime_root/config"
|
|
runtime_data="$runtime_root/data"
|
|
runtime_cache="$runtime_root/cache"
|
|
runtime_logs="$runtime_root/logs"
|
|
runtime_artifacts="$runtime_root/artifacts"
|
|
runtime_db="$runtime_data/omnigent/chat.db"
|
|
server_pid=""
|
|
|
|
cleanup() {
|
|
if [ -n "$server_pid" ]; then
|
|
kill -TERM "$server_pid" 2>/dev/null || true
|
|
wait "$server_pid" 2>/dev/null || true
|
|
fi
|
|
rm -rf "$runtime_root"
|
|
}
|
|
trap cleanup EXIT
|
|
|
|
mkdir -p \
|
|
"$runtime_home" "$runtime_tmp" \
|
|
"$runtime_config/xdg" "$runtime_data/xdg" "$runtime_cache/xdg" \
|
|
"$runtime_cache/pip" "$runtime_cache/uv" \
|
|
"$runtime_logs" "$runtime_artifacts" \
|
|
"$(dirname "$runtime_db")" \
|
|
"$runtime_config/omnigent" "$runtime_data/omnigent"
|
|
|
|
# Isolated environment shared by every step. HOME is the primary isolation
|
|
# lever (it covers ~/.config on Linux and ~/Library on macOS); the explicit
|
|
# UV_/PIP_/OMNIGENT_ overrides pin the toolchain and app state regardless of
|
|
# OS. XDG_* are set so an XDG var already exported in the caller's shell can't
|
|
# redirect state back to the real home. OMNIGENT_SKIP_WEB_UI leaves the server
|
|
# in API-only mode (no web UI build); UV_PROJECT_ENVIRONMENT points uv at the
|
|
# throwaway project venv; UV_PYTHON_DOWNLOAD=never keeps uv from fetching
|
|
# interpreters.
|
|
env_vars=(
|
|
"HOME=$runtime_home"
|
|
"TMPDIR=$runtime_tmp"
|
|
"XDG_CONFIG_HOME=$runtime_config/xdg"
|
|
"XDG_DATA_HOME=$runtime_data/xdg"
|
|
"XDG_CACHE_HOME=$runtime_cache/xdg"
|
|
"PIP_CACHE_DIR=$runtime_cache/pip"
|
|
"UV_CACHE_DIR=$runtime_cache/uv"
|
|
"UV_PROJECT_ENVIRONMENT=$project_venv"
|
|
"UV_PYTHON_DOWNLOAD=never"
|
|
"OMNIGENT_CONFIG_HOME=$runtime_config/omnigent"
|
|
"OMNIGENT_DATA_DIR=$runtime_data/omnigent"
|
|
"OMNIGENT_DATABASE_URI=sqlite:///$runtime_db"
|
|
"OMNIGENT_SKIP_WEB_UI=true"
|
|
)
|
|
|
|
echo "Runtime dir: $runtime_root"
|
|
echo "Checkout: $repo_root"
|
|
|
|
echo "Installing uv into a throwaway toolchain venv..."
|
|
python3 -m venv "$toolchain_venv"
|
|
python3 -m venv "$project_venv"
|
|
env "${env_vars[@]}" "$toolchain_venv/bin/python" -m pip install --quiet "uv>=0.11.8"
|
|
|
|
echo "Syncing project dependencies (uv sync --frozen)..."
|
|
( cd "$repo_root" && env "${env_vars[@]}" "$toolchain_venv/bin/uv" sync --frozen )
|
|
|
|
echo "Starting backend server on 127.0.0.1:$PORT (API-only)..."
|
|
nohup env "${env_vars[@]}" \
|
|
"$project_venv/bin/omnigent" server \
|
|
--host 127.0.0.1 \
|
|
--port "$PORT" \
|
|
--database-uri "sqlite:///$runtime_db" \
|
|
--artifact-location "$runtime_artifacts" \
|
|
< /dev/null > "$runtime_logs/omnigent_server.log" 2>&1 &
|
|
server_pid="$!"
|
|
|
|
echo "Waiting for /health..."
|
|
ready=""
|
|
for _ in {1..60}; do
|
|
code="$(curl -s -o /dev/null -w "%{http_code}" --max-time 2 \
|
|
"http://127.0.0.1:${PORT}/health" || true)"
|
|
if [ "$code" = "200" ]; then ready=1; break; fi
|
|
sleep 0.5
|
|
done
|
|
if [ -z "$ready" ]; then
|
|
echo "ERROR: server did not become healthy in time; last log lines:" >&2
|
|
tail -n 40 "$runtime_logs/omnigent_server.log" >&2 || true
|
|
exit 1
|
|
fi
|
|
|
|
echo "Smoke-testing API endpoints (expect 200):"
|
|
status=0
|
|
for path in / /health /docs /v1/agents /v1/sessions; do
|
|
code="$(curl -s -o /dev/null -w "%{http_code}" --max-time 5 \
|
|
"http://127.0.0.1:${PORT}${path}")"
|
|
printf " %-14s %s\n" "$path" "$code"
|
|
[ "$code" = "200" ] || status=1
|
|
done
|
|
|
|
if [ "$status" -eq 0 ]; then
|
|
echo "OK: all endpoints returned 200."
|
|
else
|
|
echo "FAIL: one or more endpoints did not return 200." >&2
|
|
fi
|
|
exit "$status"
|