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,85 +16,72 @@ 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."""
# Admin (owner)
admin = Member(
name="Admin",
slug="admin",
type=MemberType.HUMAN,
role=MemberRole.OWNER,
auth_method=AuthMethod.PASSWORD,
password_hash=hash_password("teamboard"),
status=MemberStatus.OFFLINE,
)
session.add(admin)
# Coder agent (for dev/testing)
coder = Member(
name="Coder",
slug="coder",
type=MemberType.AGENT,
role=MemberRole.MEMBER,
auth_method=AuthMethod.TOKEN,
token="tb-coder-dev-token",
status=MemberStatus.OFFLINE,
)
session.add(coder)
await session.flush()
# Team-board project
project = Project(
name="Team Board",
slug="team-board",
description="AI agent collaboration platform",
status=ProjectStatus.ACTIVE,
)
session.add(project)
await session.flush()
# Project chat
project_chat = Chat(kind=ChatKind.PROJECT, project_id=project.id)
session.add(project_chat)
# Project members
session.add(ProjectMember(project_id=project.id, member_id=admin.id, role=MemberRole.OWNER))
session.add(ProjectMember(project_id=project.id, member_id=coder.id, role=MemberRole.MEMBER))
# Lobby chat
lobby = Chat(kind=ChatKind.LOBBY, project_id=None)
session.add(lobby)
await session.commit()
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: async with engine.begin() as conn:
logger.info("Dropping all tables...")
await conn.run_sync(Base.metadata.drop_all) await conn.run_sync(Base.metadata.drop_all)
logger.info("Creating all tables...")
await conn.run_sync(Base.metadata.create_all) await conn.run_sync(Base.metadata.create_all)
logger.info("Tables recreated.")
async with async_session() as session: async with async_session() as session:
# Create admin (owner) await seed_dev_data(session)
admin = Member(
name="Admin",
slug="admin",
type=MemberType.HUMAN,
role=MemberRole.OWNER,
auth_method=AuthMethod.PASSWORD,
password_hash=hash_password("teamboard"),
status=MemberStatus.OFFLINE,
)
session.add(admin)
# Create coder agent
coder = Member(
name="Coder",
slug="coder",
type=MemberType.AGENT,
role=MemberRole.MEMBER,
auth_method=AuthMethod.TOKEN,
token="tb-coder-dev-token",
status=MemberStatus.OFFLINE,
)
session.add(coder)
# Flush to get member IDs
await session.flush()
# Create team-board project
project = Project(
name="Team Board",
slug="team-board",
description="AI agent collaboration platform",
status=ProjectStatus.ACTIVE,
)
session.add(project)
await session.flush()
# Create project chat
project_chat = Chat(
kind=ChatKind.PROJECT,
project_id=project.id,
)
session.add(project_chat)
# Create project members
admin_member = ProjectMember(
project_id=project.id,
member_id=admin.id,
role=MemberRole.OWNER,
)
session.add(admin_member)
coder_member = ProjectMember(
project_id=project.id,
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)
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)
if __name__ == "__main__": if __name__ == "__main__":
logging.basicConfig(level=logging.INFO) logging.basicConfig(level=logging.INFO)
asyncio.run(init_db()) asyncio.run(reset_db())