Fix migration runner crashing on a genuinely fresh database
Build and push server image / build-and-push (push) Successful in 39s
Build and push server image / build-and-push (push) Successful in 39s
_migration_1() is Base.metadata.create_all() -- it already builds
today's full schema straight from models.py. Every migration after it
is an incremental ALTER/UPDATE meant to bring an *existing* install
forward from an older version; replaying them against a brand-new
database collided with columns create_all had already added ("duplicate
column name"), crashing on first boot.
Found while testing the device-status-bar change against a scratch DB.
Every real deployment has been migrating forward incrementally since
before this bug existed, so it never showed up in practice -- but any
brand-new install would have hit it. Fresh databases now jump straight
to the latest schema_version after create_all; existing databases keep
applying whichever migrations are still pending, same as before.
This commit is contained in:
+17
-11
@@ -94,17 +94,23 @@ def run_migrations() -> None:
|
||||
with engine.begin() as conn:
|
||||
conn.execute(text("CREATE TABLE IF NOT EXISTS schema_version (version INTEGER NOT NULL)"))
|
||||
row = conn.execute(text("SELECT version FROM schema_version")).fetchone()
|
||||
current = row[0] if row else 0
|
||||
for version, fn in MIGRATIONS:
|
||||
if version > current:
|
||||
logger.info("Applying schema migration %d", version)
|
||||
fn(conn)
|
||||
if row is None:
|
||||
conn.execute(
|
||||
text("INSERT INTO schema_version (version) VALUES (:v)"), {"v": version}
|
||||
)
|
||||
row = (version,)
|
||||
else:
|
||||
if row is None:
|
||||
# Brand new database: _migration_1's create_all() already
|
||||
# produces today's full schema straight from models.py.
|
||||
# Every migration after it is an incremental ALTER/UPDATE
|
||||
# meant to bring an *existing* install forward -- replaying
|
||||
# those here would just collide with columns create_all
|
||||
# already added (e.g. "duplicate column name"). Jump
|
||||
# straight to the latest version instead.
|
||||
_migration_1(conn)
|
||||
latest = MIGRATIONS[-1][0]
|
||||
conn.execute(text("INSERT INTO schema_version (version) VALUES (:v)"), {"v": latest})
|
||||
else:
|
||||
current = row[0]
|
||||
for version, fn in MIGRATIONS:
|
||||
if version > current:
|
||||
logger.info("Applying schema migration %d", version)
|
||||
fn(conn)
|
||||
conn.execute(text("UPDATE schema_version SET version = :v"), {"v": version})
|
||||
_ensure_frame_one()
|
||||
_ensure_server_settings()
|
||||
|
||||
Reference in New Issue
Block a user