Expanded Migrations (Flyway, Liquibase XML/YAML, Laravel) & Adds Native DBDiff Migration CLI & Supabase Support#142
Merged
jasdeepkhalsa merged 12 commits intomasterfrom Mar 3, 2026
Conversation
Migration Output Formats
- Add FormatInterface + FormatRegistry (src/Migration/Format/)
- NativeFormat — default UP/DOWN SQL file (replaces legacy Templater output)
- FlywayFormat — V{ts}__{desc}.sql + optional U{ts}__{desc}.sql
- LiquibaseXmlFormat — changelog.xml with <changeSet>/<rollback> blocks
- LiquibaseYamlFormat — changelog.yaml equivalent via symfony/yaml
- LaravelFormat — anonymous Migration class with DB::unprepared() up/down
Native Migration Runner
- MigrationFile (src/Migration/Runner/) — YYYYMMDDHHMMSS_name.up.sql / .down.sql pairs
* timestamp-ordered, self-describing names (no cryptic V/U prefix)
* scaffold(), scanDir(), getChecksum() helpers
- MigrationHistory — _dbdiff_migrations tracking table (MySQL/Postgres/SQLite DDL)
* recordSuccess, recordFailure, repairFailed, recordBaseline
- MigrationRunner — up(), down(), status(), validate(), repair(), baseline()
* transaction-per-migration safety model (Flyway-style halt on failure)
* SHA-256 checksum verification
CLI — migrated from aura/cli to symfony/console
- Add symfony/console to composer.json
- DiffCommand — full replacement for legacy aura/cli diff flow; --format flag
- MigrationNewCommand (migration:new)
- MigrationUpCommand (migration:up [--target])
- MigrationDownCommand (migration:down [--last --target])
- MigrationStatusCommand (migration:status)
- MigrationValidateCommand (migration:validate)
- MigrationRepairCommand (migration:repair)
- MigrationBaselineCommand (migration:baseline)
- Refactor dbdiff / dbdiff.php entry points to Symfony Application
- `diff` is the default command — legacy `dbdiff db1:db2` invocations unchanged
- ConfigOptionTrait — shared YAML config loading for all migration commands
Config
- MigrationConfig (src/Migration/Config/) — YAML config loader (dbdiff.yml)
- Add dbdiff.yml.example
- DBDiff::getDiffResult() — new lower-level method for programmatic use
…--server2-url, pgbouncer) - DsnParser: parse mysql/pgsql/postgres/sqlite DSN URLs; auto-detect Supabase hosts (.supabase.co / .supabase.com) and set sslmode=require; auto-enable pgbouncer on port 6543; toServerAndDb() bridge for CLIGetter-style structs - MigrationConfig: url: YAML key + db_url override (highest priority); pgbouncer property; applyDsn() private helper; toConnectionConfig() emits PDO::ATTR_EMULATE_PREPARES when pgbouncer detected - ConfigOptionTrait: addDbUrlOption() helper; --db-url option wired into loadConfig() with highest priority - All 7 migration:* commands: --db-url option added via addDbUrlOption() - DiffCommand: input argument OPTIONAL; --server1-url / --server2-url added; applyServerUrls() auto-builds input struct from URL db names; parseServer() now accepts full DSN URLs alongside legacy user:pass@host:port format - dbdiff.yml.example: Supabase connection guide (url:, pgbouncer port, explicit fields, and --server1-url CLI example)
…es already in use)
New unit test suite (no database required):
tests/Migration/Config/DsnParserTest.php — 22 tests
• parse() for mysql/pgsql/postgres/postgresql/sqlite
• default port assignment per driver
• SQLite absolute and relative path handling
• ?sslmode and ?pgbouncer query-string extras
• Supabase host heuristics (auto-SSL, port-6543 pgbouncer)
• URL-encoded credentials (user + password)
• isSupabaseHost() for .supabase.co and .supabase.com
• toServerAndDb() output shape and SQLite path bridging
• Error cases: unsupported scheme, malformed URL
tests/Migration/Format/NativeFormatTest.php — 10 tests
tests/Migration/Format/FlywayFormatTest.php — 10 tests
tests/Migration/Format/LiquibaseXmlFormatTest.php — 10 tests
tests/Migration/Format/LiquibaseYamlFormatTest.php — 11 tests
tests/Migration/Format/LaravelFormatTest.php — 13 tests
• render() return type (string vs array as appropriate)
• file naming conventions (Flyway V/U prefix, Laravel date format)
• description slugification and special-char stripping
• UP/DOWN SQL embedding
• empty-content placeholders
• valid XML / YAML / PHP output
• getExtension() / getLabel()
tests/Migration/Runner/MigrationFileTest.php — 18 tests
• scaffold() creates .up.sql + .down.sql with correct names
• scaffold() slugifies description, sets version
• scaffold() creates directory if missing
• scaffold() throws on duplicate
• getChecksum() is SHA-256 hex, idempotent, content-sensitive
• hasDown() / getDownSql() with and without DOWN file present
• getBaseName() format
• scanDir() ascending version order, skips non-matching files,
handles empty and non-existent directories
Config:
tests/phpunit.v9.xml — added 'Unit' test suite pointing at ./Migration
scripts/run-tests.sh — added --unit flag (runs Unit suite, no DB needed)
… false PHP's parse_url() treats the empty authority in sqlite:///abs/path as a malformed URL and returns false, causing an InvalidArgumentException. Relative paths (sqlite://./rel) worked because '.' was parsed as 'host'. Fix: detect the sqlite: scheme via regex before calling parse_url, then extract the path directly from the match groups. Removes all dependency on parse_url for SQLite URLs. Caught by DsnParserTest::testSqliteAbsolutePath running under php:8.3-cli.
- New 'unit-tests' job: runs --unit testsuite on PHP 8.0/8.3/8.4/8.5 with no DB service. Gives fast feedback on every push without waiting for MySQL/Postgres containers to spin up. - Removed PHP 7.4 from all three matrices (MySQL, SQLite, Postgres). composer.json now declares require php >=8.0; 7.4 would fail on composer install. The unit-tests job starts coverage from PHP 8.0.
PHP 7.x reached end of life in November 2022. The codebase already uses
PHP 8.0+ features (#[AsCommand] attributes, match expressions, str_contains,
str_starts_with) making it a parse error on PHP 7.x regardless.
Changes:
- docker-compose.yml: remove cli-php74-{mysql80,84,93,96} service blocks
- .env / .env.example: remove PHP_VERSION_74 variable
- .travis.yml: deleted (was PHP 5.4–7.1 only; superseded by GHA entirely)
- README.md: remove PHP 7.4 from pre-requisites and supported versions list;
remove '7.3' from standalone Docker CLI section heading
- DOCKER.md: remove PHP 7.4 from versions list, CLI services list,
run examples, test examples, and CI matrix table
- GHA tests.yml: already updated in previous commit (8.0+ only)
0eb0b15 to
6edf548
Compare
DiffCommand: - Reduce execute() cognitive complexity (33→~5) by extracting buildParams(), resolveConnections(), runAndWrite(), writeRendered() - Reduce execute() return count (6→2) via top-level try/catch wrapper - applyServerUrls() now mutates $params directly and returns $autoInput only DsnParser: - Rename $SCHEME_MAP → $schemeMap (match camelCase naming convention) - Reduce parse() cognitive complexity (18→~5) by extracting resolveSqlitePath() and applySupabaseHeuristics() helpers MigrationHistory: - Extract DATE_FORMAT constant to eliminate 4× duplicated 'Y-m-d H:i:s' literal MigrationFile: - Merge nested !is_dir / !mkdir if-statements into single &&-condition - Replace generic \RuntimeException with dedicated MigrationException MigrationConfig: - Replace generic \RuntimeException with dedicated ConfigException New: - src/Migration/Exceptions/MigrationException.php - src/Migration/Exceptions/ConfigException.php All 108 unit tests still pass (PHP 8.3).
…w code
Fix root cause of "No tests executed!" on GHA:
- Add Unit testsuite to tests/phpunit.xml (was only in phpunit.v9.xml)
- PHPUnit 10+/11+ (used by GHA) uses phpunit.xml; Unit suite was missing
New test files (all verified passing locally — PHP 8.4, 147 tests total):
tests/Migration/Command/DiffCommandTest.php (20 tests):
- resolveConnections() error paths: missing input, missing --server1-url,
missing --server2-url (via CommandTester)
- parseInput() validation: missing colon, mismatched depth, unknown format
- applyServerUrls() invalid scheme propagation
- normaliseInclude() all branches: both/all→both, down, up, unknown,
uppercase variants (via @dataProvider + reflection)
- parseInput() happy paths: db-level and table-level structures (reflection)
- buildParams() defaults and custom values (reflection + ArrayInput)
tests/Migration/Config/MigrationConfigTest.php (17 tests):
- Default property values when constructed with no file
- YAML loading: database section (individual fields), DSN url, mixed
- YAML loading: migrations section (dir, history_table, out_of_order)
- ConfigException for missing file and invalid YAML
- applyOverrides() direct key→property mapping, db_url priority,
Supabase host auto-heuristics through db_url
- toConnectionConfig() for MySQL, pgsql, pgsql+pgbouncer, SQLite
- resolveMigrationsDir() absolute, relative, trailing-slash strip
tests/Migration/Config/DsnParserTest.php (2 new tests):
- testSqliteBarePathGetsLeadingSlash: sqlite://rel/path → /rel/path
(exercises the `else` branch of resolveSqlitePath())
- testSqliteSchemeWithoutDoubleSlash: sqlite:/abs/path → /abs/path
Add config.platform.php = "8.0" to composer.json so Composer resolves dependencies against the minimum supported PHP version regardless of the host PHP. This ensures the generated lock file is compatible with all matrix entries (PHP 8.0, 8.3, 8.4, 8.5) and prevents platform_check.php from blocking older PHP versions during composer install on GHA.
more 7.4 refs
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.



migration:up/down/status/validate/repair/baselinecommands;YYYYMMDDHHMMSS_name.up/down.sqlfile pairs; SHA-256 checksum tracking via_dbdiff_migrationstable--formatflag ondiff; supports native, Flyway, Liquibase XML/YAML, and Laravel migration class--server1-url/--server2-urland--db-urlaccept full connection URLs; auto-detects Supabase hosts, sets SSL, enables pgbouncer on port 6543aura/clito Symfony Console;dbdiff.ymlconfig file support addedDsnParser, all 5 format classes, andMigrationFile; no DB requiredunit-testsjob (PHP 8.0–8.5, no service); PHP 7.x removed from all matrices