Add automatic schema versioning with startup migration
All checks were successful
Build and Push Docker Image / build-and-push (push) Successful in 57s

On startup, the app now checks if the database schema version matches
the code. If there's a mismatch or no version exists, it automatically
runs a full data migration before starting.

- Add backend/version.py with SCHEMA_VERSION constant
- Add backend/migration.py with extracted migration logic
- Add SchemaVersion model to track DB version
- Add version check functions to database.py
- Update app.py lifespan to use check_and_migrate_if_needed()
- Simplify migrate_csv_to_db.py to use shared logic

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Tudor
2026-01-16 10:23:02 +00:00
parent 352eeec2db
commit f4919db3b9
6 changed files with 564 additions and 406 deletions

View File

@@ -3,9 +3,11 @@ SQLAlchemy database models for school data.
Normalized schema with separate tables for schools and yearly results.
"""
from datetime import datetime
from sqlalchemy import (
Column, Integer, String, Float, ForeignKey, Index, UniqueConstraint,
Text, Boolean
Text, Boolean, DateTime
)
from sqlalchemy.orm import relationship
from .database import Base
@@ -133,6 +135,21 @@ class SchoolResult(Base):
return f"<SchoolResult(school_id={self.school_id}, year={self.year})>"
class SchemaVersion(Base):
"""
Tracks database schema version for automatic migrations.
Single-row table that stores the current schema version.
"""
__tablename__ = "schema_version"
id = Column(Integer, primary_key=True, default=1)
version = Column(Integer, nullable=False)
migrated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
def __repr__(self):
return f"<SchemaVersion(version={self.version}, migrated_at={self.migrated_at})>"
# Mapping from CSV columns to model fields
SCHOOL_FIELD_MAPPING = {
'urn': 'urn',