Refactor main.go to reduce cyclomatic complexity

Breaks down large functions into smaller, focused helpers to pass gocyclo linter:

Auto-import refactoring:
- Extract parseJSONLIssues() to handle JSONL parsing
- Extract handleCollisions() to detect and report conflicts
- Extract importIssueData() to coordinate issue/dep/label imports
- Extract updateExistingIssue() and createNewIssue() for clarity
- Extract importDependencies() and importLabels() for modularity

Flush refactoring:
- Extract recordFlushFailure() and recordFlushSuccess() for state management
- Extract readExistingJSONL() to isolate file reading logic
- Extract fetchDirtyIssuesFromDB() to separate DB access
- Extract writeIssuesToJSONL() to handle atomic writes

Command improvements:
- Extract executeLabelCommand() to eliminate duplication in label.go
- Extract addLabelsToIssue() helper for label management
- Replace deprecated strings.Title with manual capitalization

Configuration:
- Add gocyclo exception for test files in .golangci.yml

All tests passing, no functionality changes.
This commit is contained in:
Joshua Shanks
2025-10-15 21:06:17 -07:00
committed by Steve Yegge
parent cf4f11cff7
commit b1e8ef556e
6 changed files with 787 additions and 680 deletions

View File

@@ -8,26 +8,31 @@ import (
"github.com/steveyegge/beads/internal/types"
)
// AddLabel adds a label to an issue
func (s *SQLiteStorage) AddLabel(ctx context.Context, issueID, label, actor string) error {
// executeLabelOperation executes a label operation (add or remove) within a transaction
func (s *SQLiteStorage) executeLabelOperation(
ctx context.Context,
issueID, actor string,
labelSQL string,
labelSQLArgs []interface{},
eventType types.EventType,
eventComment string,
operationError string,
) error {
tx, err := s.db.BeginTx(ctx, nil)
if err != nil {
return fmt.Errorf("failed to begin transaction: %w", err)
}
defer tx.Rollback()
_, err = tx.ExecContext(ctx, `
INSERT OR IGNORE INTO labels (issue_id, label)
VALUES (?, ?)
`, issueID, label)
_, err = tx.ExecContext(ctx, labelSQL, labelSQLArgs...)
if err != nil {
return fmt.Errorf("failed to add label: %w", err)
return fmt.Errorf("%s: %w", operationError, err)
}
_, err = tx.ExecContext(ctx, `
INSERT INTO events (issue_id, event_type, actor, comment)
VALUES (?, ?, ?, ?)
`, issueID, types.EventLabelAdded, actor, fmt.Sprintf("Added label: %s", label))
`, issueID, eventType, actor, eventComment)
if err != nil {
return fmt.Errorf("failed to record event: %w", err)
}
@@ -45,40 +50,28 @@ func (s *SQLiteStorage) AddLabel(ctx context.Context, issueID, label, actor stri
return tx.Commit()
}
// AddLabel adds a label to an issue
func (s *SQLiteStorage) AddLabel(ctx context.Context, issueID, label, actor string) error {
return s.executeLabelOperation(
ctx, issueID, actor,
`INSERT OR IGNORE INTO labels (issue_id, label) VALUES (?, ?)`,
[]interface{}{issueID, label},
types.EventLabelAdded,
fmt.Sprintf("Added label: %s", label),
"failed to add label",
)
}
// RemoveLabel removes a label from an issue
func (s *SQLiteStorage) RemoveLabel(ctx context.Context, issueID, label, actor string) error {
tx, err := s.db.BeginTx(ctx, nil)
if err != nil {
return fmt.Errorf("failed to begin transaction: %w", err)
}
defer tx.Rollback()
_, err = tx.ExecContext(ctx, `
DELETE FROM labels WHERE issue_id = ? AND label = ?
`, issueID, label)
if err != nil {
return fmt.Errorf("failed to remove label: %w", err)
}
_, err = tx.ExecContext(ctx, `
INSERT INTO events (issue_id, event_type, actor, comment)
VALUES (?, ?, ?, ?)
`, issueID, types.EventLabelRemoved, actor, fmt.Sprintf("Removed label: %s", label))
if err != nil {
return fmt.Errorf("failed to record event: %w", err)
}
// Mark issue as dirty for incremental export
_, err = tx.ExecContext(ctx, `
INSERT INTO dirty_issues (issue_id, marked_at)
VALUES (?, ?)
ON CONFLICT (issue_id) DO UPDATE SET marked_at = excluded.marked_at
`, issueID, time.Now())
if err != nil {
return fmt.Errorf("failed to mark issue dirty: %w", err)
}
return tx.Commit()
return s.executeLabelOperation(
ctx, issueID, actor,
`DELETE FROM labels WHERE issue_id = ? AND label = ?`,
[]interface{}{issueID, label},
types.EventLabelRemoved,
fmt.Sprintf("Removed label: %s", label),
"failed to remove label",
)
}
// GetLabels returns all labels for an issue