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>
69 lines
2.0 KiB
Python
69 lines
2.0 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
CLI script for manual database migration.
|
|
|
|
Usage:
|
|
python scripts/migrate_csv_to_db.py [--drop] [--geocode]
|
|
|
|
Options:
|
|
--drop Drop existing tables before migration (full reimport)
|
|
--geocode Geocode postcodes (requires network access)
|
|
"""
|
|
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
# Add parent directory to path for imports
|
|
sys.path.insert(0, str(Path(__file__).parent.parent))
|
|
|
|
import argparse
|
|
|
|
from backend.config import settings
|
|
from backend.database import Base, engine, init_db, set_db_schema_version
|
|
from backend.migration import load_csv_data, migrate_data, run_full_migration
|
|
from backend.version import SCHEMA_VERSION
|
|
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser(
|
|
description="Migrate CSV data to PostgreSQL database"
|
|
)
|
|
parser.add_argument(
|
|
"--drop", action="store_true", help="Drop existing tables before migration"
|
|
)
|
|
parser.add_argument("--geocode", action="store_true", help="Geocode postcodes")
|
|
args = parser.parse_args()
|
|
|
|
print("=" * 60)
|
|
print("School Data Migration: CSV -> PostgreSQL")
|
|
print("=" * 60)
|
|
print(f"\nDatabase: {settings.database_url.split('@')[-1]}")
|
|
print(f"Data directory: {settings.data_dir}")
|
|
print(f"Target schema version: {SCHEMA_VERSION}")
|
|
|
|
if args.drop:
|
|
print("\nRunning full migration (drop + reimport)...")
|
|
success = run_full_migration(geocode=args.geocode)
|
|
else:
|
|
print("\nCreating tables (preserving existing data)...")
|
|
init_db()
|
|
print("\nLoading CSV data...")
|
|
df = load_csv_data(settings.data_dir)
|
|
if df.empty:
|
|
print("No data found to migrate!")
|
|
return 1
|
|
migrate_data(df, geocode=args.geocode)
|
|
success = True
|
|
|
|
if success:
|
|
# Ensure schema_version table exists
|
|
init_db()
|
|
set_db_schema_version(SCHEMA_VERSION)
|
|
print(f"\nSchema version set to {SCHEMA_VERSION}")
|
|
|
|
return 0 if success else 1
|
|
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main())
|