147 lines
4.5 KiB
Python
Executable File
147 lines
4.5 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
"""
|
|
PostgreSQL-only migration runner
|
|
Manages migration state and runs migrations in order
|
|
"""
|
|
|
|
import os
|
|
import sys
|
|
import json
|
|
import subprocess
|
|
from datetime import datetime
|
|
from pathlib import Path
|
|
|
|
# Migration state file
|
|
MIGRATION_STATE_FILE = '/data/postgres_migrations_state.json'
|
|
|
|
# List of PostgreSQL migrations in order
|
|
POSTGRES_MIGRATIONS = [
|
|
'postgres_only_migration.py', # Main migration from commit 4214e88 onward
|
|
'add_note_sharing.sql', # Add note sharing functionality
|
|
]
|
|
|
|
|
|
def load_migration_state():
|
|
"""Load the migration state from file"""
|
|
if os.path.exists(MIGRATION_STATE_FILE):
|
|
try:
|
|
with open(MIGRATION_STATE_FILE, 'r') as f:
|
|
return json.load(f)
|
|
except:
|
|
return {}
|
|
return {}
|
|
|
|
|
|
def save_migration_state(state):
|
|
"""Save the migration state to file"""
|
|
os.makedirs(os.path.dirname(MIGRATION_STATE_FILE), exist_ok=True)
|
|
with open(MIGRATION_STATE_FILE, 'w') as f:
|
|
json.dump(state, f, indent=2)
|
|
|
|
|
|
def run_migration(migration_file):
|
|
"""Run a single migration script"""
|
|
script_path = os.path.join(os.path.dirname(__file__), migration_file)
|
|
|
|
if not os.path.exists(script_path):
|
|
print(f"⚠️ Migration {migration_file} not found, skipping...")
|
|
return False
|
|
|
|
print(f"\n🔄 Running migration: {migration_file}")
|
|
|
|
try:
|
|
# Check if it's a SQL file
|
|
if migration_file.endswith('.sql'):
|
|
# Run SQL file using psql
|
|
import os
|
|
db_host = os.environ.get('POSTGRES_HOST', 'db')
|
|
db_name = os.environ.get('POSTGRES_DB', 'timetrack')
|
|
db_user = os.environ.get('POSTGRES_USER', 'timetrack')
|
|
|
|
result = subprocess.run(
|
|
['psql', '-h', db_host, '-U', db_user, '-d', db_name, '-f', script_path],
|
|
capture_output=True,
|
|
text=True,
|
|
env={**os.environ, 'PGPASSWORD': os.environ.get('POSTGRES_PASSWORD', 'timetrack')}
|
|
)
|
|
else:
|
|
# Run Python migration script
|
|
result = subprocess.run(
|
|
[sys.executable, script_path],
|
|
capture_output=True,
|
|
text=True
|
|
)
|
|
|
|
if result.returncode == 0:
|
|
print(f"✅ {migration_file} completed successfully")
|
|
if result.stdout:
|
|
print(result.stdout)
|
|
return True
|
|
else:
|
|
print(f"❌ {migration_file} failed with return code {result.returncode}")
|
|
if result.stderr:
|
|
print(f"Error output: {result.stderr}")
|
|
if result.stdout:
|
|
print(f"Standard output: {result.stdout}")
|
|
return False
|
|
|
|
except Exception as e:
|
|
print(f"❌ Error running {migration_file}: {e}")
|
|
return False
|
|
|
|
|
|
def main():
|
|
"""Run all PostgreSQL migrations"""
|
|
print("=== PostgreSQL Database Migrations ===")
|
|
print(f"Running {len(POSTGRES_MIGRATIONS)} migrations...")
|
|
|
|
# Load migration state
|
|
state = load_migration_state()
|
|
|
|
success_count = 0
|
|
failed_count = 0
|
|
skipped_count = 0
|
|
|
|
for migration in POSTGRES_MIGRATIONS:
|
|
# Check if migration has already been run successfully
|
|
if state.get(migration, {}).get('status') == 'success':
|
|
print(f"\n⏭️ Skipping {migration} (already completed)")
|
|
skipped_count += 1
|
|
continue
|
|
|
|
# Run the migration
|
|
success = run_migration(migration)
|
|
|
|
# Update state
|
|
state[migration] = {
|
|
'status': 'success' if success else 'failed',
|
|
'timestamp': datetime.now().isoformat(),
|
|
'attempts': state.get(migration, {}).get('attempts', 0) + 1
|
|
}
|
|
|
|
if success:
|
|
success_count += 1
|
|
else:
|
|
failed_count += 1
|
|
|
|
# Save state after each migration
|
|
save_migration_state(state)
|
|
|
|
# Summary
|
|
print("\n" + "="*50)
|
|
print("PostgreSQL Migration Summary:")
|
|
print(f"✅ Successful: {success_count}")
|
|
print(f"❌ Failed: {failed_count}")
|
|
print(f"⏭️ Skipped: {skipped_count}")
|
|
print(f"📊 Total: {len(POSTGRES_MIGRATIONS)}")
|
|
|
|
if failed_count > 0:
|
|
print("\n⚠️ Some migrations failed. Check the logs above for details.")
|
|
return 1
|
|
else:
|
|
print("\n✨ All PostgreSQL migrations completed successfully!")
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main()) |