f04b9b3588
SLICE-01 (lead-developer): multi-stage Dockerfile (node:22-slim→python:3.12-slim), .dockerignore (excludes secrets/node_modules/.git), docker-compose.yml (port 8789, SQLite volume, env injection for all voice-service vars) SLICE-02 (backend-engineer+data-engineer): FastAPI mounts client/dist as StaticFiles at / after API routes (D-023, REQ-DEPLOY-13). G-102 MUST fix: db/store.py + db/migrate.py now read PRAXIS_DB_PATH from env so the Docker volume mount persists SQLite data. G-105 FIX: Dockerfile copies pyproject.toml before source (pip install layer cached, source changes don't invalidate). REQ-DEPLOY-01, 02, 13, 16 covered. ---ci--- project: praxis phase: 1 milestone: v0.2 status: execute slice: 01-02 wave: 1 ---/ci---
48 lines
1.5 KiB
Python
48 lines
1.5 KiB
Python
"""SQLite migration runner — applies db/migrations/*.sql in order."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import os
|
|
import sqlite3
|
|
from pathlib import Path
|
|
|
|
# G-102 FIX: read PRAXIS_DB_PATH from env (must match db/store.py).
|
|
_DEFAULT_DB_PATH = Path(os.environ.get("PRAXIS_DB_PATH", "praxis.db"))
|
|
_DEFAULT_MIGRATIONS_DIR = Path(__file__).resolve().parent / "migrations"
|
|
|
|
|
|
def apply_migrations(
|
|
db_path: Path | str | None = None,
|
|
migrations_dir: Path | None = None,
|
|
) -> list[str]:
|
|
"""Apply all pending migrations in order. Returns the list of applied names.
|
|
|
|
Uses a `_migrations` tracking table so re-running is idempotent.
|
|
"""
|
|
db = Path(db_path) if db_path else _DEFAULT_DB_PATH
|
|
mdir = migrations_dir or _DEFAULT_MIGRATIONS_DIR
|
|
|
|
conn = sqlite3.connect(str(db))
|
|
try:
|
|
conn.execute(
|
|
"CREATE TABLE IF NOT EXISTS _migrations (id TEXT PRIMARY KEY, applied_at TEXT NOT NULL DEFAULT (datetime('now')))"
|
|
)
|
|
applied: list[str] = []
|
|
for sql_path in sorted(mdir.glob("*.sql")):
|
|
mid = sql_path.stem
|
|
already = conn.execute(
|
|
"SELECT 1 FROM _migrations WHERE id = ?", (mid,)
|
|
).fetchone()
|
|
if already:
|
|
continue
|
|
sql = sql_path.read_text(encoding="utf-8")
|
|
conn.executescript(sql)
|
|
conn.execute("INSERT INTO _migrations (id) VALUES (?)", (mid,))
|
|
conn.commit()
|
|
applied.append(mid)
|
|
return applied
|
|
finally:
|
|
conn.close()
|
|
|
|
|
|
__all__ = ["apply_migrations"] |