fix: Add pre-migration orphan cleanup to avoid chicken-and-egg failure (bd-eko4)

When the database has orphaned foreign key references (dependencies or labels
pointing to non-existent issues), the migration invariant check would fail,
preventing the database from opening. This created a chicken-and-egg problem:

1. bd doctor --fix tries to open the database
2. Opening triggers migrations with invariant checks
3. Invariant check fails due to orphaned refs
4. Fix never runs because database won't open

The fix adds CleanOrphanedRefs() that runs BEFORE captureSnapshot() in
RunMigrations. This automatically cleans up orphaned dependencies and labels
(preserving external:* refs), allowing the database to open normally.

Added test coverage for the cleanup function.
This commit is contained in:
Steve Yegge
2025-12-29 13:46:47 -08:00
parent 819208b8c1
commit 64d5f20b90
3 changed files with 155 additions and 0 deletions

View File

@@ -142,6 +142,13 @@ func RunMigrations(db *sql.DB) error {
}
}()
// Pre-migration cleanup: remove orphaned refs that would fail invariant checks.
// This prevents the chicken-and-egg problem where the database can't open
// due to orphans left behind by tombstone deletion (see bd-eko4).
if _, _, err := CleanOrphanedRefs(db); err != nil {
return fmt.Errorf("pre-migration orphan cleanup failed: %w", err)
}
snapshot, err := captureSnapshot(db)
if err != nil {
return fmt.Errorf("failed to capture pre-migration snapshot: %w", err)