Skip to content

M15: cross-provider migrations, closing Phase 5 (0.5.0)#15

Merged
lgamorim merged 8 commits into
masterfrom
feature/M15-cross-provider-migrations
Jul 12, 2026
Merged

M15: cross-provider migrations, closing Phase 5 (0.5.0)#15
lgamorim merged 8 commits into
masterfrom
feature/M15-cross-provider-migrations

Conversation

@lgamorim

Copy link
Copy Markdown
Owner

Closes Phase 5 — Migrations & CLI. Spreads the migration engine and database lifecycle from SQL Server across SQLite, PostgreSQL, and MySQL, reconciles the transactional-DDL differences, and cuts a clean 0.5.0.

What's here

  • Provider abstraction — extract IDatabaseAdmin (M13 deferred this until a second implementation existed); make transactional DDL a ledger capability (IMigrationLedger.SupportsTransactionalDdl), so MigrationRunner wraps each migration in a transaction only when the provider supports it. A ProviderServices resolver replaces the CLI's != SqlServer gates and centralises connection/ledger/admin selection (shared with PrepareRunner).
  • SQLiteSqliteMigrationLedger (ISO-8601 applied_on_utc text) + SqliteDatabaseAdmin (the Data Source file is the database: create materializes it, drop deletes it).
  • PostgreSQLNpgsqlMigrationLedger (timestamptz, UTC-kind) + NpgsqlDatabaseAdmin (maintenance postgres db, idempotent create via pg_database, DROP DATABASE ... WITH (FORCE)).
  • MySQLMySqlMigrationLedger reporting SupportsTransactionalDdl = false + MySqlDatabaseAdmin (CREATE/DROP DATABASE IF (NOT) EXISTS). Migrations apply without a transaction; recorded in ADR 0007.
  • Docsdocs/migrations.md per-provider matrix; a full README rewrite for the v0.5.0 feature set (command set, provider support matrix, packages, ADR index 0001–0007, roadmap).
  • Phase closePackageVersion dropped to a clean 0.5.0 (the commit v0.5.0 will tag).

Design notes

  • Transactionality lives on the ledger — the per-provider object the runner already holds — so the engine asks whether to use a transaction rather than sniffing the provider, and MySQL's non-atomicity is surfaced honestly rather than faked (ADR 0007). SQL Server / Postgres / SQLite keep full per-migration atomicity.
  • IDatabaseAdmin extracted exactly when the second implementation arrived, matching how IQueryDescriber was handled in M10.

Verification

  • Release build 0 warnings, dotnet format clean.
  • 508 tests pass, 0 skipped (SQL Server + PostgreSQL + MySQL containers + embedded SQLite all ran).
  • All 9 packages pack at clean 0.5.0.

Two provider wrinkles the integration tests caught: Npgsql can't read regclass via ExecuteScalar (test-side fix), and the default MySQL container user lacks CREATE DATABASE, so the admin tests use root — reflecting that database creation is a privileged operation.

After merge: tag v0.5.0 on the squash commit and close the Phase 5 milestone.

🤖 Generated with Claude Code

lgamorim and others added 8 commits July 12, 2026 16:50
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Prepare the migrate and database commands to dispatch across providers
without changing behaviour (SQL Server stays the only one wired):

- Add IDatabaseAdmin in SqlBound.Migrations; SqlServerDatabaseAdmin
  implements it.
- Make transactional DDL a ledger capability (IMigrationLedger.
  SupportsTransactionalDdl); MigrationRunner wraps each migration in a
  transaction only when the provider supports it, so a non-transactional
  provider (MySQL, coming next) applies migrations without one.
- Add ProviderServices, a resolver for the connection, ledger, and
  database administrator per DatabaseTarget; route MigrationCli,
  DatabaseCommand, and PrepareRunner's connection creation through it.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
SqliteMigrationLedger stores the history in _sqlbound_migrations (with
applied_on_utc as ISO-8601 text, since SQLite has no date type) and
reports transactional DDL. SqliteDatabaseAdmin treats the Data Source
file as the database: create materializes the file, drop deletes it.
Both wired into the CLI provider resolver, so migrate run/revert/status
and database create/drop now work against SQLite.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
NpgsqlMigrationLedger stores the history in _sqlbound_migrations
(applied_on_utc as timestamptz, paired with the UTC-kind DateTime the
runner produces) and reports transactional DDL. NpgsqlDatabaseAdmin
creates and drops the target database from the maintenance 'postgres'
database, checking pg_database for idempotent create and using DROP
DATABASE ... WITH (FORCE) to evict connections. Both wired into the
provider resolver, so migrate and database now work against PostgreSQL.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
MySqlMigrationLedger stores the history in _sqlbound_migrations and,
because MySQL commits DDL implicitly, reports SupportsTransactionalDdl =
false — so MigrationRunner applies each migration without a transaction.
MySqlDatabaseAdmin creates and drops the target database with CREATE/DROP
DATABASE IF (NOT) EXISTS from a no-default-database connection. ADR 0007
records the non-transactional decision. Both wired into the resolver;
MySQL now completes the four-provider migrate and database support.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Update docs/migrations.md now that migrate and database support all four
providers: replace the SQL-Server-only notes with a per-provider matrix
covering transactional DDL and the create/drop mechanics, and link
ADR 0007 for MySQL's non-transactional migrations.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Drop the prerelease suffix now that migrations and the database
lifecycle work across all four providers. This is the commit the v0.5.0
tag will mark; PackageVersion reads a clean 0.5.0.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Bring the README up to date with all work through Phase 5: v0.5.0 status,
the full migration and database command set, a provider support matrix
(verification fidelity and migration transactionality per provider), the
complete package list including SqlBound.Introspection and .Migrations,
the ADR index through 0007, and the roadmap with Phases 1-5 done and only
Phase 6 (Ship) remaining.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@lgamorim lgamorim merged commit 8babb4d into master Jul 12, 2026
4 checks passed
@lgamorim lgamorim deleted the feature/M15-cross-provider-migrations branch July 12, 2026 17:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant