From dd8327ff2b94540ef1170201d1f5a75c0cf7df7a Mon Sep 17 00:00:00 2001 From: Mark Wotton Date: Fri, 24 Oct 2025 14:34:52 +0700 Subject: [PATCH] Preserve dependency metadata during import (#141) --- internal/storage/sqlite/dependencies.go | 16 ++++++-- internal/storage/sqlite/dependencies_test.go | 42 ++++++++++++++++++++ 2 files changed, 54 insertions(+), 4 deletions(-) diff --git a/internal/storage/sqlite/dependencies.go b/internal/storage/sqlite/dependencies.go index 6850b449..4c3d6c95 100644 --- a/internal/storage/sqlite/dependencies.go +++ b/internal/storage/sqlite/dependencies.go @@ -61,8 +61,12 @@ func (s *SQLiteStorage) AddDependency(ctx context.Context, dep *types.Dependency } } - dep.CreatedAt = time.Now() - dep.CreatedBy = actor + if dep.CreatedAt.IsZero() { + dep.CreatedAt = time.Now() + } + if dep.CreatedBy == "" { + dep.CreatedBy = actor + } tx, err := s.db.BeginTx(ctx, nil) if err != nil { @@ -191,8 +195,12 @@ func (s *SQLiteStorage) addDependencyUnchecked(ctx context.Context, dep *types.D // NOTE: We skip parent-child direction validation here because during import/remap, // we're just updating IDs on existing dependencies that were already validated. - dep.CreatedAt = time.Now() - dep.CreatedBy = actor + if dep.CreatedAt.IsZero() { + dep.CreatedAt = time.Now() + } + if dep.CreatedBy == "" { + dep.CreatedBy = actor + } tx, err := s.db.BeginTx(ctx, nil) if err != nil { diff --git a/internal/storage/sqlite/dependencies_test.go b/internal/storage/sqlite/dependencies_test.go index 9595b837..a7f2f734 100644 --- a/internal/storage/sqlite/dependencies_test.go +++ b/internal/storage/sqlite/dependencies_test.go @@ -5,6 +5,7 @@ import ( "fmt" "strings" "testing" + "time" "github.com/steveyegge/beads/internal/types" ) @@ -149,6 +150,47 @@ func TestRemoveDependency(t *testing.T) { } } +func TestAddDependencyPreservesProvidedMetadata(t *testing.T) { + store, cleanup := setupTestDB(t) + defer cleanup() + + ctx := context.Background() + + parent := &types.Issue{Title: "Parent", Status: types.StatusOpen, Priority: 1, IssueType: types.TypeTask} + child := &types.Issue{Title: "Child", Status: types.StatusOpen, Priority: 1, IssueType: types.TypeTask} + store.CreateIssue(ctx, parent, "test-user") + store.CreateIssue(ctx, child, "test-user") + + customTime := time.Date(2024, 10, 24, 12, 0, 0, 0, time.UTC) + + dep := &types.Dependency{ + IssueID: child.ID, + DependsOnID: parent.ID, + Type: types.DepParentChild, + CreatedAt: customTime, + CreatedBy: "import", + } + + if err := store.AddDependency(ctx, dep, "test-user"); err != nil { + t.Fatalf("AddDependency failed: %v", err) + } + + records, err := store.GetDependencyRecords(ctx, child.ID) + if err != nil { + t.Fatalf("GetDependencyRecords failed: %v", err) + } + if len(records) != 1 { + t.Fatalf("Expected 1 dependency record, got %d", len(records)) + } + got := records[0] + if !got.CreatedAt.Equal(customTime) { + t.Fatalf("Expected CreatedAt %v, got %v", customTime, got.CreatedAt) + } + if got.CreatedBy != "import" { + t.Fatalf("Expected CreatedBy 'import', got %q", got.CreatedBy) + } +} + func TestGetDependents(t *testing.T) { store, cleanup := setupTestDB(t) defer cleanup()