Move schema evolution to Alembic with auto-upgrade on API start.

Extract shared brownfield patches, add the legacy revision, and default to upgrade-head plus skip of duplicate inline DDL (with legacy fallback if Alembic fails).

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
oliver 2026-08-02 16:41:56 +08:00
parent 6e8003be5c
commit 57b3faf9fb
8 changed files with 503 additions and 343 deletions

View file

@ -1,22 +1,45 @@
# Alembic (schema migrations)
netx historically evolved the schema with startup `ALTER TABLE … IF NOT EXISTS`.
Alembic is the preferred path going forward.
Schema evolution uses Alembic. On API startup, netx **automatically** runs
`alembic upgrade head` (same patches as [`netx_api/schema_patches.py`](../netx_api/schema_patches.py)).
You normally do **not** need extra env flags.
## Commands
## What happens on boot
1. `create_all` — create any missing tables from ORM metadata
2. `alembic upgrade head` — apply revisions (idempotent brownfield patches)
3. Auth column safety-net ensures (before admin bootstrap)
4. Legacy inline ALTER block is **skipped** by default (already covered by Alembic)
## Commands (optional / CI)
```powershell
cd netx
.\.venv\Scripts\alembic.exe upgrade head
.\.venv\Scripts\alembic.exe current
.\.venv\Scripts\alembic.exe history
```
## Env
### Brownfield DB that already received old startup DDL
| Variable | Meaning |
First boot after this change will run `upgrade head`. Patches are idempotent.
If Alembic history was never stamped and you prefer to mark current without re-running:
```powershell
.\.venv\Scripts\alembic.exe stamp head
```
## Env overrides (usually leave defaults)
| Variable | Default | Meaning |
|----------|---------|---------|
| `NETX_ALEMBIC_UPGRADE_ON_START` | `true` | Run `alembic upgrade head` on API start. Set `false` only if a separate migrate job owns upgrades. |
| `NETX_SKIP_LEGACY_STARTUP_DDL` | `true` | Skip the duplicate inline ALTER path. Set `false` only as emergency fallback. |
| `NETX_DATABASE_URL` | — | Same URL Alembic reads via `netx_api.config.settings`. |
## Revisions
| Revision | Purpose |
|----------|---------|
| `NETX_SKIP_LEGACY_STARTUP_DDL=true` | Skip the large ad-hoc ALTER block in API startup (keep auth `scopes` column ensures). Use after `alembic upgrade head`. |
| `NETX_DATABASE_URL` | Same URL Alembic reads via `netx_api.config.settings`. |
Fresh lab installs can keep the legacy startup DDL (`false`, default) until you adopt Alembic in your deploy checklist.
Revision for capability scopes: `alembic/versions/20260802_scopes.py`.
| `20260802_scopes` | `app_user.scopes` / `api_token.scopes` |
| `20260802_legacy` | Shared brownfield patches (alarms, inventory, managed_ne, topology, port traffic, key-alert, …) |