commit 1eeea9f83ad9230a5c1f7a75662770eaab0df837 Author: Jens Luedicke <jens@luedicke.me> Date: Mon Jul 7 21:15:41 2025 +0200 Disable resuming of old time entries. commit 3e3ec2f01cb7943622b819a19179388078ae1315 Author: Jens Luedicke <jens@luedicke.me> Date: Mon Jul 7 20:59:19 2025 +0200 Refactor db migrations. commit 15a51a569da36c6b7c9e01ab17b6fdbdee6ad994 Author: Jens Luedicke <jens@luedicke.me> Date: Mon Jul 7 19:58:04 2025 +0200 Apply new style for Time Tracking view. commit 77e5278b303e060d2b03853b06277f8aa567ae68 Author: Jens Luedicke <jens@luedicke.me> Date: Mon Jul 7 18:06:04 2025 +0200 Allow direct registrations as a Company. commit 188a8772757cbef374243d3a5f29e4440ddecabe Author: Jens Luedicke <jens@luedicke.me> Date: Mon Jul 7 18:04:45 2025 +0200 Add email invitation feature. commit d9ebaa02aa01b518960a20dccdd5a327d82f30c6 Author: Jens Luedicke <jens@luedicke.me> Date: Mon Jul 7 17:12:32 2025 +0200 Apply common style for Company, User, Team management pages. commit 81149caf4d8fc6317e2ab1b4f022b32fc5aa6d22 Author: Jens Luedicke <jens@luedicke.me> Date: Mon Jul 7 16:44:32 2025 +0200 Move export functions to own module. commit 1a26e19338e73f8849c671471dd15cc3c1b1fe82 Author: Jens Luedicke <jens@luedicke.me> Date: Mon Jul 7 15:51:15 2025 +0200 Split up models.py. commit 61f1ccd10f721b0ff4dc1eccf30c7a1ee13f204d Author: Jens Luedicke <jens@luedicke.me> Date: Mon Jul 7 12:05:28 2025 +0200 Move utility function into own modules. commit 84b341ed35e2c5387819a8b9f9d41eca900ae79f Author: Jens Luedicke <jens@luedicke.me> Date: Mon Jul 7 11:44:24 2025 +0200 Refactor auth functions use. commit 923e311e3da5b26d85845c2832b73b7b17c48adb Author: Jens Luedicke <jens@luedicke.me> Date: Mon Jul 7 11:35:52 2025 +0200 Refactor route nameing and fix bugs along the way. commit f0a5c4419c340e62a2615c60b2a9de28204d2995 Author: Jens Luedicke <jens@luedicke.me> Date: Mon Jul 7 10:34:33 2025 +0200 Fix URL endpoints in announcement template. commit b74d74542a1c8dc350749e4788a9464d067a88b5 Author: Jens Luedicke <jens@luedicke.me> Date: Mon Jul 7 09:25:53 2025 +0200 Move announcements to own module. commit 9563a28021ac46c82c04fe4649b394dbf96f92c7 Author: Jens Luedicke <jens@luedicke.me> Date: Mon Jul 7 09:16:30 2025 +0200 Combine Company view and edit templates. commit 6687c373e681d54e4deab6b2582fed5cea9aadf6 Author: Jens Luedicke <jens@luedicke.me> Date: Mon Jul 7 08:17:42 2025 +0200 Move Users, Company and System Administration to own modules. commit 8b7894a2e3eb84bb059f546648b6b9536fea724e Author: Jens Luedicke <jens@luedicke.me> Date: Mon Jul 7 07:40:57 2025 +0200 Move Teams and Projects to own modules. commit d11bf059d99839ecf1f5d7020b8c8c8a2454c00b Author: Jens Luedicke <jens@luedicke.me> Date: Mon Jul 7 07:09:33 2025 +0200 Move Tasks and Sprints to own modules.
138 lines
4.3 KiB
Python
Executable File
138 lines
4.3 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
"""
|
|
Master database migration runner
|
|
Runs all database schema migrations in the correct order
|
|
"""
|
|
|
|
import os
|
|
import sys
|
|
import subprocess
|
|
import json
|
|
from datetime import datetime
|
|
|
|
# Migration state file
|
|
MIGRATION_STATE_FILE = '/data/db_migrations_state.json'
|
|
|
|
# List of database schema migrations in order
|
|
DB_MIGRATIONS = [
|
|
'01_migrate_db.py', # SQLite schema updates (must run before data migration)
|
|
'20_add_company_updated_at.py', # Add updated_at column BEFORE data migration
|
|
'02_migrate_sqlite_to_postgres_fixed.py', # Fixed SQLite to PostgreSQL data migration
|
|
'03_add_dashboard_columns.py',
|
|
'04_add_user_preferences_columns.py',
|
|
'05_fix_task_status_enum.py',
|
|
'06_add_archived_status.py',
|
|
'07_fix_company_work_config_columns.py',
|
|
'08_fix_work_region_enum.py',
|
|
'09_add_germany_to_workregion.py',
|
|
'10_add_company_settings_columns.py',
|
|
'19_add_company_invitations.py'
|
|
]
|
|
|
|
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:
|
|
# Run the 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 database migrations"""
|
|
print("=== Database Schema Migrations ===")
|
|
print(f"Running {len(DB_MIGRATIONS)} migrations...")
|
|
|
|
# Load migration state
|
|
state = load_migration_state()
|
|
|
|
success_count = 0
|
|
failed_count = 0
|
|
skipped_count = 0
|
|
|
|
for migration in DB_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
|
|
# Don't stop on failure, continue with other migrations
|
|
print(f"⚠️ Continuing despite failure in {migration}")
|
|
|
|
# Save state after each migration
|
|
save_migration_state(state)
|
|
|
|
# Summary
|
|
print("\n" + "="*50)
|
|
print("Database Migration Summary:")
|
|
print(f"✅ Successful: {success_count}")
|
|
print(f"❌ Failed: {failed_count}")
|
|
print(f"⏭️ Skipped: {skipped_count}")
|
|
print(f"📊 Total: {len(DB_MIGRATIONS)}")
|
|
|
|
if failed_count > 0:
|
|
print("\n⚠️ Some migrations failed. Check the logs above for details.")
|
|
return 1
|
|
else:
|
|
print("\n✨ All database migrations completed successfully!")
|
|
return 0
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main()) |