Skip to content

Commit b8266a6

Browse files
committed
fix: entrypoint runs create_all + column patches before alembic stamp, fixing fresh-install crash
1 parent a886549 commit b8266a6

File tree

1 file changed

+80
-5
lines changed

1 file changed

+80
-5
lines changed

backend/entrypoint.sh

Lines changed: 80 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,84 @@
11
#!/bin/bash
2-
# Docker entrypoint: run DB migrations, then start the app.
3-
# Use bash (not sh/dash) to avoid CRLF/set-option compatibility issues.
2+
# Docker entrypoint: initialize DB tables, then start the app.
3+
# Order matters:
4+
# 1. create_all - creates all tables using SQLAlchemy models (idempotent)
5+
# 2. alembic stamp head - tells alembic we are at the latest revision (skips migrations)
6+
# For existing installs that may have missing columns, safe ALTER TABLE patches run first.
7+
# 3. uvicorn - starts the FastAPI app
8+
49
set -e
510

6-
echo "[entrypoint] Running database migrations..."
7-
alembic upgrade head
8-
echo "[entrypoint] Migrations done - starting uvicorn..."
11+
echo "[entrypoint] Step 1: Creating/verifying database tables..."
12+
13+
python << 'PYEOF'
14+
import asyncio, sys
15+
16+
async def main():
17+
# Import all models to populate Base.metadata before create_all
18+
from app.database import Base, engine
19+
import app.models.user # noqa
20+
import app.models.agent # noqa
21+
import app.models.task # noqa
22+
import app.models.llm # noqa
23+
import app.models.tool # noqa
24+
import app.models.audit # noqa
25+
import app.models.skill # noqa
26+
import app.models.channel_config # noqa
27+
import app.models.schedule # noqa
28+
import app.models.plaza # noqa
29+
import app.models.activity_log # noqa
30+
import app.models.org # noqa
31+
import app.models.system_settings # noqa
32+
import app.models.invitation_code # noqa
33+
import app.models.tenant # noqa
34+
import app.models.message # noqa
35+
import app.models.chat_session # noqa
36+
37+
# Create all tables that don't exist yet (safe to run on every startup)
38+
async with engine.begin() as conn:
39+
await conn.run_sync(Base.metadata.create_all)
40+
print("[entrypoint] Tables created/verified")
41+
42+
# Apply safe column patches for existing installs that may be missing columns.
43+
# All statements use IF NOT EXISTS so they are fully idempotent.
44+
patches = [
45+
# Quota fields added in v0.2
46+
"ALTER TABLE users ADD COLUMN IF NOT EXISTS quota_message_limit INTEGER DEFAULT 50",
47+
"ALTER TABLE users ADD COLUMN IF NOT EXISTS quota_message_period VARCHAR(20) DEFAULT 'permanent'",
48+
"ALTER TABLE users ADD COLUMN IF NOT EXISTS quota_messages_used INTEGER DEFAULT 0",
49+
"ALTER TABLE users ADD COLUMN IF NOT EXISTS quota_period_start TIMESTAMPTZ",
50+
"ALTER TABLE users ADD COLUMN IF NOT EXISTS quota_max_agents INTEGER DEFAULT 2",
51+
"ALTER TABLE users ADD COLUMN IF NOT EXISTS quota_agent_ttl_hours INTEGER DEFAULT 48",
52+
"ALTER TABLE agents ADD COLUMN IF NOT EXISTS expires_at TIMESTAMPTZ",
53+
"ALTER TABLE agents ADD COLUMN IF NOT EXISTS is_expired BOOLEAN DEFAULT FALSE",
54+
"ALTER TABLE agents ADD COLUMN IF NOT EXISTS llm_calls_today INTEGER DEFAULT 0",
55+
"ALTER TABLE agents ADD COLUMN IF NOT EXISTS max_llm_calls_per_day INTEGER DEFAULT 100",
56+
"ALTER TABLE agents ADD COLUMN IF NOT EXISTS llm_calls_reset_at TIMESTAMPTZ",
57+
# agent_tools source tracking added later
58+
"ALTER TABLE agent_tools ADD COLUMN IF NOT EXISTS source VARCHAR(20) NOT NULL DEFAULT 'system'",
59+
"ALTER TABLE agent_tools ADD COLUMN IF NOT EXISTS installed_by_agent_id UUID",
60+
# chat_sessions channel tracking
61+
"ALTER TABLE chat_sessions ADD COLUMN IF NOT EXISTS source_channel VARCHAR(20) NOT NULL DEFAULT 'web'",
62+
]
63+
64+
from sqlalchemy import text
65+
async with engine.begin() as conn:
66+
for sql in patches:
67+
try:
68+
await conn.execute(text(sql))
69+
except Exception as e:
70+
print(f"[entrypoint] Patch skipped ({e})")
71+
72+
await engine.dispose()
73+
print("[entrypoint] Column patches applied")
74+
75+
asyncio.run(main())
76+
PYEOF
77+
78+
echo "[entrypoint] Step 2: Stamping alembic to latest revision..."
79+
# Mark all migrations as applied so alembic does not re-run them on top of create_all.
80+
# This is safe: create_all already created tables with all current columns.
81+
alembic stamp head
82+
83+
echo "[entrypoint] Step 3: Starting uvicorn..."
984
exec uvicorn app.main:app --host 0.0.0.0 --port 8000

0 commit comments

Comments
 (0)