mix phoenix_kit_hello_world.audit_migrations (PhoenixKitHelloWorld v0.2.2)

Copy Markdown View Source

Checks every installed PhoenixKit module's migration coordinator against the rules in lib/phoenix_kit_hello_world/migrations.ex.

mix phoenix_kit_hello_world.audit_migrations
mix phoenix_kit_hello_world.audit_migrations --prefix auth

Run it in a host app, against a database that has been migrated. It reads the database and calls each coordinator's reader functions; it never writes.

Why this exists

The rules a module-owned migration has to follow are all silent when broken. A coordinator that infers its version from "does the table exist" reports itself up to date at every version it will ever ship, so mix phoenix_kit.update prints a green line and applies nothing. A coordinator whose down/1 ignores the target version answers "roll back to V1" by dropping the table. Neither shows up in a test suite that has no database, and neither produces an error message when it goes wrong — they produce silence, or worse, success.

This task turns the mechanical part of that review into something that fails out loud.

What it checks

For each discovered module that returns a migration_module/0:

  • protocolcurrent_version/0, up/1, down/1, migrated_version/1 and migrated_version_runtime/1 all exported. Missing migrated_version_runtime/1 makes the module invisible to mix phoenix_kit.update; missing migrated_version/1 means up/1 cannot re-read the version it is about to change.
  • absent schema reports 0 — the reader must answer 0, and only 0, for a schema that does not exist.
  • invalid prefix raises — a prefix that cannot be used must raise, not be reported as version 0. Zero means "not installed here" and sends the updater off to install a schema over live data.
  • reported version ≤ target — a reader claiming to be ahead of the shipped code is inferring rather than reading.
  • version marker is numeric — only when the coordinator exports version_table/0. A non-numeric COMMENT ON TABLE on an existing table means the version is not stored there, so it is being inferred. This is the check that catches the whole class.

Coordinators without version_table/0 get the marker check reported as unverifiable, with the query to run by hand. Exporting it is one line:

def version_table, do: @version_table

Exits non-zero if anything failed, so it can gate a release.