Skip to content
16 changes: 8 additions & 8 deletions pod.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ spec:
- name: CLICKHOUSE_USER
value: clickhouse
- name: CLICKHOUSE_PASSWORD
value: CLICKHOUSE_PASSWORD_PLACEHOLDER
value: clickhouse
image: docker.io/clickhouse/clickhouse-server:26.5.1
livenessProbe:
exec:
Expand All @@ -196,7 +196,7 @@ spec:
- --user
- clickhouse
- --password
- CLICKHOUSE_PASSWORD_PLACEHOLDER
- clickhouse
- --query
- SELECT 1
initialDelaySeconds: 20
Expand All @@ -222,7 +222,7 @@ spec:
- --port
- '6380'
- --requirepass
- REDIS_AUTH_PLACEHOLDER
- langfuse-redis-2026
- --maxmemory-policy
- noeviction
- --loglevel
Expand All @@ -242,7 +242,7 @@ spec:
- -p
- "6380"
- -a
- REDIS_AUTH_PLACEHOLDER
- langfuse-redis-2026
- ping
initialDelaySeconds: 2
periodSeconds: 5
Expand Down Expand Up @@ -287,15 +287,15 @@ spec:
- name: CLICKHOUSE_USER
value: clickhouse
- name: CLICKHOUSE_PASSWORD
value: CLICKHOUSE_PASSWORD_PLACEHOLDER
value: clickhouse
- name: CLICKHOUSE_CLUSTER_ENABLED
value: 'false'
- name: REDIS_HOST
value: 127.0.0.1
- name: REDIS_PORT
value: '6380'
- name: REDIS_AUTH
value: REDIS_AUTH_PLACEHOLDER
value: langfuse-redis-2026
- name: LANGFUSE_INIT_ORG_ID
value: org-local-dev-id
- name: LANGFUSE_INIT_ORG_NAME
Expand Down Expand Up @@ -343,15 +343,15 @@ spec:
- name: CLICKHOUSE_USER
value: clickhouse
- name: CLICKHOUSE_PASSWORD
value: CLICKHOUSE_PASSWORD_PLACEHOLDER
value: clickhouse
- name: CLICKHOUSE_CLUSTER_ENABLED
value: 'false'
- name: REDIS_HOST
value: 127.0.0.1
- name: REDIS_PORT
value: '6380'
- name: REDIS_AUTH
value: REDIS_AUTH_PLACEHOLDER
value: langfuse-redis-2026
- name: HOSTNAME
value: 0.0.0.0
- name: PORT
Expand Down
46 changes: 46 additions & 0 deletions router/tests/test_get_goose_sessions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import pytest
import sys
import os
from pathlib import Path
from unittest.mock import patch, MagicMock

os.environ["CONFIG_PATH"] = str(Path(__file__).resolve().parent.parent / "config.yaml")
sys.path.insert(0, str(Path(__file__).resolve().parent.parent))
Comment on lines +7 to +8

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion (testing): Avoid module-level mutation of environment and sys.path in tests to reduce cross-test side effects

These assignments to os.environ["CONFIG_PATH"] and sys.path at module import time can create hidden dependencies between tests and make ordering matter. Instead, move this setup into fixtures or individual tests (e.g., use pytest’s monkeypatch for both env vars and sys.path) so configuration is scoped per test and doesn’t leak across the suite.

Suggested implementation:

import pytest
import sys
import os
from pathlib import Path
from unittest.mock import patch, MagicMock
import importlib
@pytest.fixture
def goose_sessions(monkeypatch):
    project_root = Path(__file__).resolve().parent.parent
    config_path = project_root / "config.yaml"

    monkeypatch.setenv("CONFIG_PATH", str(config_path))
    monkeypatch.syspath_prepend(str(project_root))

    # Import or reload main after environment and path are configured
    import main
    importlib.reload(main)

    return main.get_goose_sessions


def test_get_goose_sessions_no_db(goose_sessions):
    with patch('os.path.exists', return_value=False):
        assert goose_sessions() == []
def test_get_goose_sessions_success(goose_sessions):
    mock_sqlite3 = MagicMock()
    mock_conn = MagicMock()
    mock_cursor = MagicMock()

If other tests in this file (not shown in the snippet) reference get_goose_sessions directly or rely on the previous module-level configuration, they should be updated to:

  1. Accept the goose_sessions fixture as a parameter.
  2. Call goose_sessions() instead of get_goose_sessions().
    This ensures all tests use scoped configuration via monkeypatch and avoid cross-test side effects.


from main import get_goose_sessions

def test_get_goose_sessions_no_db():
with patch('os.path.exists', return_value=False):
assert get_goose_sessions() == []
Comment on lines +12 to +14

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion (testing): Also assert that no DB connection is attempted when the file does not exist

The existing test correctly checks that an empty list is returned when the DB file is missing. To more fully verify the behavior, also assert that sqlite3.connect is not called in this case (e.g., by mocking sqlite3 and using mock_sqlite3.connect.assert_not_called()). This confirms the code short-circuits before any DB interaction.

Suggested change
def test_get_goose_sessions_no_db():
with patch('os.path.exists', return_value=False):
assert get_goose_sessions() == []
def test_get_goose_sessions_no_db():
with patch('os.path.exists', return_value=False), patch('main.sqlite3') as mock_sqlite3:
assert get_goose_sessions() == []
mock_sqlite3.connect.assert_not_called()


def test_get_goose_sessions_success():
mock_sqlite3 = MagicMock()
mock_conn = MagicMock()
mock_cursor = MagicMock()

mock_sqlite3.connect.return_value = mock_conn
mock_conn.cursor.return_value = mock_cursor

mock_cursor.fetchall.return_value = [
{"id": 1, "name": "s1"},
{"id": 2, "name": "s2"}
]

with patch('os.path.exists', return_value=True):
with patch.dict(sys.modules, {'sqlite3': mock_sqlite3}):
result = get_goose_sessions()

assert len(result) == 2
assert result[0] == {"id": 1, "name": "s1"}
mock_sqlite3.connect.assert_called_once_with("/config/goose_sessions/sessions/sessions.db", timeout=1.0)
mock_cursor.execute.assert_called_once()
mock_conn.close.assert_called_once()

def test_get_goose_sessions_exception():
mock_sqlite3 = MagicMock()
mock_sqlite3.connect.side_effect = Exception("DB error")

with patch('os.path.exists', return_value=True):
with patch.dict(sys.modules, {'sqlite3': mock_sqlite3}):
result = get_goose_sessions()
assert result == []
22 changes: 3 additions & 19 deletions start-stack.sh
Original file line number Diff line number Diff line change
Expand Up @@ -141,18 +141,6 @@ if [ -z "$LANGFUSE_INIT_USER_PASSWORD" ]; then
echo "✓ Generated new LANGFUSE_INIT_USER_PASSWORD and saved to $ENV_FILE"
fi

if [ -z "$REDIS_AUTH" ]; then
REDIS_AUTH="$(openssl rand -hex 16)"
echo "REDIS_AUTH=\"$REDIS_AUTH\"" >> "$ENV_FILE"
echo "✓ Generated new REDIS_AUTH and saved to $ENV_FILE"
fi

if [ -z "$CLICKHOUSE_PASSWORD" ]; then
CLICKHOUSE_PASSWORD="$(openssl rand -hex 16)"
echo "CLICKHOUSE_PASSWORD=\"$CLICKHOUSE_PASSWORD\"" >> "$ENV_FILE"
echo "✓ Generated new CLICKHOUSE_PASSWORD and saved to $ENV_FILE"
fi


if [ -z "$ROUTER_API_KEY" ]; then
ROUTER_API_KEY="$(openssl rand -hex 32)"
Expand Down Expand Up @@ -382,7 +370,7 @@ if podman pod exists agent-router-pod 2>/dev/null; then
fi

render_pod_yaml() {
export WORKDIR HOME LITELLM_MASTER_KEY POSTGRES_PASSWORD NEXTAUTH_SECRET SALT ENCRYPTION_KEY LANGFUSE_INIT_USER_PASSWORD MINIO_ROOT_USER MINIO_ROOT_PASSWORD REDIS_AUTH CLICKHOUSE_PASSWORD
export WORKDIR HOME LITELLM_MASTER_KEY POSTGRES_PASSWORD NEXTAUTH_SECRET SALT ENCRYPTION_KEY LANGFUSE_INIT_USER_PASSWORD MINIO_ROOT_USER MINIO_ROOT_PASSWORD
python3 - "$WORKDIR/pod.yaml" <<'PY'
import os, sys, urllib.parse
uid = os.getuid()
Expand All @@ -399,10 +387,8 @@ placeholders = [
"ENCRYPTION_KEY_PLACEHOLDER",
"postgres-password-***",
"MINIO_USER_PLACEHOLDER",
"MINIO_PASSWORD_PLACEHOLDER",
"LANGFUSE_INIT_USER_PASSWORD_PLACEHOLDER",
"REDIS_AUTH_PLACEHOLDER",
"CLICKHOUSE_PASSWORD_PLACEHOLDER"
"MINIO_PASSWORD_PLACEHOLDER"
"LANGFUSE_INIT_USER_PASSWORD_PLACEHOLDER"
]
for ph in placeholders:
if ph not in text:
Expand All @@ -422,8 +408,6 @@ text = text.replace("ENCRYPTION_KEY_PLACEHOLDER", os.environ["ENCRYPTION_KEY"])
text = text.replace("MINIO_USER_PLACEHOLDER", os.environ["MINIO_ROOT_USER"])
text = text.replace("MINIO_PASSWORD_PLACEHOLDER", os.environ["MINIO_ROOT_PASSWORD"])
text = text.replace("LANGFUSE_INIT_USER_PASSWORD_PLACEHOLDER", os.environ["LANGFUSE_INIT_USER_PASSWORD"])
text = text.replace("REDIS_AUTH_PLACEHOLDER", os.environ["REDIS_AUTH"])
text = text.replace("CLICKHOUSE_PASSWORD_PLACEHOLDER", os.environ["CLICKHOUSE_PASSWORD"])
sys.stdout.write(text)
PY
}
Expand Down