$npx -y skills add maksimzayats/specx --skill specx-sqlalchemy-migrationsAdd or repair Alembic migrations for specx SQLAlchemy services. Use when adding SQLAlchemy models or repositories, replacing metadata.create_all schema bootstraps, creating async Alembic env.py, adding migration Makefile targets, generating initial revisions, or testing migration
| 1 | # specx SQLAlchemy Migrations |
| 2 | |
| 3 | Use this skill whenever a specx project has SQLAlchemy models or persistence |
| 4 | adapters. Read `references/alembic.md` before editing migration files. |
| 5 | |
| 6 | ## Workflow |
| 7 | |
| 8 | 1. Add `alembic>=1.18.5` as a runtime dependency when SQLAlchemy adapters |
| 9 | exist, together with SQLAlchemy's asyncio extra and the selected driver. |
| 10 | 2. Add `alembic.ini`, `migrations/env.py`, `migrations/script.py.mako`, and |
| 11 | `migrations/versions/`. |
| 12 | 3. Use Alembic's async pattern for async SQLAlchemy engines. |
| 13 | 4. Put app-wide SQLAlchemy settings/session factory under top-level |
| 14 | `infrastructure/sqlalchemy/`. |
| 15 | 5. Keep scope-owned ORM models and repositories under |
| 16 | `core/<scope>/infrastructure/sqlalchemy/`. |
| 17 | 6. Add a project-local SQLAlchemy declarative base under |
| 18 | `src/<package>/foundation/sqlalchemy_model.py`; do not use shared packaged |
| 19 | metadata for generated services. |
| 20 | 7. Put reusable model discovery under top-level |
| 21 | `infrastructure/sqlalchemy/model_discovery.py`. Use that same function from |
| 22 | `migrations/env.py` and its guardrail test before assigning |
| 23 | `target_metadata`; do not duplicate discovery or maintain hard-coded model |
| 24 | module names. |
| 25 | 8. Set `target_metadata` to the project-local `BaseSQLAlchemyModel.metadata`. |
| 26 | 9. Generate or hand-review an initial migration for current models. |
| 27 | 10. Add `make migrate` and `make makemigrations`. |
| 28 | 11. Add tests that run `alembic upgrade head` against an isolated database, |
| 29 | check for pending autogenerate changes, and prove every core SQLAlchemy |
| 30 | model file is included by the exact discovery function Alembic uses. Use |
| 31 | the production database family when dialect behavior matters. |
| 32 | |
| 33 | ## Guardrails |
| 34 | |
| 35 | - Do not call `Base.metadata.create_all`, `metadata.create_all`, or |
| 36 | `drop_all` from `src/`. |
| 37 | - Do not run migrations from FastAPI startup by default. Run migrations as an |
| 38 | operational command before app startup. |
| 39 | - Do not put app-wide engine/session factory code inside one core scope. |
| 40 | - Do not let delivery controllers import ORM models, repositories, sessions, or |
| 41 | migration helpers. |
| 42 | - Do not let Alembic drift checks depend on incomplete metadata. Model discovery |
| 43 | must include every `core/*/infrastructure/sqlalchemy/models/*.py` file. |
| 44 | - Do not trust autogenerated migrations without review. |
| 45 | - Do not edit, delete, or reorder a revision that may already have been applied; |
| 46 | add a new corrective revision. |
| 47 | - Do not pass SQLite's `autocommit` connect argument on Python 3.11. For a |
| 48 | savepoint-based SQLite test harness spanning Python versions, use |
| 49 | SQLAlchemy's `connect` and `begin` event-hook recipe. |
| 50 | |
| 51 | ## Code Style |
| 52 | |
| 53 | Use blank lines as logical separators in all code. Keep related statements |
| 54 | together, but separate independent setup, action, assertion, response, branch, |
| 55 | and transformation groups so long blocks stay readable. |
| 56 | |
| 57 | ## References |
| 58 | |
| 59 | - `references/alembic.md` - async Alembic layout, env.py, Makefile targets, |
| 60 | initial migration, and migration tests. |