Blog

Engineering

Why Jigward reads your database schema from the migrations, not the code

An answer about a table is only useful if it matches the real database. Jigward applies your Liquibase or Flyway migrations to an empty PostgreSQL and reads what they built, and says so when it cannot.

A QA engineer asks which table holds a booking. An analyst asks what a status column means before writing a request. An engineer asks whether a column can be null before changing the code that writes it. All three need the database as it is, and an answer that is close but wrong costs more than no answer: a test checks the wrong table, a request describes a field that does not exist, a change breaks on a constraint nobody mentioned.

That is why Jigward does not work the schema out from entity classes and queries. Those describe what the code expects of the database, which is not always what the migrations created. Jigward reads the schema the way the database gets it: by running the repository’s own migrations.

What you get

On a repository’s page, the Database tab shows each module’s schema: its tables, columns, keys, constraints, indexes, views, enum types and extensions, and the commit it was read at. In the app’s words: “Read from the migrations at commit … on …”.

When you ask a question in a Chat or give a Task, Jigward uses the same reading. It searches the tables a topic concerns across every module, by what the migrations name and say about them, then reads only those tables in full. A question about three tables does not need a thousand. The Task or the Chat also sees the commit the schema came from, and whether it is the commit the work is on.

How the schema is read

When a repository is added, and on every refresh, Jigward looks for Liquibase or Flyway setups. Which migrations apply is decided from file names and configuration read as data: no model, no build script, no application code.

For each setup it finds, only the migration files leave the repository. Jigward applies them to an empty PostgreSQL with its own copy of Liquibase or Flyway, pinned to an exact image, and reads back what the database now holds.

No member is asked before this runs, because what runs is the migrations under Jigward’s own tools, never the repository’s code. The database and the migration tool sit in containers on a network with no outside access, and nothing of the host is mounted except the migration files, read-only. That is a property of this one job. It is not a statement about Task workspaces, where repository code still reaches the public internet today.

One schema per module

A repository can hold several services with their own migrations, such as a fares module and a bookings module. Each module with migrations of its own gets its own schema, read, kept and shown apart. A table is named by its module, so two tables with the same name in two modules stay two tables.

Jigward does not work out which modules share a database at runtime, and it never merges two modules’ schemas. A module whose migrations have not changed since the last reading is not run again.

When there is nothing to read

A repository with no migrations has no schema, and the app says so: “There are no Liquibase or Flyway migrations at commit …, so there is no schema to read. Jigward doesn’t guess one from the code.”

The same holds module by module. A module whose migrations cannot run as they are is shown as not read, with the reason: it targets another database, its migrations need the repository’s own code, or it has two sets of migrations with nothing saying which applies. The other modules are read as if it were not there.

Migrations that fail are shown as failed for their module, with what the migration tool said. The schema read before stays in use, with the commit it was read at, so an older reading is never shown as a fresh one.

The same rule for your HTTP API

Jigward reads a repository’s HTTP API the same way, from OpenAPI 3 documents and nothing else. A committed document is a file named openapi, openapi3 or swagger, in JSON or YAML, outside build output and tests. A module that commits none, but whose build generates one with springdoc or with REST Docs through the restdocs-api-spec Gradle plugin, has its tests run in an isolated environment, and the document is taken from what they produce. The application itself is never started, no model takes part, and Jigward never derives an API from controllers.

What is supported

  • Database schemas: PostgreSQL only, with Liquibase or Flyway only. A module on another database is shown as not read, with the reason.
  • HTTP APIs: OpenAPI 3 only. A document that is not OpenAPI 3 is shown as not read for its module.
  • A schema is what the migrations define. An API document says where an endpoint is and what it accepts. What the endpoint does is still in the code.

The support is narrow on purpose. A reading that covers less and says exactly what it covered is one a colleague can rely on.