From 4f1638bda03f61425d20f2e77f30f93de0dba6ec Mon Sep 17 00:00:00 2001 From: cproudlock Date: Fri, 26 Jun 2026 14:48:07 -0400 Subject: [PATCH] Consolidate bundled plugin schema into the core migration chain The core chain already owns and reproduces the full bundled schema (deploys run `flask db upgrade` only). The per-plugin Alembic baselines duplicated those tables, so `flask plugin upgrade-all` would conflict - a footgun. Remove the 6 bundled plugin migration dirs; the per-plugin Alembic helpers (alembic_template, PluginMigrationRunner) remain for external/filesystem plugins. upgrade-all now cleanly no-ops for bundled plugins. Co-Authored-By: Claude Opus 4.8 --- plugins/computers/migrations/alembic.ini | 30 ------------- plugins/computers/migrations/env.py | 12 ----- plugins/computers/migrations/script.py.mako | 23 ---------- .../migrations/versions/0001_baseline.py | 27 ------------ .../versions/0002_pc_hardware_fields.py | 44 ------------------- plugins/equipment/migrations/alembic.ini | 30 ------------- plugins/equipment/migrations/env.py | 12 ----- plugins/equipment/migrations/script.py.mako | 23 ---------- .../migrations/versions/0001_baseline.py | 27 ------------ plugins/network/migrations/alembic.ini | 30 ------------- plugins/network/migrations/env.py | 12 ----- plugins/network/migrations/script.py.mako | 23 ---------- .../migrations/versions/0001_baseline.py | 27 ------------ plugins/notifications/migrations/alembic.ini | 30 ------------- plugins/notifications/migrations/env.py | 12 ----- .../notifications/migrations/script.py.mako | 23 ---------- .../migrations/versions/0001_baseline.py | 27 ------------ plugins/printers/migrations/__init__.py | 1 - plugins/printers/migrations/alembic.ini | 30 ------------- plugins/printers/migrations/env.py | 12 ----- plugins/printers/migrations/script.py.mako | 23 ---------- .../migrations/versions/0001_baseline.py | 27 ------------ .../migrations/versions/0002_modelsupplies.py | 44 ------------------- plugins/usb/migrations/alembic.ini | 30 ------------- plugins/usb/migrations/env.py | 12 ----- plugins/usb/migrations/script.py.mako | 23 ---------- .../usb/migrations/versions/0001_baseline.py | 27 ------------ tests/test_plugin_migrations.py | 28 +++--------- 28 files changed, 7 insertions(+), 662 deletions(-) delete mode 100644 plugins/computers/migrations/alembic.ini delete mode 100644 plugins/computers/migrations/env.py delete mode 100644 plugins/computers/migrations/script.py.mako delete mode 100644 plugins/computers/migrations/versions/0001_baseline.py delete mode 100644 plugins/computers/migrations/versions/0002_pc_hardware_fields.py delete mode 100644 plugins/equipment/migrations/alembic.ini delete mode 100644 plugins/equipment/migrations/env.py delete mode 100644 plugins/equipment/migrations/script.py.mako delete mode 100644 plugins/equipment/migrations/versions/0001_baseline.py delete mode 100644 plugins/network/migrations/alembic.ini delete mode 100644 plugins/network/migrations/env.py delete mode 100644 plugins/network/migrations/script.py.mako delete mode 100644 plugins/network/migrations/versions/0001_baseline.py delete mode 100644 plugins/notifications/migrations/alembic.ini delete mode 100644 plugins/notifications/migrations/env.py delete mode 100644 plugins/notifications/migrations/script.py.mako delete mode 100644 plugins/notifications/migrations/versions/0001_baseline.py delete mode 100644 plugins/printers/migrations/__init__.py delete mode 100644 plugins/printers/migrations/alembic.ini delete mode 100644 plugins/printers/migrations/env.py delete mode 100644 plugins/printers/migrations/script.py.mako delete mode 100644 plugins/printers/migrations/versions/0001_baseline.py delete mode 100644 plugins/printers/migrations/versions/0002_modelsupplies.py delete mode 100644 plugins/usb/migrations/alembic.ini delete mode 100644 plugins/usb/migrations/env.py delete mode 100644 plugins/usb/migrations/script.py.mako delete mode 100644 plugins/usb/migrations/versions/0001_baseline.py diff --git a/plugins/computers/migrations/alembic.ini b/plugins/computers/migrations/alembic.ini deleted file mode 100644 index 0775ad4..0000000 --- a/plugins/computers/migrations/alembic.ini +++ /dev/null @@ -1,30 +0,0 @@ -[alembic] -script_location = . -prepend_sys_path = . -file_template = %%(rev)s_%%(slug)s - -[logging] -keys = root - -[loggers] -keys = root - -[handlers] -keys = console - -[formatters] -keys = generic - -[logger_root] -level = INFO -handlers = console -qualname = - -[handler_console] -class = StreamHandler -args = (sys.stderr,) -level = INFO -formatter = generic - -[formatter_generic] -format = %%(levelname)-5.5s [%%(name)s] %%(message)s diff --git a/plugins/computers/migrations/env.py b/plugins/computers/migrations/env.py deleted file mode 100644 index 037991d..0000000 --- a/plugins/computers/migrations/env.py +++ /dev/null @@ -1,12 +0,0 @@ -"""Alembic env.py for the computers plugin. - -Thin shim that sets PLUGIN_NAME then delegates to the shared template at -shopdb.plugins.alembic_template, which filters MetaData to only this -plugin's tables and runs Alembic against the Flask app's engine. -""" -import os -os.environ['PLUGIN_NAME'] = 'computers' - -from shopdb.plugins.alembic_template import run_migrations - -run_migrations() diff --git a/plugins/computers/migrations/script.py.mako b/plugins/computers/migrations/script.py.mako deleted file mode 100644 index f230367..0000000 --- a/plugins/computers/migrations/script.py.mako +++ /dev/null @@ -1,23 +0,0 @@ -"""${message} - -Revision ID: ${up_revision} -Revises: ${down_revision | comma,n} -Create Date: ${create_date} - -""" -from alembic import op -import sqlalchemy as sa -${imports if imports else ""} - -revision = ${repr(up_revision)} -down_revision = ${repr(down_revision)} -branch_labels = ${repr(branch_labels)} -depends_on = ${repr(depends_on)} - - -def upgrade(): - ${upgrades if upgrades else "pass"} - - -def downgrade(): - ${downgrades if downgrades else "pass"} diff --git a/plugins/computers/migrations/versions/0001_baseline.py b/plugins/computers/migrations/versions/0001_baseline.py deleted file mode 100644 index f2c21b1..0000000 --- a/plugins/computers/migrations/versions/0001_baseline.py +++ /dev/null @@ -1,27 +0,0 @@ -"""computers plugin: baseline schema - -Creates every table owned by the computers plugin per -shopdb.plugins.alembic_template.PLUGIN_TABLE_OWNERS. The table definitions -are derived from the SQLAlchemy models at migration runtime so this stays -in lockstep with the model layer without duplication. - -Revision ID: 0001_baseline_computers -Revises: -Create Date: 2026-05-30 - -""" -from shopdb.plugins.alembic_template import create_plugin_tables, drop_plugin_tables - - -revision = '0001_baseline_computers' -down_revision = None -branch_labels = None -depends_on = None - - -def upgrade(): - create_plugin_tables('computers') - - -def downgrade(): - drop_plugin_tables('computers') diff --git a/plugins/computers/migrations/versions/0002_pc_hardware_fields.py b/plugins/computers/migrations/versions/0002_pc_hardware_fields.py deleted file mode 100644 index a82b791..0000000 --- a/plugins/computers/migrations/versions/0002_pc_hardware_fields.py +++ /dev/null @@ -1,44 +0,0 @@ -"""Add PC hardware make/model + installed-app version string - -Adds computers.vendorid + computers.modelnumberid (PCs carry vendor/model like -equipment) and computerinstalledapps.installedversion (raw version string from -automated collection, when there is no curated AppVersion). Supports moving the -PC form and the collector off the legacy Machine model onto the asset/computer -model (ADR-001). - -Revision ID: 0002_pc_hardware -Revises: 0001_baseline_computers -Create Date: 2026-06-26 - -""" -from alembic import op -import sqlalchemy as sa - - -revision = '0002_pc_hardware' -down_revision = '0001_baseline_computers' -branch_labels = None -depends_on = None - - -def upgrade(): - with op.batch_alter_table('computers') as batch_op: - batch_op.add_column(sa.Column('vendorid', sa.Integer(), nullable=True)) - batch_op.add_column(sa.Column('modelnumberid', sa.Integer(), nullable=True)) - batch_op.create_foreign_key('fk_computers_vendor', 'vendors', - ['vendorid'], ['vendorid']) - batch_op.create_foreign_key('fk_computers_model', 'models', - ['modelnumberid'], ['modelnumberid']) - with op.batch_alter_table('computerinstalledapps') as batch_op: - batch_op.add_column(sa.Column('installedversion', sa.String(length=100), - nullable=True)) - - -def downgrade(): - with op.batch_alter_table('computerinstalledapps') as batch_op: - batch_op.drop_column('installedversion') - with op.batch_alter_table('computers') as batch_op: - batch_op.drop_constraint('fk_computers_model', type_='foreignkey') - batch_op.drop_constraint('fk_computers_vendor', type_='foreignkey') - batch_op.drop_column('modelnumberid') - batch_op.drop_column('vendorid') diff --git a/plugins/equipment/migrations/alembic.ini b/plugins/equipment/migrations/alembic.ini deleted file mode 100644 index 0775ad4..0000000 --- a/plugins/equipment/migrations/alembic.ini +++ /dev/null @@ -1,30 +0,0 @@ -[alembic] -script_location = . -prepend_sys_path = . -file_template = %%(rev)s_%%(slug)s - -[logging] -keys = root - -[loggers] -keys = root - -[handlers] -keys = console - -[formatters] -keys = generic - -[logger_root] -level = INFO -handlers = console -qualname = - -[handler_console] -class = StreamHandler -args = (sys.stderr,) -level = INFO -formatter = generic - -[formatter_generic] -format = %%(levelname)-5.5s [%%(name)s] %%(message)s diff --git a/plugins/equipment/migrations/env.py b/plugins/equipment/migrations/env.py deleted file mode 100644 index 42ec87e..0000000 --- a/plugins/equipment/migrations/env.py +++ /dev/null @@ -1,12 +0,0 @@ -"""Alembic env.py for the equipment plugin. - -Thin shim that sets PLUGIN_NAME then delegates to the shared template at -shopdb.plugins.alembic_template, which filters MetaData to only this -plugin's tables and runs Alembic against the Flask app's engine. -""" -import os -os.environ['PLUGIN_NAME'] = 'equipment' - -from shopdb.plugins.alembic_template import run_migrations - -run_migrations() diff --git a/plugins/equipment/migrations/script.py.mako b/plugins/equipment/migrations/script.py.mako deleted file mode 100644 index f230367..0000000 --- a/plugins/equipment/migrations/script.py.mako +++ /dev/null @@ -1,23 +0,0 @@ -"""${message} - -Revision ID: ${up_revision} -Revises: ${down_revision | comma,n} -Create Date: ${create_date} - -""" -from alembic import op -import sqlalchemy as sa -${imports if imports else ""} - -revision = ${repr(up_revision)} -down_revision = ${repr(down_revision)} -branch_labels = ${repr(branch_labels)} -depends_on = ${repr(depends_on)} - - -def upgrade(): - ${upgrades if upgrades else "pass"} - - -def downgrade(): - ${downgrades if downgrades else "pass"} diff --git a/plugins/equipment/migrations/versions/0001_baseline.py b/plugins/equipment/migrations/versions/0001_baseline.py deleted file mode 100644 index 44e7837..0000000 --- a/plugins/equipment/migrations/versions/0001_baseline.py +++ /dev/null @@ -1,27 +0,0 @@ -"""equipment plugin: baseline schema - -Creates every table owned by the equipment plugin per -shopdb.plugins.alembic_template.PLUGIN_TABLE_OWNERS. The table definitions -are derived from the SQLAlchemy models at migration runtime so this stays -in lockstep with the model layer without duplication. - -Revision ID: 0001_baseline_equipment -Revises: -Create Date: 2026-05-30 - -""" -from shopdb.plugins.alembic_template import create_plugin_tables, drop_plugin_tables - - -revision = '0001_baseline_equipment' -down_revision = None -branch_labels = None -depends_on = None - - -def upgrade(): - create_plugin_tables('equipment') - - -def downgrade(): - drop_plugin_tables('equipment') diff --git a/plugins/network/migrations/alembic.ini b/plugins/network/migrations/alembic.ini deleted file mode 100644 index 0775ad4..0000000 --- a/plugins/network/migrations/alembic.ini +++ /dev/null @@ -1,30 +0,0 @@ -[alembic] -script_location = . -prepend_sys_path = . -file_template = %%(rev)s_%%(slug)s - -[logging] -keys = root - -[loggers] -keys = root - -[handlers] -keys = console - -[formatters] -keys = generic - -[logger_root] -level = INFO -handlers = console -qualname = - -[handler_console] -class = StreamHandler -args = (sys.stderr,) -level = INFO -formatter = generic - -[formatter_generic] -format = %%(levelname)-5.5s [%%(name)s] %%(message)s diff --git a/plugins/network/migrations/env.py b/plugins/network/migrations/env.py deleted file mode 100644 index 3967a1a..0000000 --- a/plugins/network/migrations/env.py +++ /dev/null @@ -1,12 +0,0 @@ -"""Alembic env.py for the network plugin. - -Thin shim that sets PLUGIN_NAME then delegates to the shared template at -shopdb.plugins.alembic_template, which filters MetaData to only this -plugin's tables and runs Alembic against the Flask app's engine. -""" -import os -os.environ['PLUGIN_NAME'] = 'network' - -from shopdb.plugins.alembic_template import run_migrations - -run_migrations() diff --git a/plugins/network/migrations/script.py.mako b/plugins/network/migrations/script.py.mako deleted file mode 100644 index f230367..0000000 --- a/plugins/network/migrations/script.py.mako +++ /dev/null @@ -1,23 +0,0 @@ -"""${message} - -Revision ID: ${up_revision} -Revises: ${down_revision | comma,n} -Create Date: ${create_date} - -""" -from alembic import op -import sqlalchemy as sa -${imports if imports else ""} - -revision = ${repr(up_revision)} -down_revision = ${repr(down_revision)} -branch_labels = ${repr(branch_labels)} -depends_on = ${repr(depends_on)} - - -def upgrade(): - ${upgrades if upgrades else "pass"} - - -def downgrade(): - ${downgrades if downgrades else "pass"} diff --git a/plugins/network/migrations/versions/0001_baseline.py b/plugins/network/migrations/versions/0001_baseline.py deleted file mode 100644 index 2be8b72..0000000 --- a/plugins/network/migrations/versions/0001_baseline.py +++ /dev/null @@ -1,27 +0,0 @@ -"""network plugin: baseline schema - -Creates every table owned by the network plugin per -shopdb.plugins.alembic_template.PLUGIN_TABLE_OWNERS. The table definitions -are derived from the SQLAlchemy models at migration runtime so this stays -in lockstep with the model layer without duplication. - -Revision ID: 0001_baseline_network -Revises: -Create Date: 2026-05-30 - -""" -from shopdb.plugins.alembic_template import create_plugin_tables, drop_plugin_tables - - -revision = '0001_baseline_network' -down_revision = None -branch_labels = None -depends_on = None - - -def upgrade(): - create_plugin_tables('network') - - -def downgrade(): - drop_plugin_tables('network') diff --git a/plugins/notifications/migrations/alembic.ini b/plugins/notifications/migrations/alembic.ini deleted file mode 100644 index 0775ad4..0000000 --- a/plugins/notifications/migrations/alembic.ini +++ /dev/null @@ -1,30 +0,0 @@ -[alembic] -script_location = . -prepend_sys_path = . -file_template = %%(rev)s_%%(slug)s - -[logging] -keys = root - -[loggers] -keys = root - -[handlers] -keys = console - -[formatters] -keys = generic - -[logger_root] -level = INFO -handlers = console -qualname = - -[handler_console] -class = StreamHandler -args = (sys.stderr,) -level = INFO -formatter = generic - -[formatter_generic] -format = %%(levelname)-5.5s [%%(name)s] %%(message)s diff --git a/plugins/notifications/migrations/env.py b/plugins/notifications/migrations/env.py deleted file mode 100644 index d02c111..0000000 --- a/plugins/notifications/migrations/env.py +++ /dev/null @@ -1,12 +0,0 @@ -"""Alembic env.py for the notifications plugin. - -Thin shim that sets PLUGIN_NAME then delegates to the shared template at -shopdb.plugins.alembic_template, which filters MetaData to only this -plugin's tables and runs Alembic against the Flask app's engine. -""" -import os -os.environ['PLUGIN_NAME'] = 'notifications' - -from shopdb.plugins.alembic_template import run_migrations - -run_migrations() diff --git a/plugins/notifications/migrations/script.py.mako b/plugins/notifications/migrations/script.py.mako deleted file mode 100644 index f230367..0000000 --- a/plugins/notifications/migrations/script.py.mako +++ /dev/null @@ -1,23 +0,0 @@ -"""${message} - -Revision ID: ${up_revision} -Revises: ${down_revision | comma,n} -Create Date: ${create_date} - -""" -from alembic import op -import sqlalchemy as sa -${imports if imports else ""} - -revision = ${repr(up_revision)} -down_revision = ${repr(down_revision)} -branch_labels = ${repr(branch_labels)} -depends_on = ${repr(depends_on)} - - -def upgrade(): - ${upgrades if upgrades else "pass"} - - -def downgrade(): - ${downgrades if downgrades else "pass"} diff --git a/plugins/notifications/migrations/versions/0001_baseline.py b/plugins/notifications/migrations/versions/0001_baseline.py deleted file mode 100644 index 6d44b6f..0000000 --- a/plugins/notifications/migrations/versions/0001_baseline.py +++ /dev/null @@ -1,27 +0,0 @@ -"""notifications plugin: baseline schema - -Creates every table owned by the notifications plugin per -shopdb.plugins.alembic_template.PLUGIN_TABLE_OWNERS. The table definitions -are derived from the SQLAlchemy models at migration runtime so this stays -in lockstep with the model layer without duplication. - -Revision ID: 0001_baseline_notifications -Revises: -Create Date: 2026-05-30 - -""" -from shopdb.plugins.alembic_template import create_plugin_tables, drop_plugin_tables - - -revision = '0001_baseline_notifications' -down_revision = None -branch_labels = None -depends_on = None - - -def upgrade(): - create_plugin_tables('notifications') - - -def downgrade(): - drop_plugin_tables('notifications') diff --git a/plugins/printers/migrations/__init__.py b/plugins/printers/migrations/__init__.py deleted file mode 100644 index bfb65cf..0000000 --- a/plugins/printers/migrations/__init__.py +++ /dev/null @@ -1 +0,0 @@ -"""Printers plugin migrations.""" diff --git a/plugins/printers/migrations/alembic.ini b/plugins/printers/migrations/alembic.ini deleted file mode 100644 index 0775ad4..0000000 --- a/plugins/printers/migrations/alembic.ini +++ /dev/null @@ -1,30 +0,0 @@ -[alembic] -script_location = . -prepend_sys_path = . -file_template = %%(rev)s_%%(slug)s - -[logging] -keys = root - -[loggers] -keys = root - -[handlers] -keys = console - -[formatters] -keys = generic - -[logger_root] -level = INFO -handlers = console -qualname = - -[handler_console] -class = StreamHandler -args = (sys.stderr,) -level = INFO -formatter = generic - -[formatter_generic] -format = %%(levelname)-5.5s [%%(name)s] %%(message)s diff --git a/plugins/printers/migrations/env.py b/plugins/printers/migrations/env.py deleted file mode 100644 index 0cec79d..0000000 --- a/plugins/printers/migrations/env.py +++ /dev/null @@ -1,12 +0,0 @@ -"""Alembic env.py for the printers plugin. - -Thin shim that sets PLUGIN_NAME then delegates to the shared template at -shopdb.plugins.alembic_template, which filters MetaData to only this -plugin's tables and runs Alembic against the Flask app's engine. -""" -import os -os.environ['PLUGIN_NAME'] = 'printers' - -from shopdb.plugins.alembic_template import run_migrations - -run_migrations() diff --git a/plugins/printers/migrations/script.py.mako b/plugins/printers/migrations/script.py.mako deleted file mode 100644 index f230367..0000000 --- a/plugins/printers/migrations/script.py.mako +++ /dev/null @@ -1,23 +0,0 @@ -"""${message} - -Revision ID: ${up_revision} -Revises: ${down_revision | comma,n} -Create Date: ${create_date} - -""" -from alembic import op -import sqlalchemy as sa -${imports if imports else ""} - -revision = ${repr(up_revision)} -down_revision = ${repr(down_revision)} -branch_labels = ${repr(branch_labels)} -depends_on = ${repr(depends_on)} - - -def upgrade(): - ${upgrades if upgrades else "pass"} - - -def downgrade(): - ${downgrades if downgrades else "pass"} diff --git a/plugins/printers/migrations/versions/0001_baseline.py b/plugins/printers/migrations/versions/0001_baseline.py deleted file mode 100644 index 8247960..0000000 --- a/plugins/printers/migrations/versions/0001_baseline.py +++ /dev/null @@ -1,27 +0,0 @@ -"""printers plugin: baseline schema - -Creates every table owned by the printers plugin per -shopdb.plugins.alembic_template.PLUGIN_TABLE_OWNERS. The table definitions -are derived from the SQLAlchemy models at migration runtime so this stays -in lockstep with the model layer without duplication. - -Revision ID: 0001_baseline_printers -Revises: -Create Date: 2026-05-30 - -""" -from shopdb.plugins.alembic_template import create_plugin_tables, drop_plugin_tables - - -revision = '0001_baseline_printers' -down_revision = None -branch_labels = None -depends_on = None - - -def upgrade(): - create_plugin_tables('printers') - - -def downgrade(): - drop_plugin_tables('printers') diff --git a/plugins/printers/migrations/versions/0002_modelsupplies.py b/plugins/printers/migrations/versions/0002_modelsupplies.py deleted file mode 100644 index 9c1feb6..0000000 --- a/plugins/printers/migrations/versions/0002_modelsupplies.py +++ /dev/null @@ -1,44 +0,0 @@ -"""printers plugin: add modelsupplies table - -Data-driven model -> toner/drum/waste part-number mapping. Replaces the old -hardcoded supply_parts table. - -Revision ID: 0002_modelsupplies_printers -Revises: 0001_baseline_printers -Create Date: 2026-06-25 - -""" -import sqlalchemy as sa -from alembic import op - - -revision = '0002_modelsupplies_printers' -down_revision = '0001_baseline_printers' -branch_labels = None -depends_on = None - - -def upgrade(): - op.create_table( - 'modelsupplies', - sa.Column('modelsupplyid', sa.Integer, primary_key=True), - sa.Column('modelnumberid', sa.Integer, - sa.ForeignKey('models.modelnumberid'), nullable=False), - sa.Column('supplytype', sa.String(20), nullable=False, server_default='toner'), - sa.Column('color', sa.String(20), nullable=False, server_default='none'), - sa.Column('capacitytier', sa.String(20), nullable=False, server_default='standard'), - sa.Column('partnumber', sa.String(50), nullable=False), - sa.Column('marketingname', sa.String(120)), - sa.Column('pageyield', sa.Integer), - sa.Column('notes', sa.Text), - sa.Column('createddate', sa.DateTime, nullable=False), - sa.Column('modifieddate', sa.DateTime, nullable=False), - sa.Column('isactive', sa.Boolean, nullable=False, server_default=sa.true()), - sa.UniqueConstraint('modelnumberid', 'partnumber', name='uq_modelsupply_part'), - ) - op.create_index('idx_modelsupplies_modelnumberid', 'modelsupplies', ['modelnumberid']) - - -def downgrade(): - op.drop_index('idx_modelsupplies_modelnumberid', table_name='modelsupplies') - op.drop_table('modelsupplies') diff --git a/plugins/usb/migrations/alembic.ini b/plugins/usb/migrations/alembic.ini deleted file mode 100644 index 0775ad4..0000000 --- a/plugins/usb/migrations/alembic.ini +++ /dev/null @@ -1,30 +0,0 @@ -[alembic] -script_location = . -prepend_sys_path = . -file_template = %%(rev)s_%%(slug)s - -[logging] -keys = root - -[loggers] -keys = root - -[handlers] -keys = console - -[formatters] -keys = generic - -[logger_root] -level = INFO -handlers = console -qualname = - -[handler_console] -class = StreamHandler -args = (sys.stderr,) -level = INFO -formatter = generic - -[formatter_generic] -format = %%(levelname)-5.5s [%%(name)s] %%(message)s diff --git a/plugins/usb/migrations/env.py b/plugins/usb/migrations/env.py deleted file mode 100644 index 7599521..0000000 --- a/plugins/usb/migrations/env.py +++ /dev/null @@ -1,12 +0,0 @@ -"""Alembic env.py for the usb plugin. - -Thin shim that sets PLUGIN_NAME then delegates to the shared template at -shopdb.plugins.alembic_template, which filters MetaData to only this -plugin's tables and runs Alembic against the Flask app's engine. -""" -import os -os.environ['PLUGIN_NAME'] = 'usb' - -from shopdb.plugins.alembic_template import run_migrations - -run_migrations() diff --git a/plugins/usb/migrations/script.py.mako b/plugins/usb/migrations/script.py.mako deleted file mode 100644 index f230367..0000000 --- a/plugins/usb/migrations/script.py.mako +++ /dev/null @@ -1,23 +0,0 @@ -"""${message} - -Revision ID: ${up_revision} -Revises: ${down_revision | comma,n} -Create Date: ${create_date} - -""" -from alembic import op -import sqlalchemy as sa -${imports if imports else ""} - -revision = ${repr(up_revision)} -down_revision = ${repr(down_revision)} -branch_labels = ${repr(branch_labels)} -depends_on = ${repr(depends_on)} - - -def upgrade(): - ${upgrades if upgrades else "pass"} - - -def downgrade(): - ${downgrades if downgrades else "pass"} diff --git a/plugins/usb/migrations/versions/0001_baseline.py b/plugins/usb/migrations/versions/0001_baseline.py deleted file mode 100644 index 6200b1f..0000000 --- a/plugins/usb/migrations/versions/0001_baseline.py +++ /dev/null @@ -1,27 +0,0 @@ -"""usb plugin: baseline schema - -Creates every table owned by the usb plugin per -shopdb.plugins.alembic_template.PLUGIN_TABLE_OWNERS. The table definitions -are derived from the SQLAlchemy models at migration runtime so this stays -in lockstep with the model layer without duplication. - -Revision ID: 0001_baseline_usb -Revises: -Create Date: 2026-05-30 - -""" -from shopdb.plugins.alembic_template import create_plugin_tables, drop_plugin_tables - - -revision = '0001_baseline_usb' -down_revision = None -branch_labels = None -depends_on = None - - -def upgrade(): - create_plugin_tables('usb') - - -def downgrade(): - drop_plugin_tables('usb') diff --git a/tests/test_plugin_migrations.py b/tests/test_plugin_migrations.py index 418dd26..b48e3be 100644 --- a/tests/test_plugin_migrations.py +++ b/tests/test_plugin_migrations.py @@ -1,11 +1,10 @@ -"""Per-plugin Alembic chain wiring tests. +"""Plugin table-ownership tests. -Pins the bundled-plugin migration setup so a future refactor that breaks -the scaffolding fails fast with a clear test rather than a confusing -runtime error on a fresh deploy. +Bundled plugin schema is owned by the core migration chain (deploys run +`flask db upgrade` only, which reproduces the full schema). The per-plugin +Alembic helpers remain for external/filesystem plugins; these tests pin the +PLUGIN_TABLE_OWNERS registry those helpers consume. """ -from pathlib import Path - import pytest from shopdb.plugins.alembic_template import ( @@ -20,29 +19,16 @@ BUNDLED_PLUGINS = ('computers', 'equipment', 'network', 'notifications', 'printe @pytest.mark.parametrize('plugin', BUNDLED_PLUGINS) def test_bundled_plugin_has_table_owner_entry(plugin): """Every bundled plugin appears in PLUGIN_TABLE_OWNERS with at least - one table; otherwise its baseline migration would be a no-op.""" + one table, documenting which tables it contributes to the schema.""" assert plugin in PLUGIN_TABLE_OWNERS assert len(PLUGIN_TABLE_OWNERS[plugin]) > 0 -@pytest.mark.parametrize('plugin', BUNDLED_PLUGINS) -def test_bundled_plugin_has_migrations_dir(plugin): - """Each bundled plugin has the on-disk Alembic scaffolding.""" - root = Path(__file__).resolve().parent.parent / 'plugins' / plugin / 'migrations' - assert (root / 'env.py').is_file(), f"{plugin}/migrations/env.py missing" - assert (root / 'alembic.ini').is_file(), f"{plugin}/migrations/alembic.ini missing" - assert (root / 'script.py.mako').is_file(), f"{plugin}/migrations/script.py.mako missing" - versions = root / 'versions' - assert versions.is_dir(), f"{plugin}/migrations/versions missing" - baseline = versions / '0001_baseline.py' - assert baseline.is_file(), f"{plugin}/migrations/versions/0001_baseline.py missing" - - @pytest.mark.parametrize('plugin', BUNDLED_PLUGINS) def test_plugin_metadata_has_all_owned_tables(plugin, app): """The MetaData filtered to a plugin's owned tables actually contains every table named in PLUGIN_TABLE_OWNERS. Catches drift between the - template's table list and what the models declare.""" + registry and what the models declare.""" with app.app_context(): md = _get_plugin_metadata(plugin) owned = set(PLUGIN_TABLE_OWNERS[plugin])