diff --git a/cmd/analyze.go b/cmd/analyze.go index 56dbe9f2..72d3bd93 100644 --- a/cmd/analyze.go +++ b/cmd/analyze.go @@ -188,42 +188,33 @@ func getToolName(toolName string, version string) string { return toolName } -func runEslintAnalysis(workDirectory string, pathsToCheck []string, autoFix bool, outputFile string, outputFormat string) { +func runEslintAnalysis(workDirectory string, pathsToCheck []string, autoFix bool, outputFile string, outputFormat string) error { eslint := config.Config.Tools()["eslint"] eslintInstallationDirectory := eslint.InstallDir nodeRuntime := config.Config.Runtimes()["node"] nodeBinary := nodeRuntime.Binaries["node"] - tools.RunEslint(workDirectory, eslintInstallationDirectory, nodeBinary, pathsToCheck, autoFix, outputFile, outputFormat) + return tools.RunEslint(workDirectory, eslintInstallationDirectory, nodeBinary, pathsToCheck, autoFix, outputFile, outputFormat) } -func runTrivyAnalysis(workDirectory string, pathsToCheck []string, outputFile string, outputFormat string) { +func runTrivyAnalysis(workDirectory string, pathsToCheck []string, outputFile string, outputFormat string) error { trivy := config.Config.Tools()["trivy"] trivyBinary := trivy.Binaries["trivy"] - err := tools.RunTrivy(workDirectory, trivyBinary, pathsToCheck, outputFile, outputFormat) - if err != nil { - log.Fatalf("Error running Trivy: %v", err) - } + return tools.RunTrivy(workDirectory, trivyBinary, pathsToCheck, outputFile, outputFormat) } -func runPmdAnalysis(workDirectory string, pathsToCheck []string, outputFile string, outputFormat string) { +func runPmdAnalysis(workDirectory string, pathsToCheck []string, outputFile string, outputFormat string) error { pmd := config.Config.Tools()["pmd"] pmdBinary := pmd.Binaries["pmd"] - err := tools.RunPmd(workDirectory, pmdBinary, pathsToCheck, outputFile, outputFormat, config.Config) - if err != nil { - log.Fatalf("Error running PMD: %v", err) - } + return tools.RunPmd(workDirectory, pmdBinary, pathsToCheck, outputFile, outputFormat, config.Config) } -func runPylintAnalysis(workDirectory string, pathsToCheck []string, outputFile string, outputFormat string) { +func runPylintAnalysis(workDirectory string, pathsToCheck []string, outputFile string, outputFormat string) error { pylint := config.Config.Tools()["pylint"] - err := tools.RunPylint(workDirectory, pylint, pathsToCheck, outputFile, outputFormat) - if err != nil { - log.Fatalf("Error running Pylint: %v", err) - } + return tools.RunPylint(workDirectory, pylint, pathsToCheck, outputFile, outputFormat) } var analyzeCmd = &cobra.Command{ @@ -265,7 +256,9 @@ var analyzeCmd = &cobra.Command{ for toolName := range toolsToRun { log.Printf("Running %s...\n", toolName) tmpFile := filepath.Join(tmpDir, fmt.Sprintf("%s.sarif", toolName)) - runTool(workDirectory, toolName, args, tmpFile) + if err := runTool(workDirectory, toolName, args, tmpFile); err != nil { + log.Printf("Tool failed to run: %s: %v\n", toolName, err) + } sarifOutputs = append(sarifOutputs, tmpFile) } @@ -296,23 +289,25 @@ var analyzeCmd = &cobra.Command{ // Run tools without merging outputs for toolName := range toolsToRun { log.Printf("Running %s...\n", toolName) - runTool(workDirectory, toolName, args, outputFile) + if err := runTool(workDirectory, toolName, args, outputFile); err != nil { + log.Printf("Tool failed to run: %s: %v\n", toolName, err) + } } } }, } -func runTool(workDirectory string, toolName string, args []string, outputFile string) { +func runTool(workDirectory string, toolName string, args []string, outputFile string) error { switch toolName { case "eslint": - runEslintAnalysis(workDirectory, args, autoFix, outputFile, outputFormat) + return runEslintAnalysis(workDirectory, args, autoFix, outputFile, outputFormat) case "trivy": - runTrivyAnalysis(workDirectory, args, outputFile, outputFormat) + return runTrivyAnalysis(workDirectory, args, outputFile, outputFormat) case "pmd": - runPmdAnalysis(workDirectory, args, outputFile, outputFormat) + return runPmdAnalysis(workDirectory, args, outputFile, outputFormat) case "pylint": - runPylintAnalysis(workDirectory, args, outputFile, outputFormat) + return runPylintAnalysis(workDirectory, args, outputFile, outputFormat) default: - log.Printf("Warning: Unsupported tool: %s\n", toolName) + return fmt.Errorf("unsupported tool: %s", toolName) } } diff --git a/tools/eslintRunner.go b/tools/eslintRunner.go index 9e8314e0..f7212d6d 100644 --- a/tools/eslintRunner.go +++ b/tools/eslintRunner.go @@ -2,6 +2,7 @@ package tools import ( "codacy/cli-v2/config" + "fmt" "os" "os/exec" "path/filepath" @@ -10,7 +11,7 @@ import ( // * Run from the root of the repo we want to analyse // * NODE_PATH="/node_modules" // * The local installed ESLint should have the @microsoft/eslint-formatter-sarif installed -func RunEslint(repositoryToAnalyseDirectory string, eslintInstallationDirectory string, nodeBinary string, pathsToCheck []string, autoFix bool, outputFile string, outputFormat string) { +func RunEslint(repositoryToAnalyseDirectory string, eslintInstallationDirectory string, nodeBinary string, pathsToCheck []string, autoFix bool, outputFile string, outputFormat string) error { eslintInstallationNodeModules := filepath.Join(eslintInstallationDirectory, "node_modules") eslintJsPath := filepath.Join(eslintInstallationNodeModules, ".bin", "eslint") @@ -54,6 +55,14 @@ func RunEslint(repositoryToAnalyseDirectory string, eslintInstallationDirectory // fmt.Println(cmd.Env) // fmt.Println(cmd) - // TODO eslint returns 1 when it finds errors, so we're not propagating it - cmd.Run() + // Run the command and handle errors + err := cmd.Run() + if err != nil { + // ESLint returns 1 when it finds errors, which is not a failure + if exitErr, ok := err.(*exec.ExitError); ok && exitErr.ExitCode() == 1 { + return nil + } + return fmt.Errorf("failed to run ESLint: %w", err) + } + return nil } diff --git a/tools/pmdRunner.go b/tools/pmdRunner.go index 901d09d5..c59a2b0c 100644 --- a/tools/pmdRunner.go +++ b/tools/pmdRunner.go @@ -2,6 +2,7 @@ package tools import ( "codacy/cli-v2/config" + "fmt" "os" "os/exec" "strings" @@ -56,7 +57,7 @@ func RunPmd(repositoryToAnalyseDirectory string, pmdBinary string, pathsToCheck // Exit code 4 means violations found – treat as success return nil } - return err + return fmt.Errorf("failed to run PMD: %w", err) } return nil } diff --git a/tools/pylintRunner.go b/tools/pylintRunner.go index 5d907837..84cfecdf 100644 --- a/tools/pylintRunner.go +++ b/tools/pylintRunner.go @@ -59,7 +59,7 @@ func RunPylint(workDirectory string, toolInfo *plugins.ToolInfo, files []string, // Pylint returns non-zero exit code when it finds issues // We should not treat this as an error if _, ok := err.(*exec.ExitError); !ok { - return fmt.Errorf("failed to run pylint: %w", err) + return fmt.Errorf("failed to run Pylint: %w", err) } } diff --git a/tools/trivyRunner.go b/tools/trivyRunner.go index 8e8e3522..8f580553 100644 --- a/tools/trivyRunner.go +++ b/tools/trivyRunner.go @@ -2,6 +2,7 @@ package tools import ( "codacy/cli-v2/config" + "fmt" "os" "os/exec" ) @@ -35,5 +36,9 @@ func RunTrivy(repositoryToAnalyseDirectory string, trivyBinary string, pathsToCh cmd.Stderr = os.Stderr cmd.Stdout = os.Stdout - return cmd.Run() + err := cmd.Run() + if err != nil { + return fmt.Errorf("failed to run Trivy: %w", err) + } + return nil }