diff --git a/backend/tests/test_serve_uv_extras_detection.py b/backend/tests/test_serve_uv_extras_detection.py new file mode 100644 index 0000000000..01189421be --- /dev/null +++ b/backend/tests/test_serve_uv_extras_detection.py @@ -0,0 +1,70 @@ +"""Regression tests for postgres extra detection in scripts/serve.sh.""" + +from __future__ import annotations + +import subprocess +import tempfile +from pathlib import Path +from shutil import which + +import pytest + +REPO_ROOT = Path(__file__).resolve().parents[2] +SCRIPT_PATH = REPO_ROOT / "scripts" / "lib" / "uv-extras.sh" +BASH_CANDIDATES = [ + Path(r"C:\Program Files\Git\bin\bash.exe"), + Path(which("bash")) if which("bash") else None, +] +BASH_EXECUTABLE = next( + (str(path) for path in BASH_CANDIDATES if path is not None and path.exists() and "WindowsApps" not in str(path)), + None, +) + +if BASH_EXECUTABLE is None: + pytestmark = pytest.mark.skip(reason="bash is required for serve.sh detection tests") + + +def _detect_uv_extras(config_content: str, *, nested_backend_config: bool = False) -> str: + with tempfile.TemporaryDirectory() as tmpdir: + tmp_root = Path(tmpdir) + config_path = tmp_root / ("backend/config.yaml" if nested_backend_config else "config.yaml") + config_path.parent.mkdir(parents=True, exist_ok=True) + config_path.write_text(config_content, encoding="utf-8") + + command = f"cd '{tmp_root}' && source '{SCRIPT_PATH}' && detect_uv_extras" + + return subprocess.check_output( + [BASH_EXECUTABLE, "-lc", command], + text=True, + encoding="utf-8", + ).strip() + + +def test_detect_uv_extras_empty_when_database_backend_is_sqlite(): + config = """ +database: + backend: sqlite + sqlite_dir: .deer-flow/data +""".strip() + + assert _detect_uv_extras(config) == "" + + +def test_detect_uv_extras_returns_postgres_for_repo_root_config(): + config = """ +database: + backend: postgres + postgres_url: $DATABASE_URL +""".strip() + + assert _detect_uv_extras(config) == "postgres" + + +def test_detect_uv_extras_returns_postgres_for_backend_config(): + config = """ +database: + backend: postgres + postgres_url: $DATABASE_URL +""".strip() + + assert _detect_uv_extras(config, nested_backend_config=True) == "postgres" diff --git a/scripts/lib/uv-extras.sh b/scripts/lib/uv-extras.sh new file mode 100644 index 0000000000..11c2e2fc92 --- /dev/null +++ b/scripts/lib/uv-extras.sh @@ -0,0 +1,31 @@ +#!/usr/bin/env bash + +detect_uv_extras() { + local config_file="" + local backend="" + + if [ -n "${DEER_FLOW_CONFIG_PATH:-}" ] && [ -f "${DEER_FLOW_CONFIG_PATH}" ]; then + config_file="${DEER_FLOW_CONFIG_PATH}" + elif [ -f "backend/config.yaml" ]; then + config_file="backend/config.yaml" + elif [ -f "config.yaml" ]; then + config_file="config.yaml" + else + return 0 + fi + + backend=$(awk ' + /^[[:space:]]*database:[[:space:]]*$/ { in_database=1; next } + in_database && /^[^[:space:]#]/ { in_database=0 } + in_database && /^[[:space:]]*backend:[[:space:]]*/ { + line=$0 + sub(/^[[:space:]]*backend:[[:space:]]*/, "", line) + print line + exit + } + ' "$config_file") + + if [ "$backend" = "postgres" ]; then + echo "postgres" + fi +} diff --git a/scripts/serve.sh b/scripts/serve.sh index 17d46eede3..86b4005b19 100755 --- a/scripts/serve.sh +++ b/scripts/serve.sh @@ -29,6 +29,8 @@ set -e REPO_ROOT="$(builtin cd "$(dirname "${BASH_SOURCE[0]}")/.." >/dev/null 2>&1 && pwd -P)" cd "$REPO_ROOT" +source "$REPO_ROOT/scripts/lib/uv-extras.sh" + # ── Load .env ──────────────────────────────────────────────────────────────── if [ -f "$REPO_ROOT/.env" ]; then @@ -159,7 +161,13 @@ fi if ! $SKIP_INSTALL; then echo "Syncing dependencies..." - (cd backend && uv sync --quiet) || { echo "✗ Backend dependency install failed"; exit 1; } + UV_EXTRAS_VALUE="$(detect_uv_extras)" + if [ -n "$UV_EXTRAS_VALUE" ]; then + echo "→ Enabling backend uv extras: $UV_EXTRAS_VALUE" + (cd backend && uv sync --quiet --extra "$UV_EXTRAS_VALUE") || { echo "✗ Backend dependency install failed"; exit 1; } + else + (cd backend && uv sync --quiet) || { echo "✗ Backend dependency install failed"; exit 1; } + fi (cd frontend && pnpm install --silent) || { echo "✗ Frontend dependency install failed"; exit 1; } echo "✓ Dependencies synced" else