diff --git a/scripts/e2e_seed.py b/scripts/e2e_seed.py index f2ac5994..fcc35365 100644 --- a/scripts/e2e_seed.py +++ b/scripts/e2e_seed.py @@ -24,6 +24,7 @@ from sqlalchemy import delete, func, select # noqa: E402 from app.db import SessionLocal # noqa: E402 from app.models import ( # noqa: E402 + AppState, Channel, Playlist, PlaylistItem, @@ -46,6 +47,21 @@ def _now() -> datetime: def main() -> None: db = SessionLocal() try: + # 0. Mark the instance configured so the first-run setup wizard is skipped. A prod→dev + # reseed (siftlode seed-dev-from-prod) TRUNCATEs app_state — it's excluded from the + # data allow-list, being local/operational state — which would otherwise drop the box + # back into "Setup needed" and block login/UAT. Since e2e_seed always leaves a loginable + # admin below, the instance is legitimately set up. Idempotent (mirrors state._row + + # state.mark_configured). The running api process caches `configured` one-way from False, + # so it re-reads the DB and promotes on the next request — no restart needed. + app_state = db.get(AppState, 1) + if app_state is None: + app_state = AppState(id=1, sync_paused=False) + db.add(app_state) + app_state.configured = True + app_state.setup_token_hash = None + db.commit() + # 1. Upsert the account and always reset it to a clean, loginable baseline # (email_verified + is_active + not suspended + not demo + password set). user = db.scalar(select(User).where(User.email == EMAIL))