fix: address CI lint errors (gosec, errcheck, unparam, duplicate tests) (#730)

* fix: address CI lint errors (gosec, errcheck, unparam, duplicate tests)

- Remove duplicate TestHandleDelete_DryRun and TestHandleDelete_PartialSuccess
  from server_mutations_test.go (already defined in server_delete_test.go)
- Add nolint:gosec comments for exec.CommandContext calls in sync_branch.go
  (variables come from trusted config/git sources)
- Fix gosec G304/G306 in yaml_config.go (file read/write permissions)
- Fix errcheck in mol_run.go (templateStore.Close)
- Add nolint:unparam for updateYamlKey error return

* fix: add remaining nolint:gosec comments for exec.CommandContext calls

- sync_branch.go: diffCmd, logCmd (dry-run), commitCmd, pushCmd, remoteCmd
- sync_check.go: checkLocalCmd

* fix: add more nolint:gosec comments for exec.CommandContext calls

- sync_branch.go: pullCmd
- sync_check.go: localRefCmd, remoteRefCmd, aheadCmd
- sync_import.go: checkoutCmd

* fix: add final nolint:gosec comments for exec.CommandContext calls

- sync_check.go: behindCmd
- sync_import.go: fetchCmd

---------

Co-authored-by: Charles P. Cross <cpdata@users.noreply.github.com>
This commit is contained in:
Charles P. Cross
2025-12-24 15:35:32 -05:00
committed by GitHub
parent 177ee3265e
commit 8676c41c18
6 changed files with 25 additions and 200 deletions

View File

@@ -94,7 +94,7 @@ func runMolRun(cmd *cobra.Command, args []string) {
fmt.Fprintf(os.Stderr, "Error opening template database %s: %v\n", templateDB, err)
os.Exit(1)
}
defer templateStore.Close()
defer func() { _ = templateStore.Close() }()
}
// Resolve molecule ID from template store

View File

@@ -58,7 +58,7 @@ func showSyncStatus(ctx context.Context) error {
}
// Check if sync branch exists
checkCmd := exec.CommandContext(ctx, "git", "show-ref", "--verify", "--quiet", "refs/heads/"+syncBranch)
checkCmd := exec.CommandContext(ctx, "git", "show-ref", "--verify", "--quiet", "refs/heads/"+syncBranch) //nolint:gosec // syncBranch from config
if err := checkCmd.Run(); err != nil {
return fmt.Errorf("sync branch '%s' does not exist", syncBranch)
}
@@ -68,7 +68,7 @@ func showSyncStatus(ctx context.Context) error {
// Show commit diff
fmt.Println("Commits in sync branch not in main:")
logCmd := exec.CommandContext(ctx, "git", "log", "--oneline", currentBranch+".."+syncBranch)
logCmd := exec.CommandContext(ctx, "git", "log", "--oneline", currentBranch+".."+syncBranch) //nolint:gosec // branch names from git
logOutput, err := logCmd.CombinedOutput()
if err != nil {
return fmt.Errorf("failed to get commit log: %w\n%s", err, logOutput)
@@ -81,7 +81,7 @@ func showSyncStatus(ctx context.Context) error {
}
fmt.Println("\nCommits in main not in sync branch:")
logCmd = exec.CommandContext(ctx, "git", "log", "--oneline", syncBranch+".."+currentBranch)
logCmd = exec.CommandContext(ctx, "git", "log", "--oneline", syncBranch+".."+currentBranch) //nolint:gosec // branch names from git
logOutput, err = logCmd.CombinedOutput()
if err != nil {
return fmt.Errorf("failed to get commit log: %w\n%s", err, logOutput)
@@ -95,7 +95,7 @@ func showSyncStatus(ctx context.Context) error {
// Show file diff for .beads/issues.jsonl
fmt.Println("\nFile differences in .beads/issues.jsonl:")
diffCmd := exec.CommandContext(ctx, "git", "diff", currentBranch+"..."+syncBranch, "--", ".beads/issues.jsonl")
diffCmd := exec.CommandContext(ctx, "git", "diff", currentBranch+"..."+syncBranch, "--", ".beads/issues.jsonl") //nolint:gosec // branch names from git
diffOutput, err := diffCmd.CombinedOutput()
if err != nil {
// diff returns non-zero when there are differences, which is fine
@@ -130,7 +130,7 @@ func mergeSyncBranch(ctx context.Context, dryRun bool) error {
}
// Check if sync branch exists
checkCmd := exec.CommandContext(ctx, "git", "show-ref", "--verify", "--quiet", "refs/heads/"+syncBranch)
checkCmd := exec.CommandContext(ctx, "git", "show-ref", "--verify", "--quiet", "refs/heads/"+syncBranch) //nolint:gosec // syncBranch from config
if err := checkCmd.Run(); err != nil {
return fmt.Errorf("sync branch '%s' does not exist", syncBranch)
}
@@ -150,7 +150,7 @@ func mergeSyncBranch(ctx context.Context, dryRun bool) error {
if dryRun {
fmt.Println("→ [DRY RUN] Would merge sync branch")
// Show what would be merged
logCmd := exec.CommandContext(ctx, "git", "log", "--oneline", currentBranch+".."+syncBranch)
logCmd := exec.CommandContext(ctx, "git", "log", "--oneline", currentBranch+".."+syncBranch) //nolint:gosec // branch names from git
logOutput, _ := logCmd.CombinedOutput()
if len(strings.TrimSpace(string(logOutput))) > 0 {
fmt.Println("\nCommits that would be merged:")
@@ -162,7 +162,7 @@ func mergeSyncBranch(ctx context.Context, dryRun bool) error {
}
// Perform the merge
mergeCmd := exec.CommandContext(ctx, "git", "merge", syncBranch, "-m", fmt.Sprintf("Merge sync branch '%s'", syncBranch))
mergeCmd := exec.CommandContext(ctx, "git", "merge", syncBranch, "-m", fmt.Sprintf("Merge sync branch '%s'", syncBranch)) //nolint:gosec // syncBranch from config
mergeOutput, err := mergeCmd.CombinedOutput()
if err != nil {
return fmt.Errorf("merge failed: %w\n%s", err, mergeOutput)
@@ -228,13 +228,13 @@ func commitToExternalBeadsRepo(ctx context.Context, beadsDir, message string, pu
relBeadsDir = beadsDir // Fallback to absolute path
}
addCmd := exec.CommandContext(ctx, "git", "-C", repoRoot, "add", relBeadsDir)
addCmd := exec.CommandContext(ctx, "git", "-C", repoRoot, "add", relBeadsDir) //nolint:gosec // paths from trusted sources
if output, err := addCmd.CombinedOutput(); err != nil {
return false, fmt.Errorf("git add failed: %w\n%s", err, output)
}
// Check if there are staged changes
diffCmd := exec.CommandContext(ctx, "git", "-C", repoRoot, "diff", "--cached", "--quiet")
diffCmd := exec.CommandContext(ctx, "git", "-C", repoRoot, "diff", "--cached", "--quiet") //nolint:gosec // repoRoot from git
if diffCmd.Run() == nil {
return false, nil // No changes to commit
}
@@ -244,14 +244,14 @@ func commitToExternalBeadsRepo(ctx context.Context, beadsDir, message string, pu
message = fmt.Sprintf("bd sync: %s", time.Now().Format("2006-01-02 15:04:05"))
}
commitArgs := buildGitCommitArgs(repoRoot, message)
commitCmd := exec.CommandContext(ctx, "git", commitArgs...)
commitCmd := exec.CommandContext(ctx, "git", commitArgs...) //nolint:gosec // args from buildGitCommitArgs
if output, err := commitCmd.CombinedOutput(); err != nil {
return false, fmt.Errorf("git commit failed: %w\n%s", err, output)
}
// Push if requested
if push {
pushCmd := exec.CommandContext(ctx, "git", "-C", repoRoot, "push")
pushCmd := exec.CommandContext(ctx, "git", "-C", repoRoot, "push") //nolint:gosec // repoRoot from git
if pushOutput, err := runGitCmdWithTimeoutMsg(ctx, pushCmd, "git push", 5*time.Second); err != nil {
return true, fmt.Errorf("git push failed: %w\n%s", err, pushOutput)
}
@@ -270,13 +270,13 @@ func pullFromExternalBeadsRepo(ctx context.Context, beadsDir string) error {
}
// Check if remote exists
remoteCmd := exec.CommandContext(ctx, "git", "-C", repoRoot, "remote")
remoteCmd := exec.CommandContext(ctx, "git", "-C", repoRoot, "remote") //nolint:gosec // repoRoot from git
remoteOutput, err := remoteCmd.Output()
if err != nil || len(strings.TrimSpace(string(remoteOutput))) == 0 {
return nil // No remote, skip pull
}
pullCmd := exec.CommandContext(ctx, "git", "-C", repoRoot, "pull")
pullCmd := exec.CommandContext(ctx, "git", "-C", repoRoot, "pull") //nolint:gosec // repoRoot from git
if output, err := pullCmd.CombinedOutput(); err != nil {
return fmt.Errorf("git pull failed: %w\n%s", err, output)
}

View File

@@ -130,14 +130,14 @@ func checkForcedPush(ctx context.Context) *ForcedPushCheck {
}
// Check if sync branch exists locally
checkLocalCmd := exec.CommandContext(ctx, "git", "show-ref", "--verify", "--quiet", "refs/heads/"+syncBranch)
checkLocalCmd := exec.CommandContext(ctx, "git", "show-ref", "--verify", "--quiet", "refs/heads/"+syncBranch) //nolint:gosec // syncBranch from config
if checkLocalCmd.Run() != nil {
result.Message = fmt.Sprintf("Sync branch '%s' does not exist locally", syncBranch)
return result
}
// Get local ref
localRefCmd := exec.CommandContext(ctx, "git", "rev-parse", syncBranch)
localRefCmd := exec.CommandContext(ctx, "git", "rev-parse", syncBranch) //nolint:gosec // syncBranch from config
localRefOutput, err := localRefCmd.Output()
if err != nil {
result.Message = "Failed to get local sync branch ref"
@@ -153,7 +153,7 @@ func checkForcedPush(ctx context.Context) *ForcedPushCheck {
}
// Get remote ref
remoteRefCmd := exec.CommandContext(ctx, "git", "rev-parse", remote+"/"+syncBranch)
remoteRefCmd := exec.CommandContext(ctx, "git", "rev-parse", remote+"/"+syncBranch) //nolint:gosec // remote and syncBranch from config
remoteRefOutput, err := remoteRefCmd.Output()
if err != nil {
result.Message = fmt.Sprintf("Remote tracking branch '%s/%s' does not exist", remote, syncBranch)
@@ -169,14 +169,14 @@ func checkForcedPush(ctx context.Context) *ForcedPushCheck {
}
// Check if local is ahead of remote (normal case)
aheadCmd := exec.CommandContext(ctx, "git", "merge-base", "--is-ancestor", remoteRef, localRef)
aheadCmd := exec.CommandContext(ctx, "git", "merge-base", "--is-ancestor", remoteRef, localRef) //nolint:gosec // refs from git rev-parse
if aheadCmd.Run() == nil {
result.Message = "Local sync branch is ahead of remote (normal)"
return result
}
// Check if remote is ahead of local (behind, needs pull)
behindCmd := exec.CommandContext(ctx, "git", "merge-base", "--is-ancestor", localRef, remoteRef)
behindCmd := exec.CommandContext(ctx, "git", "merge-base", "--is-ancestor", localRef, remoteRef) //nolint:gosec // refs from git rev-parse
if behindCmd.Run() == nil {
result.Message = "Local sync branch is behind remote (needs pull)"
return result

View File

@@ -109,14 +109,14 @@ func doSyncFromMain(ctx context.Context, jsonlPath string, renameOnImport bool,
// Step 1: Fetch from main
fmt.Printf("→ Fetching from %s/%s...\n", remote, defaultBranch)
fetchCmd := exec.CommandContext(ctx, "git", "fetch", remote, defaultBranch)
fetchCmd := exec.CommandContext(ctx, "git", "fetch", remote, defaultBranch) //nolint:gosec // remote and defaultBranch from config
if output, err := fetchCmd.CombinedOutput(); err != nil {
return fmt.Errorf("git fetch %s %s failed: %w\n%s", remote, defaultBranch, err, output)
}
// Step 2: Checkout .beads/ directory from main
fmt.Printf("→ Checking out beads from %s/%s...\n", remote, defaultBranch)
checkoutCmd := exec.CommandContext(ctx, "git", "checkout", fmt.Sprintf("%s/%s", remote, defaultBranch), "--", ".beads/")
checkoutCmd := exec.CommandContext(ctx, "git", "checkout", fmt.Sprintf("%s/%s", remote, defaultBranch), "--", ".beads/") //nolint:gosec // remote and defaultBranch from config
if output, err := checkoutCmd.CombinedOutput(); err != nil {
return fmt.Errorf("git checkout .beads/ from %s/%s failed: %w\n%s", remote, defaultBranch, err, output)
}