feat: auto-seed in dev mode on startup if DB empty
Some checks failed
Deploy Tracker / deploy (push) Failing after 4s

This commit is contained in:
markov 2026-02-25 08:41:44 +01:00
parent 7a58cf97c8
commit ce98d45712
2 changed files with 72 additions and 76 deletions

View File

@ -64,6 +64,15 @@ async def lifespan(app: FastAPI):
await conn.run_sync(Base.metadata.create_all) await conn.run_sync(Base.metadata.create_all)
logger.info("Database tables ensured.") logger.info("Database tables ensured.")
# Auto-seed if DB is empty (dev only)
async with async_session() as session:
result = await session.execute(select(Member).limit(1))
if not result.scalar_one_or_none():
logger.info("Empty DB detected in dev mode — running seed...")
from tracker.init_db import seed_dev_data
await seed_dev_data(session)
logger.info("Dev seed complete.")
heartbeat_task = asyncio.create_task(heartbeat_monitor()) heartbeat_task = asyncio.create_task(heartbeat_monitor())
yield yield
heartbeat_task.cancel() heartbeat_task.cancel()

View File

@ -1,11 +1,11 @@
"""Initialize database — drop all and create fresh tables + seed data.""" """Initialize database — dev seed data."""
import asyncio import asyncio
import hashlib import hashlib
import logging import logging
import uuid
from tracker.database import engine, async_session from sqlalchemy.ext.asyncio import AsyncSession
from tracker.enums import AuthMethod, ChatKind, MemberRole, MemberStatus, MemberType, ProjectStatus from tracker.enums import AuthMethod, ChatKind, MemberRole, MemberStatus, MemberType, ProjectStatus
from tracker.models import Base, Member, Chat, Project, ProjectMember, AgentConfig from tracker.models import Base, Member, Chat, Project, ProjectMember, AgentConfig
@ -16,16 +16,9 @@ def hash_password(password: str) -> str:
return hashlib.sha256(password.encode()).hexdigest() return hashlib.sha256(password.encode()).hexdigest()
async def init_db(): async def seed_dev_data(session: AsyncSession):
"""Drop all tables and recreate from models. Seed with admin + lobby.""" """Seed dev data into an existing session. Expects empty DB."""
async with engine.begin() as conn: # Admin (owner)
logger.info("Dropping all tables...")
await conn.run_sync(Base.metadata.drop_all)
logger.info("Creating all tables...")
await conn.run_sync(Base.metadata.create_all)
async with async_session() as session:
# Create admin (owner)
admin = Member( admin = Member(
name="Admin", name="Admin",
slug="admin", slug="admin",
@ -37,7 +30,7 @@ async def init_db():
) )
session.add(admin) session.add(admin)
# Create coder agent # Coder agent (for dev/testing)
coder = Member( coder = Member(
name="Coder", name="Coder",
slug="coder", slug="coder",
@ -48,11 +41,9 @@ async def init_db():
status=MemberStatus.OFFLINE, status=MemberStatus.OFFLINE,
) )
session.add(coder) session.add(coder)
# Flush to get member IDs
await session.flush() await session.flush()
# Create team-board project # Team-board project
project = Project( project = Project(
name="Team Board", name="Team Board",
slug="team-board", slug="team-board",
@ -62,39 +53,35 @@ async def init_db():
session.add(project) session.add(project)
await session.flush() await session.flush()
# Create project chat # Project chat
project_chat = Chat( project_chat = Chat(kind=ChatKind.PROJECT, project_id=project.id)
kind=ChatKind.PROJECT,
project_id=project.id,
)
session.add(project_chat) session.add(project_chat)
# Create project members # Project members
admin_member = ProjectMember( session.add(ProjectMember(project_id=project.id, member_id=admin.id, role=MemberRole.OWNER))
project_id=project.id, session.add(ProjectMember(project_id=project.id, member_id=coder.id, role=MemberRole.MEMBER))
member_id=admin.id,
role=MemberRole.OWNER,
)
session.add(admin_member)
coder_member = ProjectMember( # Lobby chat
project_id=project.id, lobby = Chat(kind=ChatKind.LOBBY, project_id=None)
member_id=coder.id,
role=MemberRole.MEMBER,
)
session.add(coder_member)
# Create lobby chat
lobby = Chat(
kind=ChatKind.LOBBY,
project_id=None,
)
session.add(lobby) session.add(lobby)
await session.commit() await session.commit()
logger.info("Seed data created: admin user, coder agent, team-board project (id=%s), lobby chat (id=%s)", project.id, lobby.id) logger.info("Dev seed: admin, coder, project team-board (id=%s), lobby", project.id)
async def reset_db():
"""Drop all tables, recreate, and seed. For dev use only."""
from tracker.database import engine, async_session
async with engine.begin() as conn:
await conn.run_sync(Base.metadata.drop_all)
await conn.run_sync(Base.metadata.create_all)
logger.info("Tables recreated.")
async with async_session() as session:
await seed_dev_data(session)
if __name__ == "__main__": if __name__ == "__main__":
logging.basicConfig(level=logging.INFO) logging.basicConfig(level=logging.INFO)
asyncio.run(init_db()) asyncio.run(reset_db())