Skip to content

v0.9.4 — migrate preflight --against

Choose a tag to compare

@evoludigit evoludigit released this 29 Apr 19:51
· 161 commits to main since this release

What's new

confiture migrate preflight --against <url> (issue #116)

Test pending migrations against a disposable database (typically seeded from pg_dump --schema-only) and report all failures in one pass — not just the first one.

The problem it solves: migrations written against a locally-built schema can fail on a production database that has accumulated incremental changes. The previous feedback cycle was: push → restore full backup (~30–40 min) → discover one failure → fix → repeat.

The new workflow:
```bash

1. Pull production schema (~1 MB, ~2 s)

pg_dump --schema-only -f /tmp/prod.sql postgresql://prod-host/mydb

2. Seed a local preflight database

createdb myapp_preflight
psql -d myapp_preflight < /tmp/prod.sql

3. Test all pending migrations — get all failures at once

confiture migrate preflight
--against postgresql://localhost/myapp_preflight
--env production

4. Fix, repeat step 3 until all pass — then ship

```

New options

Option Description
--against <url> PostgreSQL URL of the preflight database
--env <name> / --config <path> Detect pending migrations from a live tracking table
--since <version> Test migrations at or after a version (inclusive, no second DB connection)
--allow-non-transactional Run CREATE INDEX CONCURRENTLY etc. in autocommit mode
--format json Output {"static": …, "against": …} envelope

How it works

  • Per-migration SAVEPOINTs allow execution to continue past individual failures
  • An outer SAVEPOINT is always rolled back — the preflight DB is left unchanged
  • Non-transactional migrations are skipped by default (neutral, exit 0); opt-in with --allow-non-transactional
  • Exit 0 = all pass, exit 1 = failures detected, exit 2 = connection/config error

New public API

```python
from confiture import PreflightAgainstResult, PreflightAgainstMigration
from confiture.core._migrator.session import MigratorSession

session = MigratorSession(
config=None,
migrations_dir=Path("db/migrations"),
database_url_override="postgresql://localhost/myapp_preflight",
)
with session:
result = session.run_against(pending_files, against_url="postgresql://localhost/myapp_preflight")

print(result.all_passed, result.failures)
```

Full changelog

See CHANGELOG.md for details.

Full Changelog: v0.9.3...v0.9.4