Document migration-on-deploy contract for plugin schema changes
A plugin model change that references a column its migration has not applied yet 500s every query on that table. Make the deploy order explicit: run flask db upgrade then flask plugin upgrade-all before serving traffic, and require model+migration to ship together.
This commit is contained in:
5
.github/copilot-instructions.md
vendored
5
.github/copilot-instructions.md
vendored
@@ -67,6 +67,11 @@ name. Spell out: `config context manager request response environment utilities`
|
||||
`migrations/versions/`; each plugin owns its own chain under
|
||||
`plugins/<name>/migrations/`. New schema = a new migration with an idempotent
|
||||
guard and a real downgrade. Migrations must run clean on strict MySQL 8.
|
||||
Any model column/table change ships WITH its migration in the SAME change, and
|
||||
bringing up a new image MUST run `flask db upgrade` then
|
||||
`flask plugin upgrade-all` before serving traffic. A model that references a
|
||||
column its migration has not applied yet 500s every query on that table
|
||||
(`1054 Unknown column`), so code and schema must never be deployed out of step.
|
||||
- **Asset model is the platform contract.** Physical things are an `Asset` plus a
|
||||
plugin subtype row linked by `assetid` (FK, `ON DELETE CASCADE`). Consumables
|
||||
with quantities are standalone tables, not assets.
|
||||
|
||||
@@ -24,6 +24,24 @@
|
||||
- **Index names**: `idx_<table>_<column>`. Underscores allowed here only because indexes are infrastructure, not data.
|
||||
- Good: `idx_machines_locationid`
|
||||
|
||||
### Migrations and deploy ordering
|
||||
|
||||
- **A model change ships WITH its migration in the same change.** Adding or
|
||||
changing a column/table on a SQLAlchemy model without the matching Alembic
|
||||
migration is a broken change, even if it passes tests against a freshly built
|
||||
schema.
|
||||
- **Code and schema must never deploy out of step.** A model that references a
|
||||
column its migration has not applied yet makes MySQL raise
|
||||
`1054 Unknown column`, which 500s every query on that table (this is not a
|
||||
degraded read - the whole endpoint fails).
|
||||
- **Bringing up a new image MUST run migrations before serving traffic**, in
|
||||
order: `flask db upgrade` (core chain) then `flask plugin upgrade-all`
|
||||
(per-plugin chains). A rebuilt image with new model code but an
|
||||
un-migrated database will 500 until this runs.
|
||||
- Core schema lives in `migrations/versions/`; each plugin owns its own chain
|
||||
under `plugins/<name>/migrations/`. New schema = a new migration with an
|
||||
idempotent guard and a real downgrade, clean on strict MySQL 8.
|
||||
|
||||
### Allowed acronyms (closed list, expand by PR)
|
||||
|
||||
- **Universal**: `id`, `url`, `api`, `http`, `https`, `json`, `jwt`, `sql`, `os`, `ip`, `dns`, `csv`, `pdf`, `cors`, `ttl`, `uuid`, `html`, `css`, `orm`
|
||||
|
||||
Reference in New Issue
Block a user