mirror of
https://tangled.org/evan.jarrett.net/at-container-registry
synced 2026-09-02 08:16:57 +00:00
schema.sql and migrations/ are meant to move in lockstep, and nothing checked that they did. The cost is already on the record: migration 0009 exists only because 0004 "was supposed to drop these columns but either failed or was only recorded (not executed) on production", leaving production carrying eleven columns fresh installs never had. Build the schema both ways and compare. testdata/base_schema.sql is the shape immediately before 0009, reconstructed by reversing 0009-0029 out of the current schema.sql; applying it and then running every migration must land on the same place as applying schema.sql directly. Columns compare as a set, ignoring ordinal position. Migrations append with ADD COLUMN while schema.sql places the same column mid-table, so manifests, users, devices and repo_pages legitimately differ in order. Reordering them would mean four rebuild migrations for no functional gain, and nothing in pkg/appview reads by position (no SELECT *, no column-less INSERT ... VALUES). Verified non-vacuous three ways: a column only in schema.sql, a column only in a migration, and a table only in schema.sql are each caught. That last case is the one with teeth, since InitDB skips schema.sql entirely once schema_migrations has rows, so a table added only there never reaches an existing database. The snapshot records versions 1-8 as applied, which is what "before 0009" means. It also sidesteps a live rake: migration 0001's query is a bare SELECT, and go-libsql rejects row-returning statements passed to Exec. Every real database recorded 0001 long ago so it never fires, but a future migration opening with a SELECT would fail the same way. This cannot independently verify tables that appear in no migration; those are copied from schema.sql and compare against themselves. Drift there is the startup check's job. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>