From e4026d3c8bd11a5802ca342db27d58ec45a5aa72 Mon Sep 17 00:00:00 2001 From: Byron Guina Date: Tue, 22 Sep 2026 21:58:34 -0500 Subject: [PATCH] fix(lint): discard Close errors explicitly so golangci-lint passes The lint job has failed on every CI run since Feb 10, including on main. golangci-lint's errcheck flagged 15 calls to rows.Close() and conceptRows.Close() in internal/db/labels.go and internal/db/learnings.go whose error return was silently dropped. CI only showed 6 of them because golangci-lint collapses repeats of the same message by default. The rest of internal/db already uses `defer func() { _ = rows.Close() }()` to mark the error as deliberately ignored; these two files predate or missed that convention. This applies the same pattern: deferred closes get the wrapper, and inline closes on early-return paths become `_ = conceptRows.Close()`. Clearing errcheck surfaced one staticcheck SA5011 in TestGetCurrentTaskID: a false positive, since t.Fatal stops the test before the dereference. It is restructured as `else if` rather than suppressed, which is correct without the analyzer needing to know t.Fatal does not return. No behavior change: Close errors were already ignored; this only makes that explicit. Co-Authored-By: Claude Opus 5.5 --- internal/db/labels.go | 6 +++--- internal/db/learnings.go | 24 ++++++++++++------------ internal/db/learnings_test.go | 3 +-- 3 files changed, 16 insertions(+), 17 deletions(-) diff --git a/internal/db/labels.go b/internal/db/labels.go index 0ab046b..adf1a7e 100644 --- a/internal/db/labels.go +++ b/internal/db/labels.go @@ -65,7 +65,7 @@ func (db *DB) ListLabels(project string) ([]model.Label, error) { if err != nil { return nil, fmt.Errorf("failed to list labels: %w", err) } - defer rows.Close() + defer func() { _ = rows.Close() }() var labels []model.Label for rows.Next() { @@ -208,7 +208,7 @@ func (db *DB) GetItemLabels(itemID string) ([]model.Label, error) { if err != nil { return nil, fmt.Errorf("failed to get item labels: %w", err) } - defer rows.Close() + defer func() { _ = rows.Close() }() var labels []model.Label for rows.Next() { @@ -257,7 +257,7 @@ func (db *DB) PopulateItemLabels(items []model.Item) error { if err != nil { return fmt.Errorf("failed to query item labels: %w", err) } - defer rows.Close() + defer func() { _ = rows.Close() }() // Build a map of item ID -> label names labelMap := make(map[string][]string) diff --git a/internal/db/learnings.go b/internal/db/learnings.go index d5a44ca..49d72fd 100644 --- a/internal/db/learnings.go +++ b/internal/db/learnings.go @@ -108,7 +108,7 @@ func (db *DB) GetLearning(id string) (*model.Learning, error) { if err != nil { return nil, fmt.Errorf("failed to get concepts: %w", err) } - defer rows.Close() + defer func() { _ = rows.Close() }() for rows.Next() { var concept string @@ -153,7 +153,7 @@ func (db *DB) ListConcepts(project string, sortByRecent bool) ([]model.Concept, if err != nil { return nil, fmt.Errorf("failed to list concepts: %w", err) } - defer rows.Close() + defer func() { _ = rows.Close() }() var concepts []model.Concept for rows.Next() { @@ -327,7 +327,7 @@ func (db *DB) GetLearningsByConcepts(project string, conceptNames []string, incl if err != nil { return nil, fmt.Errorf("failed to query learnings: %w", err) } - defer rows.Close() + defer func() { _ = rows.Close() }() var learnings []model.Learning for rows.Next() { @@ -359,12 +359,12 @@ func (db *DB) GetLearningsByConcepts(project string, conceptNames []string, incl for conceptRows.Next() { var concept string if err := conceptRows.Scan(&concept); err != nil { - conceptRows.Close() + _ = conceptRows.Close() return nil, fmt.Errorf("failed to scan concept: %w", err) } l.Concepts = append(l.Concepts, concept) } - conceptRows.Close() + _ = conceptRows.Close() learnings = append(learnings, l) } @@ -394,7 +394,7 @@ func (db *DB) SearchLearnings(project string, query string, includeStale bool) ( if err != nil { return nil, fmt.Errorf("failed to search learnings: %w", err) } - defer rows.Close() + defer func() { _ = rows.Close() }() var learnings []model.Learning for rows.Next() { @@ -426,12 +426,12 @@ func (db *DB) SearchLearnings(project string, query string, includeStale bool) ( for conceptRows.Next() { var concept string if err := conceptRows.Scan(&concept); err != nil { - conceptRows.Close() + _ = conceptRows.Close() return nil, fmt.Errorf("failed to scan concept: %w", err) } l.Concepts = append(l.Concepts, concept) } - conceptRows.Close() + _ = conceptRows.Close() learnings = append(learnings, l) } @@ -462,7 +462,7 @@ func (db *DB) ListConceptsWithStats(project string) ([]ConceptStats, error) { if err != nil { return nil, fmt.Errorf("failed to list concept stats: %w", err) } - defer rows.Close() + defer func() { _ = rows.Close() }() var stats []ConceptStats now := time.Now() @@ -516,7 +516,7 @@ func (db *DB) GetAllLearnings(project string, includeStale bool) ([]model.Learni if err != nil { return nil, fmt.Errorf("failed to query learnings: %w", err) } - defer rows.Close() + defer func() { _ = rows.Close() }() var learnings []model.Learning for rows.Next() { @@ -548,12 +548,12 @@ func (db *DB) GetAllLearnings(project string, includeStale bool) ([]model.Learni for conceptRows.Next() { var concept string if err := conceptRows.Scan(&concept); err != nil { - conceptRows.Close() + _ = conceptRows.Close() return nil, fmt.Errorf("failed to scan concept: %w", err) } l.Concepts = append(l.Concepts, concept) } - conceptRows.Close() + _ = conceptRows.Close() learnings = append(learnings, l) } diff --git a/internal/db/learnings_test.go b/internal/db/learnings_test.go index f814fad..4fe63f1 100644 --- a/internal/db/learnings_test.go +++ b/internal/db/learnings_test.go @@ -762,8 +762,7 @@ func TestGetCurrentTaskID(t *testing.T) { } if taskID == nil { t.Fatal("expected task ID, got nil") - } - if *taskID != task.ID { + } else if *taskID != task.ID { t.Errorf("taskID = %q, want %q", *taskID, task.ID) } }