bd-162: Add database integrity checks with oracle review fixes
- Added validatePreExport to prevent data loss - Added checkDuplicateIDs to detect corruption - Added checkOrphanedDeps to find orphaned dependencies (both sides) - Added validatePostImport to ensure imports don't lose data - CRITICAL FIX: Removed post-pull export that clobbered fresh JSONL - Conservative checks when JSONL is unreadable - Efficient COUNT(*) SQL path instead of loading all issues - Comprehensive test coverage including edge cases
This commit is contained in:
@@ -104,6 +104,23 @@ Use --import-only to just import from JSONL (useful after git pull).`,
|
||||
if dryRun {
|
||||
fmt.Println("→ [DRY RUN] Would export pending changes to JSONL")
|
||||
} else {
|
||||
// Pre-export integrity checks
|
||||
if err := ensureStoreActive(); err == nil && store != nil {
|
||||
if err := validatePreExport(ctx, store, jsonlPath); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Pre-export validation failed: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
if err := checkDuplicateIDs(ctx, store); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Database corruption detected: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
if orphaned, err := checkOrphanedDeps(ctx, store); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Warning: orphaned dependency check failed: %v\n", err)
|
||||
} else if len(orphaned) > 0 {
|
||||
fmt.Fprintf(os.Stderr, "Warning: found %d orphaned dependencies: %v\n", len(orphaned), orphaned)
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Println("→ Exporting pending changes to JSONL...")
|
||||
if err := exportToJSONL(ctx, jsonlPath); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error exporting: %v\n", err)
|
||||
@@ -144,12 +161,36 @@ Use --import-only to just import from JSONL (useful after git pull).`,
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Count issues before import for validation
|
||||
var beforeCount int
|
||||
if err := ensureStoreActive(); err == nil && store != nil {
|
||||
beforeCount, err = countDBIssues(ctx, store)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Warning: failed to count issues before import: %v\n", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Step 4: Import updated JSONL after pull
|
||||
fmt.Println("→ Importing updated JSONL...")
|
||||
if err := importFromJSONL(ctx, jsonlPath, renameOnImport); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error importing: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Validate import didn't cause data loss
|
||||
if beforeCount > 0 {
|
||||
if err := ensureStoreActive(); err == nil && store != nil {
|
||||
afterCount, err := countDBIssues(ctx, store)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Warning: failed to count issues after import: %v\n", err)
|
||||
} else {
|
||||
if err := validatePostImport(beforeCount, afterCount); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Post-import validation failed: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user