diff --git a/CHANGELOG.rst b/CHANGELOG.rst index b4f7feae96..6c26d95bd8 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -17,6 +17,16 @@ Unreleased ---------- * nothing unreleased +[8.17.1] - 2026-09-30 +---------------------- +* fix: The MariaDB UUID conversions in ``blackboard`` 0025, ``canvas`` 0041 and + ``integrated_channel`` 0037 altered the enterprise-integrated-channels tables + (``blackboard_channel_*``, ``canvas_channel_*``, ``channel_integration_*``) + instead of this package's own, so ``migrate`` failed on a fresh MariaDB + database and left these apps' UUID columns as char(32). They now name this + package's tables, and new migrations convert those tables on databases that + already applied the old versions. + [8.17.0] - 2026-09-29 ---------------------- * feat: Add ``enterprise_learner_generic_name`` and ``enterprise_learner_portal_link`` diff --git a/enterprise/__init__.py b/enterprise/__init__.py index 0da8a68fca..7c1a016393 100644 --- a/enterprise/__init__.py +++ b/enterprise/__init__.py @@ -2,4 +2,4 @@ Your project description goes here. """ -__version__ = "8.17.0" +__version__ = "8.17.1" diff --git a/integrated_channels/blackboard/migrations/0025_mariadb_uuid_conversion.py b/integrated_channels/blackboard/migrations/0025_mariadb_uuid_conversion.py index 981829b966..2dbeb097ac 100644 --- a/integrated_channels/blackboard/migrations/0025_mariadb_uuid_conversion.py +++ b/integrated_channels/blackboard/migrations/0025_mariadb_uuid_conversion.py @@ -21,7 +21,7 @@ def apply_mariadb_migration(apps, schema_editor): return with connection.cursor() as cursor: - cursor.execute("ALTER TABLE blackboard_channel_blackboardenterprisecustomerconfiguration MODIFY uuid uuid NOT NULL") + cursor.execute("ALTER TABLE blackboard_blackboardenterprisecustomerconfiguration MODIFY uuid uuid NOT NULL") def reverse_mariadb_migration(apps, schema_editor): @@ -37,7 +37,7 @@ def reverse_mariadb_migration(apps, schema_editor): return with connection.cursor() as cursor: - cursor.execute("ALTER TABLE blackboard_channel_blackboardenterprisecustomerconfiguration MODIFY uuid char(32) NOT NULL") + cursor.execute("ALTER TABLE blackboard_blackboardenterprisecustomerconfiguration MODIFY uuid char(32) NOT NULL") class Migration(migrations.Migration): diff --git a/integrated_channels/blackboard/migrations/0026_mariadb_uuid_conversion_own_table.py b/integrated_channels/blackboard/migrations/0026_mariadb_uuid_conversion_own_table.py new file mode 100644 index 0000000000..ee9f8260b8 --- /dev/null +++ b/integrated_channels/blackboard/migrations/0026_mariadb_uuid_conversion_own_table.py @@ -0,0 +1,46 @@ +""" +Convert blackboard_blackboardenterprisecustomerconfiguration.uuid from char(32) to uuid on MariaDB. + +0025_mariadb_uuid_conversion was released altering +blackboard_channel_blackboardenterprisecustomerconfiguration, the +enterprise-integrated-channels copy of this table, which that package converts +in its own migrations. On a fresh database 0025 failed because nothing creates +that table first, and on existing databases this table kept its char(32) +column. 0025 now names this table; this migration converts it on databases that +applied the old version. MODIFY to the type a column already has changes +nothing, so it is also safe after the corrected 0025. + +See: https://docs.djangoproject.com/en/5.2/releases/5.0/#migrating-uuidfield +""" + +from django.db import migrations + + +def _is_mariadb(connection): + if connection.vendor != 'mysql': + return False + with connection.cursor() as cursor: + cursor.execute("SELECT VERSION()") + return 'mariadb' in cursor.fetchone()[0].lower() + + +def apply_mariadb_migration(apps, schema_editor): + if not _is_mariadb(schema_editor.connection): + return + with schema_editor.connection.cursor() as cursor: + cursor.execute("ALTER TABLE blackboard_blackboardenterprisecustomerconfiguration MODIFY uuid uuid NOT NULL") + + +class Migration(migrations.Migration): + + dependencies = [ + ('blackboard', '0025_mariadb_uuid_conversion'), + ] + + operations = [ + # Reversing to char(32) is left to 0025_mariadb_uuid_conversion, which this repeats. + migrations.RunPython( + code=apply_mariadb_migration, + reverse_code=migrations.RunPython.noop, + ), + ] diff --git a/integrated_channels/canvas/migrations/0041_mariadb_uuid_conversion.py b/integrated_channels/canvas/migrations/0041_mariadb_uuid_conversion.py index c90968cf8e..bfee48c823 100644 --- a/integrated_channels/canvas/migrations/0041_mariadb_uuid_conversion.py +++ b/integrated_channels/canvas/migrations/0041_mariadb_uuid_conversion.py @@ -21,7 +21,7 @@ def apply_mariadb_migration(apps, schema_editor): return with connection.cursor() as cursor: - cursor.execute("ALTER TABLE canvas_channel_canvasenterprisecustomerconfiguration MODIFY uuid uuid NOT NULL") + cursor.execute("ALTER TABLE canvas_canvasenterprisecustomerconfiguration MODIFY uuid uuid NOT NULL") def reverse_mariadb_migration(apps, schema_editor): @@ -37,7 +37,7 @@ def reverse_mariadb_migration(apps, schema_editor): return with connection.cursor() as cursor: - cursor.execute("ALTER TABLE canvas_channel_canvasenterprisecustomerconfiguration MODIFY uuid char(32) NOT NULL") + cursor.execute("ALTER TABLE canvas_canvasenterprisecustomerconfiguration MODIFY uuid char(32) NOT NULL") class Migration(migrations.Migration): diff --git a/integrated_channels/canvas/migrations/0042_mariadb_uuid_conversion_own_table.py b/integrated_channels/canvas/migrations/0042_mariadb_uuid_conversion_own_table.py new file mode 100644 index 0000000000..5cf1078f8a --- /dev/null +++ b/integrated_channels/canvas/migrations/0042_mariadb_uuid_conversion_own_table.py @@ -0,0 +1,46 @@ +""" +Convert canvas_canvasenterprisecustomerconfiguration.uuid from char(32) to uuid on MariaDB. + +0041_mariadb_uuid_conversion was released altering +canvas_channel_canvasenterprisecustomerconfiguration, the +enterprise-integrated-channels copy of this table, which that package converts +in its own migrations. On a fresh database 0041 failed because nothing creates +that table first, and on existing databases this table kept its char(32) +column. 0041 now names this table; this migration converts it on databases that +applied the old version. MODIFY to the type a column already has changes +nothing, so it is also safe after the corrected 0041. + +See: https://docs.djangoproject.com/en/5.2/releases/5.0/#migrating-uuidfield +""" + +from django.db import migrations + + +def _is_mariadb(connection): + if connection.vendor != 'mysql': + return False + with connection.cursor() as cursor: + cursor.execute("SELECT VERSION()") + return 'mariadb' in cursor.fetchone()[0].lower() + + +def apply_mariadb_migration(apps, schema_editor): + if not _is_mariadb(schema_editor.connection): + return + with schema_editor.connection.cursor() as cursor: + cursor.execute("ALTER TABLE canvas_canvasenterprisecustomerconfiguration MODIFY uuid uuid NOT NULL") + + +class Migration(migrations.Migration): + + dependencies = [ + ('canvas', '0041_mariadb_uuid_conversion'), + ] + + operations = [ + # Reversing to char(32) is left to 0041_mariadb_uuid_conversion, which this repeats. + migrations.RunPython( + code=apply_mariadb_migration, + reverse_code=migrations.RunPython.noop, + ), + ] diff --git a/integrated_channels/integrated_channel/migrations/0037_mariadb_uuid_conversion.py b/integrated_channels/integrated_channel/migrations/0037_mariadb_uuid_conversion.py index ff0cd4f587..14517a8535 100644 --- a/integrated_channels/integrated_channel/migrations/0037_mariadb_uuid_conversion.py +++ b/integrated_channels/integrated_channel/migrations/0037_mariadb_uuid_conversion.py @@ -21,8 +21,8 @@ def apply_mariadb_migration(apps, schema_editor): return with connection.cursor() as cursor: - cursor.execute("ALTER TABLE channel_integration_genericlearnerdatatransmissionaudit MODIFY enterprise_customer_uuid uuid NULL") - cursor.execute("ALTER TABLE channel_integration_contentmetadataitemtransmission MODIFY enterprise_customer_catalog_uuid uuid NOT NULL") + cursor.execute("ALTER TABLE integrated_channel_genericlearnerdatatransmissionaudit MODIFY enterprise_customer_uuid uuid NULL") + cursor.execute("ALTER TABLE integrated_channel_contentmetadataitemtransmission MODIFY enterprise_customer_catalog_uuid uuid NULL") def reverse_mariadb_migration(apps, schema_editor): @@ -38,8 +38,8 @@ def reverse_mariadb_migration(apps, schema_editor): return with connection.cursor() as cursor: - cursor.execute("ALTER TABLE channel_integration_genericlearnerdatatransmissionaudit MODIFY enterprise_customer_uuid char(32) NULL") - cursor.execute("ALTER TABLE channel_integration_contentmetadataitemtransmission MODIFY enterprise_customer_catalog_uuid char(32) NOT NULL") + cursor.execute("ALTER TABLE integrated_channel_genericlearnerdatatransmissionaudit MODIFY enterprise_customer_uuid char(32) NULL") + cursor.execute("ALTER TABLE integrated_channel_contentmetadataitemtransmission MODIFY enterprise_customer_catalog_uuid char(32) NULL") class Migration(migrations.Migration): diff --git a/integrated_channels/integrated_channel/migrations/0038_mariadb_uuid_conversion_own_tables.py b/integrated_channels/integrated_channel/migrations/0038_mariadb_uuid_conversion_own_tables.py new file mode 100644 index 0000000000..caa23a45c3 --- /dev/null +++ b/integrated_channels/integrated_channel/migrations/0038_mariadb_uuid_conversion_own_tables.py @@ -0,0 +1,47 @@ +""" +Convert this app's UUIDField columns from char(32) to uuid on MariaDB. + +0037_mariadb_uuid_conversion was released altering the channel_integration_* +tables, the enterprise-integrated-channels copies of this app's tables, which +that package converts in its own migrations. Nothing creates those tables +before 0037, so a fresh migrate only succeeds when Django happens to order +them first, and this app's own columns kept char(32). 0037 now +names this app's tables; this migration converts them on databases that +applied the old version. MODIFY to the type a column already has changes +nothing, so it is also safe after the corrected 0037. + +See: https://docs.djangoproject.com/en/5.2/releases/5.0/#migrating-uuidfield +""" + +from django.db import migrations + + +def _is_mariadb(connection): + if connection.vendor != 'mysql': + return False + with connection.cursor() as cursor: + cursor.execute("SELECT VERSION()") + return 'mariadb' in cursor.fetchone()[0].lower() + + +def apply_mariadb_migration(apps, schema_editor): + if not _is_mariadb(schema_editor.connection): + return + with schema_editor.connection.cursor() as cursor: + cursor.execute("ALTER TABLE integrated_channel_genericlearnerdatatransmissionaudit MODIFY enterprise_customer_uuid uuid NULL") + cursor.execute("ALTER TABLE integrated_channel_contentmetadataitemtransmission MODIFY enterprise_customer_catalog_uuid uuid NULL") + + +class Migration(migrations.Migration): + + dependencies = [ + ('integrated_channel', '0037_mariadb_uuid_conversion'), + ] + + operations = [ + # Reversing to char(32) is left to 0037_mariadb_uuid_conversion, which this repeats. + migrations.RunPython( + code=apply_mariadb_migration, + reverse_code=migrations.RunPython.noop, + ), + ]