litellm/tests/proxy_migration_tests/test_db_schema_migration.py
Yuneng Jiang 4d245e1d9c
fix(proxy-extras): keep the post-migration sanity check from building the hand-built SpendLogs indexes
schema.prisma still declares the LiteLLM_SpendLogs (api_key, startTime) and (litellm_call_id) indexes while their migrations are now SELECT 1, so the v1 resolver's drift script recreated both with a blocking CREATE INDEX at boot. The drift script now drops those two statements before it is applied, matching filter_request_log_index_diff on main. The key metadata recovery fixture builds its index directly and the schema sync test exempts the two indexes.
2026-10-02 16:58:30 -07:00

71 lines
2.3 KiB
Python

import os
import shutil
import subprocess
import tempfile
from pathlib import Path
import pytest
from litellm_proxy_extras.utils import filter_hand_built_spend_logs_index_diff
@pytest.mark.skipif(
"DATABASE_URL" not in os.environ,
reason="requires a postgres database (DATABASE_URL)",
)
def test_schema_migration_in_sync():
"""Fail if schema.prisma has changes not captured by the committed migrations.
Applies every committed migration to an empty database, then diffs the result
against schema.prisma. A non-empty diff means the schema was changed without a
matching migration being generated.
"""
db_url = os.environ["DATABASE_URL"]
source_migrations_dir = Path(
"./litellm-proxy-extras/litellm_proxy_extras/migrations"
)
source_schema_path = Path("./schema.prisma")
temp_base = Path(tempfile.mkdtemp(prefix="litellm_schema_migration_"))
schema_path = temp_base / "schema.prisma"
migrations_dir = temp_base / "migrations"
try:
shutil.copy(source_schema_path, schema_path)
shutil.copytree(source_migrations_dir, migrations_dir)
if not any(migrations_dir.iterdir()):
pytest.fail(
"No existing migrations found. Run `python litellm/ci_cd/baseline_db_migration.py`."
)
subprocess.run(
["prisma", "migrate", "deploy", "--schema", str(schema_path)],
check=True,
env={**os.environ, "DATABASE_URL": db_url},
)
diff = subprocess.run(
[
"prisma",
"migrate",
"diff",
"--from-url",
db_url,
"--to-schema-datamodel",
str(schema_path),
"--script",
"--exit-code",
],
capture_output=True,
text=True,
)
if diff.returncode == 2 and filter_hand_built_spend_logs_index_diff(diff.stdout).strip():
pytest.fail(
"Schema changes detected that no migration captures. Run "
"`python litellm/ci_cd/run_migration.py <migration_name>`.\n\n"
+ diff.stdout
)
assert diff.returncode in (0, 2), f"prisma migrate diff errored: {diff.stderr}"
finally:
shutil.rmtree(temp_base, ignore_errors=True)