diff options
| author | Peter Stone <thepeterstone@gmail.com> | 2026-01-25 20:55:58 -1000 |
|---|---|---|
| committer | Peter Stone <thepeterstone@gmail.com> | 2026-01-25 20:55:58 -1000 |
| commit | f5b997bfc4c77ef262726d14b30d387eb7acd1c6 (patch) | |
| tree | 740879da10f3ddcd62bf276cd0632134b53a23c8 /internal/api | |
| parent | fa95c71494458070b78270e3d9170076028fc974 (diff) | |
Fix all static analysis errors (golangci-lint)
- Fix errcheck: handle all error return values in production code
- Fix errcheck: handle all error return values in test files
- Fix staticcheck: replace deprecated WithCredentialsFile with WithAuthCredentialsFile
- Remove unused code: authHeaders, planToEatPlannerItem, planToEatResponse
- Use defer func() { _ = x.Close() }() pattern for ignored close errors
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Diffstat (limited to 'internal/api')
| -rw-r--r-- | internal/api/google_calendar.go | 3 | ||||
| -rw-r--r-- | internal/api/http.go | 4 | ||||
| -rw-r--r-- | internal/api/plantoeat.go | 25 | ||||
| -rw-r--r-- | internal/api/research_test.go | 18 | ||||
| -rw-r--r-- | internal/api/todoist_test.go | 12 | ||||
| -rw-r--r-- | internal/api/trello_test.go | 10 |
6 files changed, 26 insertions, 46 deletions
diff --git a/internal/api/google_calendar.go b/internal/api/google_calendar.go index dc61f3d..e4f9c2f 100644 --- a/internal/api/google_calendar.go +++ b/internal/api/google_calendar.go @@ -55,7 +55,8 @@ func deduplicateEvents(events []models.CalendarEvent) []models.CalendarEvent { // NewGoogleCalendarClient creates a client that fetches from multiple calendars. // calendarIDs can be comma-separated (e.g., "cal1@group.calendar.google.com,cal2@group.calendar.google.com") func NewGoogleCalendarClient(ctx context.Context, credentialsFile, calendarIDs string) (*GoogleCalendarClient, error) { - srv, err := calendar.NewService(ctx, option.WithCredentialsFile(credentialsFile)) + // Use type-safe credential loading (replaces deprecated WithCredentialsFile) + srv, err := calendar.NewService(ctx, option.WithAuthCredentialsFile(option.ServiceAccount, credentialsFile)) if err != nil { return nil, fmt.Errorf("unable to retrieve Calendar client: %v", err) } diff --git a/internal/api/http.go b/internal/api/http.go index 8854625..df28c65 100644 --- a/internal/api/http.go +++ b/internal/api/http.go @@ -95,7 +95,7 @@ func (c *BaseClient) PostEmpty(ctx context.Context, path string, headers map[str if err != nil { return fmt.Errorf("request failed: %w", err) } - defer resp.Body.Close() + defer func() { _ = resp.Body.Close() }() if resp.StatusCode < 200 || resp.StatusCode >= 300 { body, _ := io.ReadAll(resp.Body) @@ -126,7 +126,7 @@ func (c *BaseClient) doJSON(req *http.Request, result interface{}) error { if err != nil { return fmt.Errorf("request failed: %w", err) } - defer resp.Body.Close() + defer func() { _ = resp.Body.Close() }() if resp.StatusCode < 200 || resp.StatusCode >= 300 { body, _ := io.ReadAll(resp.Body) diff --git a/internal/api/plantoeat.go b/internal/api/plantoeat.go index a7fdf58..5c24cc1 100644 --- a/internal/api/plantoeat.go +++ b/internal/api/plantoeat.go @@ -39,27 +39,6 @@ func (c *PlanToEatClient) SetSessionCookie(cookie string) { c.sessionCookie = cookie } -func (c *PlanToEatClient) authHeaders() map[string]string { - return map[string]string{"Authorization": "Bearer " + c.apiKey} -} - -// planToEatPlannerItem represents a planner item from the API -type planToEatPlannerItem struct { - ID int `json:"id"` - Date string `json:"date"` - MealType string `json:"meal_type"` - Recipe struct { - ID int `json:"id"` - Title string `json:"title"` - URL string `json:"url"` - } `json:"recipe"` -} - -// planToEatResponse wraps the API response -type planToEatResponse struct { - Items []planToEatPlannerItem `json:"items"` -} - // GetUpcomingMeals fetches meals by scraping the planner web interface // Requires a valid session cookie set via SetSessionCookie func (c *PlanToEatClient) GetUpcomingMeals(ctx context.Context, days int) ([]models.Meal, error) { @@ -84,7 +63,7 @@ func (c *PlanToEatClient) GetUpcomingMeals(ctx context.Context, days int) ([]mod if err != nil { return nil, fmt.Errorf("request failed: %w", err) } - defer resp.Body.Close() + defer func() { _ = resp.Body.Close() }() log.Printf("DEBUG [PlanToEat/Meals]: Response status %d", resp.StatusCode) @@ -238,7 +217,7 @@ func (c *PlanToEatClient) GetShoppingList(ctx context.Context) ([]models.Shoppin if err != nil { return nil, fmt.Errorf("request failed: %w", err) } - defer resp.Body.Close() + defer func() { _ = resp.Body.Close() }() log.Printf("DEBUG [PlanToEat/Shopping]: Response status %d", resp.StatusCode) diff --git a/internal/api/research_test.go b/internal/api/research_test.go index 83a52b4..f2519e2 100644 --- a/internal/api/research_test.go +++ b/internal/api/research_test.go @@ -45,7 +45,7 @@ func TestTodoistSyncResearch(t *testing.T) { if err != nil { t.Fatalf("Failed to call Sync API: %v", err) } - defer resp.Body.Close() + defer func() { _ = resp.Body.Close() }() body, err := io.ReadAll(resp.Body) if err != nil { @@ -102,13 +102,13 @@ func TestTodoistSyncResearch(t *testing.T) { if err != nil { t.Fatalf("Incremental sync failed: %v", err) } - defer resp2.Body.Close() + defer func() { _ = resp2.Body.Close() }() body2, _ := io.ReadAll(resp2.Body) t.Logf("Incremental response size: %d bytes (vs full: %d bytes)", len(body2), len(body)) var syncResp2 map[string]interface{} - json.Unmarshal(body2, &syncResp2) + _ = json.Unmarshal(body2, &syncResp2) if items2, ok := syncResp2["items"].([]interface{}); ok { t.Logf("Incremental items count: %d", len(items2)) } @@ -142,7 +142,7 @@ func TestTrelloOptimizationResearch(t *testing.T) { t.Fatalf("Failed to fetch boards: %v", err) } body, _ := io.ReadAll(resp.Body) - resp.Body.Close() + _ = resp.Body.Close() fullDuration := time.Since(start) t.Logf("Test 1 - Full boards response:") @@ -150,7 +150,7 @@ func TestTrelloOptimizationResearch(t *testing.T) { t.Logf(" Duration: %v", fullDuration) var boards []map[string]interface{} - json.Unmarshal(body, &boards) + _ = json.Unmarshal(body, &boards) t.Logf(" Board count: %d", len(boards)) if len(boards) > 0 { t.Logf(" Fields in first board: %v", getKeys(boards[0])) @@ -170,7 +170,7 @@ func TestTrelloOptimizationResearch(t *testing.T) { t.Fatalf("Failed to fetch limited boards: %v", err) } body2, _ := io.ReadAll(resp2.Body) - resp2.Body.Close() + _ = resp2.Body.Close() limitedDuration := time.Since(start) t.Logf("\nTest 2 - Limited fields (id,name):") @@ -196,7 +196,7 @@ func TestTrelloOptimizationResearch(t *testing.T) { t.Fatalf("Failed to fetch board with cards: %v", err) } body3, _ := io.ReadAll(resp3.Body) - resp3.Body.Close() + _ = resp3.Body.Close() batchDuration := time.Since(start) t.Logf("\nTest 3 - Single board with cards/lists embedded:") @@ -204,7 +204,7 @@ func TestTrelloOptimizationResearch(t *testing.T) { t.Logf(" Duration: %v", batchDuration) var boardWithCards map[string]interface{} - json.Unmarshal(body3, &boardWithCards) + _ = json.Unmarshal(body3, &boardWithCards) if cards, ok := boardWithCards["cards"].([]interface{}); ok { t.Logf(" Cards count: %d", len(cards)) } @@ -227,7 +227,7 @@ func TestTrelloOptimizationResearch(t *testing.T) { t.Logf(" 'since' parameter: Error - %v", err) } else { body4, _ := io.ReadAll(resp4.Body) - resp4.Body.Close() + _ = resp4.Body.Close() t.Logf(" 'since' parameter: Status %d, Size %d bytes", resp4.StatusCode, len(body4)) } } diff --git a/internal/api/todoist_test.go b/internal/api/todoist_test.go index 2fa6e28..7bbcc1e 100644 --- a/internal/api/todoist_test.go +++ b/internal/api/todoist_test.go @@ -13,7 +13,7 @@ import ( // newTestTodoistClient creates a TodoistClient for testing with custom base URL func newTestTodoistClient(baseURL, apiKey string) *TodoistClient { client := NewTodoistClient(apiKey) - client.BaseClient.BaseURL = baseURL + client.BaseURL = baseURL client.syncClient.BaseURL = baseURL return client } @@ -62,7 +62,7 @@ func TestTodoistClient_CreateTask(t *testing.T) { } w.Header().Set("Content-Type", "application/json") - json.NewEncoder(w).Encode(response) + _ = json.NewEncoder(w).Encode(response) })) defer server.Close() @@ -96,7 +96,7 @@ func TestTodoistClient_CreateTask_WithDueDate(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { // Parse JSON body var payload map[string]interface{} - json.NewDecoder(r.Body).Decode(&payload) + _ = json.NewDecoder(r.Body).Decode(&payload) // Verify due_date if payload["due_date"] != "2026-01-15" { @@ -117,7 +117,7 @@ func TestTodoistClient_CreateTask_WithDueDate(t *testing.T) { } w.Header().Set("Content-Type", "application/json") - json.NewEncoder(w).Encode(response) + _ = json.NewEncoder(w).Encode(response) })) defer server.Close() @@ -181,7 +181,7 @@ func TestTodoistClient_CompleteTask_Error(t *testing.T) { // Mock server that returns error server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusNotFound) - w.Write([]byte(`{"error":"Task not found"}`)) + _, _ = w.Write([]byte(`{"error":"Task not found"}`)) })) defer server.Close() @@ -218,7 +218,7 @@ func TestTodoistClient_GetProjects(t *testing.T) { } w.Header().Set("Content-Type", "application/json") - json.NewEncoder(w).Encode(response) + _ = json.NewEncoder(w).Encode(response) })) defer server.Close() diff --git a/internal/api/trello_test.go b/internal/api/trello_test.go index 7433ff0..d677363 100644 --- a/internal/api/trello_test.go +++ b/internal/api/trello_test.go @@ -15,7 +15,7 @@ import ( // newTestTrelloClient creates a TrelloClient for testing with custom base URL func newTestTrelloClient(baseURL, apiKey, token string) *TrelloClient { client := NewTrelloClient(apiKey, token) - client.BaseClient.BaseURL = baseURL + client.BaseURL = baseURL return client } @@ -67,7 +67,7 @@ func TestTrelloClient_CreateCard(t *testing.T) { } w.Header().Set("Content-Type", "application/json") - json.NewEncoder(w).Encode(response) + _ = json.NewEncoder(w).Encode(response) })) defer server.Close() @@ -122,7 +122,7 @@ func TestTrelloClient_CreateCard_WithDueDate(t *testing.T) { } w.Header().Set("Content-Type", "application/json") - json.NewEncoder(w).Encode(response) + _ = json.NewEncoder(w).Encode(response) })) defer server.Close() @@ -176,7 +176,7 @@ func TestTrelloClient_UpdateCard(t *testing.T) { // Return 200 OK w.WriteHeader(http.StatusOK) - w.Write([]byte(`{"id":"card-123","name":"Updated Name"}`)) + _, _ = w.Write([]byte(`{"id":"card-123","name":"Updated Name"}`)) })) defer server.Close() @@ -201,7 +201,7 @@ func TestTrelloClient_UpdateCard_Error(t *testing.T) { // Mock server that returns error server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusBadRequest) - w.Write([]byte(`{"error":"Invalid card ID"}`)) + _, _ = w.Write([]byte(`{"error":"Invalid card ID"}`)) })) defer server.Close() |
