feat: FlowPilot migration — Phase 1-9 + Phase 9 bug fixes + QA fixture harness #147

Merged
chihlasm merged 85 commits from feat/flowpilot-migration into main 2026-04-25 06:02:14 +00:00
2 changed files with 28 additions and 8 deletions
Showing only changes of commit dab740ddf7 - Show all commits

View File

@@ -14,21 +14,33 @@ from sqlalchemy.pool import NullPool
from app.main import app
from app.core.database import Base, get_db
from app.core.admin_database import get_admin_db
from app.core.config import settings
# Disable invite code requirement for tests
settings.REQUIRE_INVITE_CODE = False
# Test database URL (separate from production)
# Use DATABASE_TEST_URL env var if set (e.g. inside Docker where host is 'db'),
# otherwise fall back to localhost for local development.
# Test database URL — NEVER reuse DATABASE_URL. The test_db fixture does
# `DROP SCHEMA public CASCADE` on every test; if DATABASE_URL (which normally
# points at the dev/prod DB) leaked into this value, running `pytest tests/`
# would silently nuke the dev database. Only DATABASE_TEST_URL is honored,
# and the safety assertion below refuses to run against a DB whose name
# doesn't contain "test".
import os
TEST_DATABASE_URL = os.environ.get(
"DATABASE_URL",
os.environ.get(
"DATABASE_TEST_URL",
"postgresql+asyncpg://postgres:postgres@localhost:5432/patherly_test",
),
"DATABASE_TEST_URL",
"postgresql+asyncpg://postgres:postgres@localhost:5432/resolutionflow_test",
)
# Belt-and-suspenders: refuse to run tests against a DB whose name doesn't
# contain "test". Parses the last path segment of the URL (everything after
# the final '/', with query string stripped) so credentials / hosts that
# happen to contain "test" can't bypass the check.
_test_db_name = TEST_DATABASE_URL.rsplit("/", 1)[-1].split("?", 1)[0].lower()
assert "test" in _test_db_name, (
f"Refusing to run tests against database {_test_db_name!r}"
f"the DB name must contain 'test'. Set DATABASE_TEST_URL to a dedicated "
f"test database (e.g. resolutionflow_test)."
)
@@ -131,6 +143,11 @@ async def client(test_db: AsyncSession):
yield test_db
app.dependency_overrides[get_db] = override_get_db
# Endpoints that use get_admin_db (register, admin routes, service accounts)
# must also hit the test DB; otherwise they leak into the real admin DB.
# RLS is not enabled in the test schema (create_all, not alembic), so sharing
# the same session is safe.
app.dependency_overrides[get_admin_db] = override_get_db
transport = ASGITransport(app=app)
async with AsyncClient(transport=transport, base_url="http://test") as ac:

View File

@@ -33,6 +33,9 @@ services:
- DEBUG=true
- DATABASE_URL=postgresql+asyncpg://postgres:postgres@db:5432/resolutionflow
- DATABASE_URL_SYNC=postgresql://postgres:postgres@db:5432/resolutionflow
# Dedicated test database — pytest will refuse to run against any DB
# whose name doesn't contain 'test' (conftest.py safety assertion).
- DATABASE_TEST_URL=postgresql+asyncpg://postgres:postgres@db:5432/resolutionflow_test
- SECRET_KEY=${SECRET_KEY}
- ALGORITHM=HS256
- ACCESS_TOKEN_EXPIRE_MINUTES=15