Fix 15 lint errors: dupl, gosec, revive, staticcheck, unparam

Reduced golangci-lint issues from 56 to 41:

Fixed:
- dupl (2→0): Extracted parseLabelArgs helper, added nolint for cobra commands
- gosec G104 (4→0): Handle unhandled errors with _ = assignments
- gosec G302/G306 (4→0): Fixed file permissions from 0644 to 0600
- revive exported (4→0): Added proper godoc comments for all exported types
- staticcheck SA1019 (1→0): Removed deprecated netErr.Temporary() call
- staticcheck SA4003 (1→0): Removed impossible uint64 < 0 check
- unparam (8→0): Removed unused params/returns, added nolint where needed

Renamed types in compact package to avoid stuttering:
- CompactConfig → Config
- CompactResult → Result

Remaining 41 issues are documented baseline:
- gocyclo (24): High complexity in large functions
- gosec G204/G115 (17): False positives for subprocess/conversions

Closes bd-92

Amp-Thread-ID: https://ampcode.com/threads/T-1c136506-d703-4781-bcfa-eb605999545a
Co-authored-by: Amp <amp@ampcode.com>
This commit is contained in:
Steve Yegge
2025-10-24 12:40:56 -07:00
parent 9dcb86ebfb
commit c2c7eda14f
16 changed files with 92 additions and 75 deletions

View File

@@ -42,7 +42,7 @@ func createTestDBWithIssues(t *testing.T, issues []*types.Issue) (string, *sqlit
}
// Helper function to write JSONL file
func writeJSONLFile(t *testing.T, dir string, issues []*types.Issue) string {
func writeJSONLFile(t *testing.T, dir string, issues []*types.Issue) {
t.Helper()
jsonlPath := filepath.Join(dir, "issues.jsonl")
f, err := os.Create(jsonlPath)
@@ -57,8 +57,6 @@ func writeJSONLFile(t *testing.T, dir string, issues []*types.Issue) string {
t.Fatalf("Failed to encode issue %s: %v", issue.ID, err)
}
}
return jsonlPath
}
// Helper function to capture stderr output

View File

@@ -48,7 +48,7 @@ Examples:
// Handle compact stats first
if compactStats {
if daemonClient != nil {
runCompactStatsRPC(ctx)
runCompactStatsRPC()
} else {
sqliteStore, ok := store.(*sqlite.SQLiteStorage)
if !ok {
@@ -94,7 +94,7 @@ Examples:
os.Exit(1)
}
config := &compact.CompactConfig{
config := &compact.Config{
APIKey: apiKey,
Concurrency: compactWorkers,
DryRun: compactDryRun,
@@ -512,7 +512,7 @@ func runCompactRPC(ctx context.Context) {
}
}
func runCompactStatsRPC(ctx context.Context) {
func runCompactStatsRPC() {
args := map[string]interface{}{
"tier": compactTier,
}

View File

@@ -30,7 +30,7 @@ func (l *DaemonLock) Close() error {
// acquireDaemonLock attempts to acquire an exclusive lock on daemon.lock
// Returns ErrDaemonLocked if another daemon is already running
func acquireDaemonLock(beadsDir string, global bool) (*DaemonLock, error) {
func acquireDaemonLock(beadsDir string, _ bool) (*DaemonLock, error) {
lockPath := filepath.Join(beadsDir, "daemon.lock")
// Open or create the lock file
@@ -56,7 +56,7 @@ func acquireDaemonLock(beadsDir string, global bool) (*DaemonLock, error) {
// Also write PID file for Windows compatibility (can't read locked files on Windows)
pidFile := filepath.Join(beadsDir, "daemon.pid")
_ = os.WriteFile(pidFile, []byte(fmt.Sprintf("%d\n", os.Getpid())), 0644)
_ = os.WriteFile(pidFile, []byte(fmt.Sprintf("%d\n", os.Getpid())), 0600)
return &DaemonLock{file: f, path: lockPath}, nil
}

View File

@@ -345,7 +345,7 @@ func removeIssueFromJSONL(issueID string) error {
// Write to temp file atomically
temp := fmt.Sprintf("%s.tmp.%d", path, os.Getpid())
out, err := os.OpenFile(temp, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0o644)
out, err := os.OpenFile(temp, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0o600)
if err != nil {
return fmt.Errorf("failed to create temp file: %w", err)
}

View File

@@ -66,14 +66,19 @@ func processBatchLabelOperation(issueIDs []string, label string, operation strin
}
}
func parseLabelArgs(args []string) (issueIDs []string, label string) {
label = args[len(args)-1]
issueIDs = args[:len(args)-1]
return
}
//nolint:dupl // labelAddCmd and labelRemoveCmd are similar but serve different operations
var labelAddCmd = &cobra.Command{
Use: "add [issue-id...] [label]",
Short: "Add a label to one or more issues",
Args: cobra.MinimumNArgs(2),
Run: func(cmd *cobra.Command, args []string) {
label := args[len(args)-1]
issueIDs := args[:len(args)-1]
issueIDs, label := parseLabelArgs(args)
processBatchLabelOperation(issueIDs, label, "added",
func(issueID, lbl string) error {
_, err := daemonClient.AddLabel(&rpc.LabelAddArgs{ID: issueID, Label: lbl})
@@ -85,14 +90,13 @@ var labelAddCmd = &cobra.Command{
},
}
//nolint:dupl // labelRemoveCmd and labelAddCmd are similar but serve different operations
var labelRemoveCmd = &cobra.Command{
Use: "remove [issue-id...] [label]",
Short: "Remove a label from one or more issues",
Args: cobra.MinimumNArgs(2),
Run: func(cmd *cobra.Command, args []string) {
label := args[len(args)-1]
issueIDs := args[:len(args)-1]
issueIDs, label := parseLabelArgs(args)
processBatchLabelOperation(issueIDs, label, "removed",
func(issueID, lbl string) error {
_, err := daemonClient.RemoveLabel(&rpc.LabelRemoveArgs{ID: issueID, Label: lbl})

View File

@@ -813,6 +813,8 @@ func canDialSocket(socketPath string, timeout time.Duration) bool {
}
// waitForSocketReadiness waits for daemon socket to be ready by testing actual connections
//
//nolint:unparam // timeout is configurable even though current callers use 5s
func waitForSocketReadiness(socketPath string, timeout time.Duration) bool {
deadline := time.Now().Add(timeout)
for time.Now().Before(deadline) {