Repository navigation
Releases: fsmutimeer/migrax
Releases · fsmutimeer/migrax
Release list
Migrax 0.17.2-rc.1
Release candidate for 0.17.2, for testing: Java migration numbering, the order of column drops,
verify in the server's version and the Quarkus startup metrics. It is not on Maven Central: use
the CLI from the Download page or the container image ghcr.io/fsmutimeer/migrax:0.17.2-rc.1.
Changed
verifystarts its throwaway PostgreSQL, MySQL or MariaDB container in the version of your
database server when Migrax can reach it, as reading a schema file already did, so the
migrations are proven on the version they will run on. Before, it always used its default
image (postgres:16-alpinefor PostgreSQL).--imagestill picks another one.generateanddiffnow drop columns after adding and changing the table's other columns.
MySQL, MariaDB, Oracle and H2 commit each schema change at once, so when a later statement
of a migration failed, for example making a new column NOT NULL while it still has empty
rows, the old column and its data were already gone. Now the migration stops while they are
still there. The order of the summary lines changes the same way, and so can the name of
the generated file.
Fixed
generategave its file the number of a Java migration written withmigrax new --java
when that number was the highest one, because it counted only SQL files. Both migrations
then ran in an order nobody chose (the SQL file first). Java migrations now count, and
generate,checkanddoctorreport a SQL file and a Java migration that share a number,
with how to fix it: rename the one that is not applied yet. A project that already has such
a pair failscheck(exit code 1) until then, unless both are applied in its database.migrax new --javarefuses a--java-packageormigrax.java-packagethat is not a Java
package name. A value such as/tmp/xor..xmade it write the class outside the project.
With a comma list of packages, the class goes into the first one.- Quarkus: the
migrax.migrations.appliedandmigrax.migrations.failedcounters and the
migrax.runtimer of the migrations at startup could stay at 0 in the application's
registries (Prometheus, OTLP, ...), depending on the order in which Quarkus ran its startup
steps. They now always count the startup run.
Migrax 0.17.1
Added
- Every GitHub release lists the libraries it contains in
migrax-<version>-sbom.cdx.json
(CycloneDX), and each of its files has a signed record of the workflow run that built it:
gh attestation verify <file> -R fsmutimeer/migraxchecks it. The container image carries
its own software list and build record in the registry. See Download > Check your
download.
Fixed
- Renaming a table no longer needs
--allow-destructive. Hibernate's foreign key names
contain the table name, sogenerate --rename-table(or answering "yes" to "Did you
rename table ...?") dropped the old key and added it again under its new name, and the drop
was counted as a destructive change. A foreign key that comes back unchanged under a new
name in the same migration is no longer destructive; one that is really removed or changed
still is. It is listed as "rename foreign key ..." ("kind": "rename_foreign_key"in
plan --jsonanddiff --json). On PostgreSQL, CockroachDB, YugabyteDB and H2 the
migration renames the key (RENAME CONSTRAINT); other databases drop it and add it again,
which checks every row. - SQLite: the rollback of a table rename lost the other changes to that table (a renamed
foreign key, a changed column). SQLite makes them by rebuilding the table, and the rollback
looked the table up under the name it gives back only afterwards, so the rebuild was left
out without a word. It is now rebuilt under that name, and a table that can't be found stops
migrax generatewith an error instead. - Oracle: making a NUMBER column smaller (fewer decimals or fewer digits before the point,
biginttointegerincluded) failed with ORA-01440 once the table had rows, in a
migration or in the rollback of one that made it larger. Oracle allows that only on an
empty column, so the change now goes through a new column: first a check that every value
fits unchanged (a value with too many digits or decimals stops the migration with a message
saying how many, before the column is changed, and so does an index, constraint or column
grant made by hand that dropping the column would remove), then the new column is added, a
trigger keeps it up to date while the application goes on writing, the values are copied
and checked once more, the old column is dropped (writes fail for a moment there) and the
new one gets its name, default, NOT NULL and comment. The table is rewritten and the column
moves to its end; the migration account needsCREATE TRIGGER. Columns in a key, index,
unique constraint or check, and identity columns, keep the plain change, which Oracle
still refuses once they have values (see Reference > Limitations).
Security
- Container image: newer JDBC drivers without known vulnerabilities. PostgreSQL 42.7.5 to
42.7.14 (could fall back to weaker authentication despitechannelBinding=require, and a
server could make it spend CPU on SCRAM), MariaDB 3.5.1 to 3.5.11 (could send the password
in clear text to a server in the middle), SQL Server 12.8.1 to 13.6.1 (did not check some
input from the server well enough). URLs withencryptandtrustServerCertificatework
as before (tested on SQL Server 2022). The CLI download bundles no drivers and is not affected. - Container image: the base images are pinned to exact versions, so every build of a release
ships the same thing, and/usr/bin/pebble, a program of the base image that Migrax never
runs and that scanners report, is removed. - The published POMs no longer name library versions with known vulnerabilities
(Micrometer, OpenTelemetry, Spring Boot). Migrax never bundled them: your application keeps
its own versions, and the framework versions Migrax works with are unchanged. - The GitHub Action (
uses: fsmutimeer/migrax@...) runs the actions it uses at exact
commits instead of version tags, so a moved or compromised tag can't change what runs in
your workflow.
Migrax 0.17.0
Added
- Spring Data JDBC: projects without JPA that use Spring Data JDBC (3.0 to 4.1, Spring Boot 3.0
to 4.1) getgenerate,check,verify,driftand the startup migration like JPA
projects. Migrax reads Spring Data JDBC's own mapping, without a database: aggregate roots
are the classes with@Tableand the types of repositories, and their child tables get the
back-reference and key columns Spring Data JDBC names (@MappedCollection), with a foreign
key to the parent. Found by itself when the project has no JPA entities, or chosen with
--extractor spring-data-jdbc. Names written in@Tableor@Columnkeep their letter case
where an unquoted name would get another one (lower case on H2, Oracle, HSQLDB and Derby,
capitals on PostgreSQL), as Spring Data JDBC sends them quoted. See Reference >
Entity readers. - Micronaut Data JDBC and R2DBC: projects with
@MappedEntityentities (Micronaut Data 4 and
5) getgenerate,check,verifyanddriftlike JPA projects. Migrax reads the mapping
Micronaut's annotation processor compiled, without a database, and follows Micronaut Data's
rules for names, join tables, embedded values and generated ids (identity, sequences, UUIDs).
Found by itself when the project has no JPA entities, or chosen with
--extractor micronaut-data. Micronaut 5 projects need Migrax running on Java 25; Migrax
names the Java a project needs when it can't load its classes. See Reference > Entity
readers. migrax environments: every environment's migrations side by side, read-only. For each
migrax.environments.<name>.url(dev, staging, production, ...) it shows how many migrations
are applied and pending, the last one applied and whether the schema drifted from the
snapshot;-- migrax:envmigrations count only where they run. All databases are asked at
once with--timeout, so one that doesn't answer only marks its own row. Exit code 1 when an
environment can't be reached or a migration failed, changed or is missing there, 2 on drift;
--jsonfor dashboards. ErrorMXE116when none is configured. See Guides > Comparing
databases.- Migrations from a SQL file instead of entities: with
migrax.schema-file=db/schema.sql
(--schema-file,MIGRAX_SCHEMA_FILE, ormigrax.databases.<name>.schema-file), a project
without JPA entities keeps its tables as they should be in one SQL file, andgenerate
writes the migration and its rollback script from the changes, with rename questions, lint
and--zero-downtimeas for entities.plan,check,verifyanddoctorread the file
too. Migrax reads it by applying it to a throwaway database (in memory, Docker, or an empty
one given with--scratch-url) and keeps what it read in.migrax/schema-model.json, so
checkin CI needs no Docker while the file is unchanged. A statement that fails is named
with its line (errorMXE115). On PostgreSQL, MySQL and MariaDB the throwaway database runs
the server's own version, so a file written bypg_dump --schema-onlyor
mysqldump --no-dataapplies as it is. See Guides > SQL migrations for any language and
Guides > Schema file from your ORM (SQLAlchemy, Drizzle, and any ORM through a dump).
Fixed
migrax cleandrops tables and sequences whose names keep their letter case: names with
capitals on PostgreSQL, or lower-case names created in quotes on H2 and Oracle. Before, it
stopped with "table does not exist".- The Spring Boot starter now works on Spring Boot 4. Spring Boot 4 moved the classes the
starter was ordered against, so it didn't run at all: no migrations at startup, and a JPA
application withddl-auto=validatefailed with a missing table. Themigraxhealth
component works with Spring Boot 4's Actuator too. migrax-micronautnow works on Micronaut 4.0 to 4.9. Before, those versions skipped it
without an error: no migrations at startup, and the application failed on a missing table.
Micronaut 4.10 and 5 work as before.
Migrax 0.16.0
Added
- Drift at startup:
migrax.drift.check=warnorfailmakes the application compare the
database with the schema its migrations produce when it starts, in the Spring Boot, Quarkus,
Micronaut, Helidon and Jakarta EE integrations (migrax.databases.<name>.drift.checkper
database).warnlogs every difference,failstops the start; the default isoff. The
build puts.migrax/snapshot.jsoninto the application: the Quarkus extension (also native)
and the Gradle plugin do it by themselves, Maven with the new goalmigrax:package-snapshot.
See Guides > Production safety > Drift at startup.
Changed
historyandpendingcan't be names of further databases (migrax.databases.<name>): the
migraxcommand keeps the default database's files in.migrax/history/and
.migrax/pending/, next to each further database's.migrax/<name>/.migrax-integrationsandmigrax-quarkus-parentare no longer published to Maven Central:
they only group modules for the build, and no published artifact refers to them.
Migrax 0.15.0
Added
- Several databases per application: a block
migrax.databases.<name>.*(data source,
folders, Java package, schemas, placeholders) migrates a further database at startup, in the
Spring Boot, Quarkus (also native), Micronaut, Helidon and Jakarta EE integrations. Health
checks report every database. See Guides > Several databases. --database <name>on every command that works on a project (and-Dmigrax.databasefor
the Maven goals,MIGRAX_DATABASE): the command works on that database, with its own
connection, folders, entity package (migrax.databases.<name>.package) and snapshot in
.migrax/<name>/. The default database no longer reads the entities of another database's
package.
Changed
- Every metric has the tag
database(default, or the name of a further database), and
spans the attributemigrax.database. Queries without the tag keep working. - A migration folder without a prefix (
migrax.locations=db/sql,--locations db/sql) is now
a classpath folder (undersrc/main/resources) for themigraxcommand and the Maven and
Gradle goals too, the same as when the application migrates at startup. Before, the command
looked for it in the project folder. Writefilesystem:db/sqlfor a folder outside the
resources; absolute paths are unchanged.
Migrax 0.14.0
Added
migrax.migrate-at-startup=falsein the Spring Boot, Quarkus, Micronaut, Helidon and Jakarta
EE integrations: the application starts without migrating, for teams whose pipeline or DBA
runs the migrations, and logs what is pending; the health check keeps reporting.- Gauge
migrax.migrations.pending(migrax_migrations_pending): how many migrations wait to
run, in the same integrations when the application has Micrometer. Off with
migrax.metrics.enabled=false. See Guides > Metrics and tracing. migrax diff <source-url>: compares the schema of another database of the same kind (for
example staging) with the project's database and lists the changes that would make it match;
--sqlprints them as a script,--jsonfor tools, exit code 2 when they differ. Also
mvn migrax:diff. See Guides > Comparing databases.- GitLab CI and Bitbucket Pipelines templates:
check, lint of new or changed migrations, the
HTML report as an artifact, and a comment on the merge or pull request (updated on each
pipeline). See Guides > Continuous integration. - Published on Maven Central: the library and Maven plugin
org.migrax:migrax, the framework
integrations,migrax-junitand the Gradle pluginorg.migrax, with sources, javadoc and
signatures. Builds no longer need to install Migrax from the source first.
Changed
- Migrax is now licensed under the Apache License 2.0 (with a
NOTICEfile). Releases up to
0.13.0 keep the MIT License they were published with.
Fixed
generateno longer drops and re-adds a check constraint whose condition differs only in
spacing or in parentheses around the whole condition (databases store conditions their own
way, for example Derby).- Check conditions read from MySQL keep valid SQL quotes (MySQL reports
''as\'\'), and
MySQL, MariaDB and TiDB primary keys are no longer namedPRIMARYwhen Migrax writes them
back.
Migrax 0.13.0
Added
- Metrics and tracing of migrations at startup: Micrometer metrics (
migrax.run,
migrax.migration,migrax.migrations.applied/failed,migrax.lock.wait) and
OpenTelemetry spans (migrax migratewith amigrax migrationspan each), recorded by the
Spring Boot, Quarkus, Micronaut, Helidon and Jakarta EE integrations when the application has
aMeterRegistryor anOpenTelemetry. Turn them off withmigrax.metrics.enabled=falseor
migrax.tracing.enabled=false.MigrationListenerbeans hear every run too, and the Java API
takes listeners withlistener(...). See Guides > Metrics and tracing. - Preconditions: a
-- migrax:requireline makes a migration check the database before it
runs (table-exists,table-missing,column-exists,column-missing, orsql <query>).
An unmet condition stops the run (MXE114), or withelse skiprecords the migration without
running it.statusandmigrate --dry-runshow the conditions of pending migrations;
migrate --sqlchecks them for the first migration and stops before later ones.
Migrax 0.12.0
Four more databases: YugabyteDB, TiDB, HSQLDB and Apache Derby.
Added
- YugabyteDB (2024.2 and newer), the 9th database: dialect
yugabytedb, reached with the
PostgreSQL driver (recognized from the server) or YugabyteDB's own driver. It writes
PostgreSQL's SQL; the migration lock is PostgreSQL's advisory lock from 2025.1 on and a row
inmigrax_lockbefore.verifystarts a throwaway YugabyteDB container, and
--zero-downtimeworks as on PostgreSQL. - TiDB (7.5 and newer), the 10th database: dialect
tidb, reached with the MySQL driver and
recognized from the server. It writes MySQL's SQL; check constraints need
tidb_enable_check_constraint(migrax doctorwarns when it is off),--keep-databacks up
withCREATE TABLE ... LIKE, and--zero-downtimecan't split renames (no triggers or
writable views).verifystarts a throwaway TiDB container. - HSQLDB (HyperSQL 2.7 and newer), the 11th database: dialect
hsqldb, recognized from
jdbc:hsqldb:URLs. The migration lock is a row inmigrax_lock, so it also holds across
processes for file and server databases;verifyreplays the migrations in memory. - Apache Derby (10.16 and newer), the 12th database: dialect
derby, recognized from
jdbc:derby:URLs. Type changes Derby can't make in place rebuild the column, comments are
left out (Derby keeps none), andverifyreplays the migrations in memory.
Migrax 0.11.0
Zero-downtime changes and an HTML report.
Added
generate --zero-downtimesplits a change so the old and the new application version can
use the database at the same time: an expand migration for this release (new columns still
nullable, a renamed column copied and kept equal to the old one by a trigger, a renamed
table's old name kept as a view, wider types) and a contract migration for the next release
(drops, NOT NULL, narrower types, new constraints). The contract migration waits in
.migrax/pending/untilgenerate --contractadds it to the migration folder. Column
renames need PostgreSQL, MySQL, MariaDB or Oracle; table renames also work on SQL Server.
See Guides > Zero-downtime changes.migrax report(andmvn migrax:report) writes one HTML page for reviews and CI
artifacts: the schema with a diagram, entity changes without a migration, every migration
with its status and lint findings, and drift. The GitHub Action uploads it as the artifact
migrax-reportand links it from its pull request comment (report: falseturns it off).
Changed
- Lint rules MX007 (drops) and MX008 (renames) name
generate --zero-downtimeas the fix.
Migrax 0.10.0
A Java API, and a JUnit 5 extension that checks migrations against the entities.
Added
- A Java API,
org.migrax.api.Migrax:Migrax.configure().dataSource(ds).load(), then
migrate(),status(),rollback(steps),rollbackTo(version),validate()(do the
entities match the database?) andtestRollbacks(). The startup integrations run on it. migrax-junit, a JUnit 5 extension:@MigraxTestmigrates a test database (H2, a
DataSourceor a Testcontainers container) before the tests and fails them when the
entities don't match the migrated schema. Withrollbacks = trueit also tests every
rollback script. See Guides > Java API and JUnit tests.