Skip to content

fix: recreate the credential table skipped on databases created on v0.9.7 - #947

Merged
cristian-tamblay merged 1 commit into
developfrom
fix/credential-table-missing-after-upgrade
Oct 27, 2026
Merged

cristian-tamblay merged 1 commit into
developfrom
fix/credential-table-missing-after-upgrade

Conversation

@cristian-tamblay

Copy link
Copy Markdown
Member

Summary

Databases created on v0.9.7.post1 or v0.9.7.post2 (or on develop between 2026-07-02 and 2026-08-14) end up without the credential table after updating to 0.10.0 or develop. The app boots normally because the table is only touched lazily, and every /api/v1/credential/ request then fails with no such table: credential. This surfaced on a server install that had been running for months and was updated to today's develop.

Cause. a7d2c9e4f1b0 (model_name on parameter_history) reached develop on 2026-07-02 with parent f1a2b3c4d5e6. The merge 3f7083c5d (2026-07-23, develop into feat/base-credential) rewrote its parent to d4e8a2c6f0b1, the revision that creates credential, and that reached develop with #710 on 2026-08-14. Alembic stores only the current revision and treats every ancestor of it as applied, so on a database that already had a7d2c9e4f1b0, d4e8a2c6f0b1 is never run. v0.9.7.post1 (2026-08-07) and v0.9.7.post2 (2026-08-12) shipped a7d2c9e4f1b0 without the credential migration; v0.10.0 shipped the rewritten chain.

Scope, verified by simulation. A database built with the migrations of each tag from v0.9.0 to v0.10.0 and upgraded with develop's migrations was compared (tables, columns, unique constraints, indexes, foreign keys) with a database created from scratch. Only the two v0.9.7 tags differ, and only by the missing credential table. The other revision rewritten in that window (e0f00f71ba44, after b2c3d4e5f6a7 was renamed to d1c2b3a4f5e6 in 31dee775e) is harmless: its content was already applied under the old id, so skipping it is correct.

The existing DB Migrations workflow could not catch this: it only runs base → head → base → head on an empty database.


Type of Change

Check all that apply like this [x]:

  • Backend change
  • Frontend change
  • CI / Workflow change
  • Build / Packaging change
  • Bug fix
  • Documentation

Changes (by file)

  • DashAI/alembic/versions/72db19a8ec8d_ensure_credential_table_exists.py: new head revision. Creates credential with the same DDL as d4e8a2c6f0b1 when the table is missing, does nothing otherwise. Downgrade is a no-op because d4e8a2c6f0b1 owns the table.
  • scripts/ci_alembic_history.py: two checks that protect databases out there.
    • check-parents REF...: fails if a migration present in a git ref is missing from the working tree or has a different down_revision. This is the edit that caused the bug.
    • upgrade-from REF...: builds a database with each ref's migrations (via git archive), upgrades it with the working-tree migrations and diffs the schema against a fresh database. It drives the migrations through -x url so the DATABASE_URL the workflow sets is never touched, and lists the revisions Alembic counts as applied without running them.
  • .github/workflows/db-migrations.yaml: fetch-depth: 0 (tags and base branch are needed), check-parents against the latest tag plus the PR base branch, and upgrade-from against the last 8 tags after the existing steps.
  • tests/back/migrations/test_ensure_credential_table_exists.py: the revision recreates the table when it is missing, and leaves an existing table and its rows alone on upgrade and downgrade.

Testing

Run locally on this branch:

  • pytest tests/back/migrations: 17 passed.
  • check-parents v0.10.0 origin/develop: passes. Against v0.9.7.post2 it reports the three historical rewrites, which is why the workflow compares against the latest tag only; upgrade-from is what covers the older ones.
  • upgrade-from on the last 8 tags: all OK, with DATABASE_URL pointing at a decoy file that was never created. With the new migration removed, v0.9.7.post2 fails with missing table credential.
  • The existing steps (upgrade head, downgrade base, upgrade head, ci_alembic_check): pass.

Notes

  • Updates and data: the migration only creates an empty table when it is absent. Nothing else is touched. The server install that surfaced this was patched by hand with the same DDL; the new revision detects the table there and does nothing.
  • Rule going forward: never edit the down_revision (or the id) of a migration that already reached develop or a release. Two heads are joined with a merge revision (alembic merge). CI now enforces this against the base branch of every PR.

…ation

Databases created on v0.9.7.post1 or v0.9.7.post2 applied a7d2c9e4f1b0
while its parent was f1a2b3c4d5e6. The merge 3f7083c later rewrote that
parent to d4e8a2c6f0b1 (credential table), so Alembic treats it as applied
on those databases and never creates the table.

- New head revision 72db19a8ec8d creates the table when it is missing.
- scripts/ci_alembic_history.py adds two checks: published migrations
  must keep their id and parent, and a database created on each of the
  last releases must upgrade to the same schema as a fresh one.
- The DB Migrations workflow runs both.
@cristian-tamblay
cristian-tamblay merged commit 5d85556 into develop Oct 27, 2026
18 checks passed
@cristian-tamblay
cristian-tamblay deleted the fix/credential-table-missing-after-upgrade branch October 27, 2026 15:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant