From d3b6855aa95913166e428af7971bc38ef608ea96 Mon Sep 17 00:00:00 2001 From: Steve Yegge Date: Mon, 29 Dec 2025 15:58:11 -0800 Subject: [PATCH] fix: resolve lint errors blocking CI MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add explicit error checking for fmt.Fprintf/Fprintln in claude.go - Add gosec nolint for safe exec.CommandContext calls in sync_git.go - Remove unused error return from findTownRoutes in routes.go šŸ¤– Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- cmd/bd/setup/claude.go | 46 +++++++++++++++++++------------------- cmd/bd/sync_git.go | 4 ++-- internal/routing/routes.go | 16 ++++++------- 3 files changed, 33 insertions(+), 33 deletions(-) diff --git a/cmd/bd/setup/claude.go b/cmd/bd/setup/claude.go index fe086115..53806004 100644 --- a/cmd/bd/setup/claude.go +++ b/cmd/bd/setup/claude.go @@ -71,21 +71,21 @@ func installClaude(env claudeEnv, project bool, stealth bool) error { var settingsPath string if project { settingsPath = projectSettingsPath(env.projectDir) - fmt.Fprintln(env.stdout, "Installing Claude hooks for this project...") + _, _ = fmt.Fprintln(env.stdout, "Installing Claude hooks for this project...") } else { settingsPath = globalSettingsPath(env.homeDir) - fmt.Fprintln(env.stdout, "Installing Claude hooks globally...") + _, _ = fmt.Fprintln(env.stdout, "Installing Claude hooks globally...") } if err := env.ensureDir(filepath.Dir(settingsPath), 0o755); err != nil { - fmt.Fprintf(env.stderr, "Error: %v\n", err) + _, _ = fmt.Fprintf(env.stderr, "Error: %v\n", err) return err } settings := make(map[string]interface{}) if data, err := env.readFile(settingsPath); err == nil { if err := json.Unmarshal(data, &settings); err != nil { - fmt.Fprintf(env.stderr, "Error: failed to parse settings.json: %v\n", err) + _, _ = fmt.Fprintf(env.stderr, "Error: failed to parse settings.json: %v\n", err) return err } } @@ -102,26 +102,26 @@ func installClaude(env claudeEnv, project bool, stealth bool) error { } if addHookCommand(hooks, "SessionStart", command) { - fmt.Fprintln(env.stdout, "āœ“ Registered SessionStart hook") + _, _ = fmt.Fprintln(env.stdout, "āœ“ Registered SessionStart hook") } if addHookCommand(hooks, "PreCompact", command) { - fmt.Fprintln(env.stdout, "āœ“ Registered PreCompact hook") + _, _ = fmt.Fprintln(env.stdout, "āœ“ Registered PreCompact hook") } data, err := json.MarshalIndent(settings, "", " ") if err != nil { - fmt.Fprintf(env.stderr, "Error: marshal settings: %v\n", err) + _, _ = fmt.Fprintf(env.stderr, "Error: marshal settings: %v\n", err) return err } if err := env.writeFile(settingsPath, data); err != nil { - fmt.Fprintf(env.stderr, "Error: write settings: %v\n", err) + _, _ = fmt.Fprintf(env.stderr, "Error: write settings: %v\n", err) return err } - fmt.Fprintln(env.stdout, "\nāœ“ Claude Code integration installed") - fmt.Fprintf(env.stdout, " Settings: %s\n", settingsPath) - fmt.Fprintln(env.stdout, "\nRestart Claude Code for changes to take effect.") + _, _ = fmt.Fprintln(env.stdout, "\nāœ“ Claude Code integration installed") + _, _ = fmt.Fprintf(env.stdout, " Settings: %s\n", settingsPath) + _, _ = fmt.Fprintln(env.stdout, "\nRestart Claude Code for changes to take effect.") return nil } @@ -144,14 +144,14 @@ func checkClaude(env claudeEnv) error { switch { case hasBeadsHooks(globalSettings): - fmt.Fprintf(env.stdout, "āœ“ Global hooks installed: %s\n", globalSettings) + _, _ = fmt.Fprintf(env.stdout, "āœ“ Global hooks installed: %s\n", globalSettings) return nil case hasBeadsHooks(projectSettings): - fmt.Fprintf(env.stdout, "āœ“ Project hooks installed: %s\n", projectSettings) + _, _ = fmt.Fprintf(env.stdout, "āœ“ Project hooks installed: %s\n", projectSettings) return nil default: - fmt.Fprintln(env.stdout, "āœ— No hooks installed") - fmt.Fprintln(env.stdout, " Run: bd setup claude") + _, _ = fmt.Fprintln(env.stdout, "āœ— No hooks installed") + _, _ = fmt.Fprintln(env.stdout, " Run: bd setup claude") return errClaudeHooksMissing } } @@ -173,27 +173,27 @@ func removeClaude(env claudeEnv, project bool) error { var settingsPath string if project { settingsPath = projectSettingsPath(env.projectDir) - fmt.Fprintln(env.stdout, "Removing Claude hooks from project...") + _, _ = fmt.Fprintln(env.stdout, "Removing Claude hooks from project...") } else { settingsPath = globalSettingsPath(env.homeDir) - fmt.Fprintln(env.stdout, "Removing Claude hooks globally...") + _, _ = fmt.Fprintln(env.stdout, "Removing Claude hooks globally...") } data, err := env.readFile(settingsPath) if err != nil { - fmt.Fprintln(env.stdout, "No settings file found") + _, _ = fmt.Fprintln(env.stdout, "No settings file found") return nil } var settings map[string]interface{} if err := json.Unmarshal(data, &settings); err != nil { - fmt.Fprintf(env.stderr, "Error: failed to parse settings.json: %v\n", err) + _, _ = fmt.Fprintf(env.stderr, "Error: failed to parse settings.json: %v\n", err) return err } hooks, ok := settings["hooks"].(map[string]interface{}) if !ok { - fmt.Fprintln(env.stdout, "No hooks found") + _, _ = fmt.Fprintln(env.stdout, "No hooks found") return nil } @@ -204,16 +204,16 @@ func removeClaude(env claudeEnv, project bool) error { data, err = json.MarshalIndent(settings, "", " ") if err != nil { - fmt.Fprintf(env.stderr, "Error: marshal settings: %v\n", err) + _, _ = fmt.Fprintf(env.stderr, "Error: marshal settings: %v\n", err) return err } if err := env.writeFile(settingsPath, data); err != nil { - fmt.Fprintf(env.stderr, "Error: write settings: %v\n", err) + _, _ = fmt.Fprintf(env.stderr, "Error: write settings: %v\n", err) return err } - fmt.Fprintln(env.stdout, "āœ“ Claude hooks removed") + _, _ = fmt.Fprintln(env.stdout, "āœ“ Claude hooks removed") return nil } diff --git a/cmd/bd/sync_git.go b/cmd/bd/sync_git.go index b7beb307..88f8caae 100644 --- a/cmd/bd/sync_git.go +++ b/cmd/bd/sync_git.go @@ -387,7 +387,7 @@ func gitPull(ctx context.Context) error { remote := strings.TrimSpace(string(remoteOutput)) // Pull with explicit remote and branch - cmd := exec.CommandContext(ctx, "git", "pull", remote, branch) + cmd := exec.CommandContext(ctx, "git", "pull", remote, branch) //nolint:gosec // G204: remote/branch from git config, not user input output, err := cmd.CombinedOutput() if err != nil { return fmt.Errorf("git pull failed: %w\n%s", err, output) @@ -422,7 +422,7 @@ func restoreBeadsDirFromBranch(ctx context.Context) error { // Restore .beads/ from HEAD (current branch's committed state) // Using -- to ensure .beads/ is treated as a path, not a branch name - cmd := exec.CommandContext(ctx, "git", "checkout", "HEAD", "--", beadsDir) + cmd := exec.CommandContext(ctx, "git", "checkout", "HEAD", "--", beadsDir) //nolint:gosec // G204: beadsDir from FindBeadsDir(), not user input output, err := cmd.CombinedOutput() if err != nil { return fmt.Errorf("git checkout failed: %w\n%s", err, output) diff --git a/internal/routing/routes.go b/internal/routing/routes.go index 06fda97e..67d30e83 100644 --- a/internal/routing/routes.go +++ b/internal/routing/routes.go @@ -116,7 +116,7 @@ func LookupRigForgiving(input, beadsDir string) (Route, bool) { // lookupRigForgivingWithTown finds a route with flexible matching and returns the town root. // Returns (route, townRoot, found). func lookupRigForgivingWithTown(input, beadsDir string) (Route, string, bool) { - routes, townRoot, _ := findTownRoutes(beadsDir) + routes, townRoot := findTownRoutes(beadsDir) if len(routes) == 0 { return Route{}, "", false } @@ -235,7 +235,7 @@ func ResolveToExternalRef(id, beadsDir string) string { func ResolveBeadsDirForID(ctx context.Context, id, currentBeadsDir string) (string, bool, error) { // Step 1: Check for routes.jsonl based on ID prefix // First try local, then walk up to find town-level routes - routes, townRoot, _ := findTownRoutes(currentBeadsDir) + routes, townRoot := findTownRoutes(currentBeadsDir) if len(routes) > 0 { prefix := ExtractPrefix(id) if prefix != "" { @@ -294,29 +294,29 @@ func findTownRoot(startDir string) string { // findTownRoutes searches for routes.jsonl at the town level. // It walks up from currentBeadsDir to find the town root, then loads routes // from /.beads/routes.jsonl. -// Returns (routes, townRoot, error). -func findTownRoutes(currentBeadsDir string) ([]Route, string, error) { +// Returns (routes, townRoot). Returns nil routes if not in a Gas Town or no routes found. +func findTownRoutes(currentBeadsDir string) ([]Route, string) { // First try the current beads dir (works if we're already at town level) routes, err := LoadRoutes(currentBeadsDir) if err == nil && len(routes) > 0 { // Return the parent of the beads dir as "town root" for path resolution - return routes, filepath.Dir(currentBeadsDir), nil + return routes, filepath.Dir(currentBeadsDir) } // Walk up to find town root townRoot := findTownRoot(currentBeadsDir) if townRoot == "" { - return nil, "", nil // Not in a Gas Town + return nil, "" // Not in a Gas Town } // Load routes from town beads townBeadsDir := filepath.Join(townRoot, ".beads") routes, err = LoadRoutes(townBeadsDir) if err != nil || len(routes) == 0 { - return nil, "", nil // No town routes + return nil, "" // No town routes } - return routes, townRoot, nil + return routes, townRoot } // resolveRedirect checks for a redirect file in the beads directory