From 1a0e90b22d8215d90708eea1e143a705ac079d27 Mon Sep 17 00:00:00 2001 From: Albrecht Degering Date: Mon, 20 Jul 2026 20:03:02 +0200 Subject: [PATCH] fix(migrations): preserve runtime logging during upgrades --- alembic/env.py | 5 ++++- tests/test_database_migrations.py | 19 +++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/alembic/env.py b/alembic/env.py index d00ecda..b294856 100644 --- a/alembic/env.py +++ b/alembic/env.py @@ -20,7 +20,10 @@ database_url = config.attributes.get("database_url") or settings.database_url config.set_main_option("sqlalchemy.url", database_url) if config.config_file_name is not None: - fileConfig(config.config_file_name) + # Migrations can run inside the long-lived application process when module + # state changes. Do not let Alembic's logging setup disable loggers that the + # server already created (for example slow-request diagnostics). + fileConfig(config.config_file_name, disable_existing_loggers=False) def _target_metadata(): diff --git a/tests/test_database_migrations.py b/tests/test_database_migrations.py index 8c31435..a98784c 100644 --- a/tests/test_database_migrations.py +++ b/tests/test_database_migrations.py @@ -1,5 +1,6 @@ from __future__ import annotations +import logging import tempfile import unittest from pathlib import Path @@ -39,6 +40,22 @@ def database_migration_heads(connection) -> set[str]: class DatabaseMigrationTests(unittest.TestCase): + def test_migration_logging_keeps_application_loggers_enabled(self) -> None: + logger = logging.getLogger("govoplan.request") + previous_disabled = logger.disabled + logger.disabled = False + try: + with tempfile.TemporaryDirectory(prefix="govoplan-migration-logging-test-") as directory: + database = Path(directory) / "logging.db" + command.stamp( + alembic_config(database_url=f"sqlite:///{database}", enabled_modules=()), + "heads", + ) + + self.assertFalse(logger.disabled) + finally: + logger.disabled = previous_disabled + def test_migration_tracks_use_separate_version_locations(self) -> None: release_locations = alembic_config(database_url="sqlite:////tmp/govoplan-release.db").get_main_option("version_locations") dev_locations = alembic_config( @@ -184,6 +201,7 @@ class DatabaseMigrationTests(unittest.TestCase): self.assertIsNone(result.reconciled_revision) self.assertEqual(current, configured_migration_heads(url)) self.assertEqual(result.current_revision, ",".join(sorted(current))) + self.assertIn("calendar_outbox_operations", tables) self.assertIn("calendar_sync_credentials", tables) self.assertIn("campaign_recipient_import_mapping_profiles", tables) self.assertIn("file_connector_credentials", tables) @@ -216,6 +234,7 @@ class DatabaseMigrationTests(unittest.TestCase): self.assertEqual(result.current_revision, ",".join(sorted(current))) self.assertIn("0f1e2d3c4b5a", current) self.assertIn("audit_outbox_events", tables) + self.assertIn("calendar_outbox_operations", tables) self.assertIn("file_connector_profiles", tables) self.assertIn("core_scopes", tables) finally: