Skip to content

Commit 253ceac

Browse files
authored
Merge branch 'main' into feature/add-dartanalyzer
2 parents 371ffe3 + 054c857 commit 253ceac

File tree

8 files changed

+69
-43
lines changed

8 files changed

+69
-43
lines changed

README.md

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ To install `codacy-cli` using Homebrew:
4545
brew install codacy/codacy-cli-v2/codacy-cli-v2
4646
```
4747

48-
## Linux
48+
### Linux
4949

5050
For Linux, we rely on the codacy-cli.sh script in the root. To download the CLI, run:
5151

@@ -66,7 +66,7 @@ Before running the analysis, install the specified tools:
6666
codacy-cli install
6767
```
6868

69-
### Run Analysis
69+
## Run Analysis
7070

7171
To run ESLint and output the results to the terminal:
7272

@@ -102,6 +102,16 @@ Some behaviors have changed with the new updates of the CLI. To rely on a specif
102102
export CODACY_CLI_V2_VERSION="1.0.0-main.133.3607792"
103103
```
104104

105-
### Example Repository
105+
## Example Repository
106106

107107
As an example, you can check https://github.com/troubleshoot-codacy/eslint-test-examples for a repository that has an action relying on this CLI.
108+
109+
## Troubleshooting
110+
111+
#### Errors related to `docker-credential-osxkeychain` not found when running analysis
112+
113+
Install the docker credential helper. For example, in MacOS:
114+
115+
```bash
116+
brew install docker-credential-helper
117+
```

cmd/analyze.go

Lines changed: 21 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -188,42 +188,33 @@ func getToolName(toolName string, version string) string {
188188
return toolName
189189
}
190190

191-
func runEslintAnalysis(workDirectory string, pathsToCheck []string, autoFix bool, outputFile string, outputFormat string) {
191+
func runEslintAnalysis(workDirectory string, pathsToCheck []string, autoFix bool, outputFile string, outputFormat string) error {
192192
eslint := config.Config.Tools()["eslint"]
193193
eslintInstallationDirectory := eslint.InstallDir
194194
nodeRuntime := config.Config.Runtimes()["node"]
195195
nodeBinary := nodeRuntime.Binaries["node"]
196196

197-
tools.RunEslint(workDirectory, eslintInstallationDirectory, nodeBinary, pathsToCheck, autoFix, outputFile, outputFormat)
197+
return tools.RunEslint(workDirectory, eslintInstallationDirectory, nodeBinary, pathsToCheck, autoFix, outputFile, outputFormat)
198198
}
199199

200-
func runTrivyAnalysis(workDirectory string, pathsToCheck []string, outputFile string, outputFormat string) {
200+
func runTrivyAnalysis(workDirectory string, pathsToCheck []string, outputFile string, outputFormat string) error {
201201
trivy := config.Config.Tools()["trivy"]
202202
trivyBinary := trivy.Binaries["trivy"]
203203

204-
err := tools.RunTrivy(workDirectory, trivyBinary, pathsToCheck, outputFile, outputFormat)
205-
if err != nil {
206-
log.Fatalf("Error running Trivy: %v", err)
207-
}
204+
return tools.RunTrivy(workDirectory, trivyBinary, pathsToCheck, outputFile, outputFormat)
208205
}
209206

210-
func runPmdAnalysis(workDirectory string, pathsToCheck []string, outputFile string, outputFormat string) {
207+
func runPmdAnalysis(workDirectory string, pathsToCheck []string, outputFile string, outputFormat string) error {
211208
pmd := config.Config.Tools()["pmd"]
212209
pmdBinary := pmd.Binaries["pmd"]
213210

214-
err := tools.RunPmd(workDirectory, pmdBinary, pathsToCheck, outputFile, outputFormat, config.Config)
215-
if err != nil {
216-
log.Fatalf("Error running PMD: %v", err)
217-
}
211+
return tools.RunPmd(workDirectory, pmdBinary, pathsToCheck, outputFile, outputFormat, config.Config)
218212
}
219213

220-
func runPylintAnalysis(workDirectory string, pathsToCheck []string, outputFile string, outputFormat string) {
214+
func runPylintAnalysis(workDirectory string, pathsToCheck []string, outputFile string, outputFormat string) error {
221215
pylint := config.Config.Tools()["pylint"]
222216

223-
err := tools.RunPylint(workDirectory, pylint, pathsToCheck, outputFile, outputFormat)
224-
if err != nil {
225-
log.Fatalf("Error running Pylint: %v", err)
226-
}
217+
return tools.RunPylint(workDirectory, pylint, pathsToCheck, outputFile, outputFormat)
227218
}
228219

229220
func runDartAnalyzer(workDirectory string, pathsToCheck []string, outputFile string, outputFormat string) {
@@ -273,7 +264,9 @@ var analyzeCmd = &cobra.Command{
273264
for toolName := range toolsToRun {
274265
log.Printf("Running %s...\n", toolName)
275266
tmpFile := filepath.Join(tmpDir, fmt.Sprintf("%s.sarif", toolName))
276-
runTool(workDirectory, toolName, args, tmpFile)
267+
if err := runTool(workDirectory, toolName, args, tmpFile); err != nil {
268+
log.Printf("Tool failed to run: %s: %v\n", toolName, err)
269+
}
277270
sarifOutputs = append(sarifOutputs, tmpFile)
278271
}
279272

@@ -304,25 +297,27 @@ var analyzeCmd = &cobra.Command{
304297
// Run tools without merging outputs
305298
for toolName := range toolsToRun {
306299
log.Printf("Running %s...\n", toolName)
307-
runTool(workDirectory, toolName, args, outputFile)
300+
if err := runTool(workDirectory, toolName, args, outputFile); err != nil {
301+
log.Printf("Tool failed to run: %s: %v\n", toolName, err)
302+
}
308303
}
309304
}
310305
},
311306
}
312307

313-
func runTool(workDirectory string, toolName string, args []string, outputFile string) {
308+
func runTool(workDirectory string, toolName string, args []string, outputFile string) error {
314309
switch toolName {
315310
case "eslint":
316-
runEslintAnalysis(workDirectory, args, autoFix, outputFile, outputFormat)
311+
return runEslintAnalysis(workDirectory, args, autoFix, outputFile, outputFormat)
317312
case "trivy":
318-
runTrivyAnalysis(workDirectory, args, outputFile, outputFormat)
313+
return runTrivyAnalysis(workDirectory, args, outputFile, outputFormat)
319314
case "pmd":
320-
runPmdAnalysis(workDirectory, args, outputFile, outputFormat)
315+
return runPmdAnalysis(workDirectory, args, outputFile, outputFormat)
321316
case "pylint":
322-
runPylintAnalysis(workDirectory, args, outputFile, outputFormat)
317+
return runPylintAnalysis(workDirectory, args, outputFile, outputFormat)
323318
case "dartanalyzer":
324-
runDartAnalyzer(workDirectory, args, outputFile, outputFormat)
319+
return runDartAnalyzer(workDirectory, args, outputFile, outputFormat)
325320
default:
326-
log.Printf("Warning: Unsupported tool: %s\n", toolName)
321+
return fmt.Errorf("unsupported tool: %s", toolName)
327322
}
328323
}

cmd/root.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ func getExampleText() string {
7474

7575
func init() {
7676
// Add global flags here
77-
rootCmd.PersistentFlags().StringP("config", "c", filepath.Join(".codacy", "codacy.yaml"), "config file")
77+
rootCmd.PersistentFlags().String("config", filepath.Join(".codacy", "codacy.yaml"), "config file")
7878

7979
// Customize help template
8080
rootCmd.SetUsageTemplate(`

tools/eslintRunner.go

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package tools
22

33
import (
44
"codacy/cli-v2/config"
5+
"fmt"
56
"os"
67
"os/exec"
78
"path/filepath"
@@ -10,18 +11,18 @@ import (
1011
// * Run from the root of the repo we want to analyse
1112
// * NODE_PATH="<the installed eslint path>/node_modules"
1213
// * The local installed ESLint should have the @microsoft/eslint-formatter-sarif installed
13-
func RunEslint(repositoryToAnalyseDirectory string, eslintInstallationDirectory string, nodeBinary string, pathsToCheck []string, autoFix bool, outputFile string, outputFormat string) {
14+
func RunEslint(repositoryToAnalyseDirectory string, eslintInstallationDirectory string, nodeBinary string, pathsToCheck []string, autoFix bool, outputFile string, outputFormat string) error {
1415
eslintInstallationNodeModules := filepath.Join(eslintInstallationDirectory, "node_modules")
1516
eslintJsPath := filepath.Join(eslintInstallationNodeModules, ".bin", "eslint")
1617

1718
cmd := exec.Command(nodeBinary, eslintJsPath)
1819

19-
// For Eslint compatibility with version 8.
20-
// https://eslint.org/docs/v8.x/use/configure/configuration-files-new
21-
cmd.Env = append(cmd.Env, "ESLINT_USE_FLAT_CONFIG=true")
22-
2320
// Add config file from tools-configs directory if it exists
2421
if configFile, exists := ConfigFileExists(config.Config, "eslint.config.mjs"); exists {
22+
// For Eslint compatibility with version 8.
23+
// https://eslint.org/docs/v8.x/use/configure/configuration-files-new
24+
cmd.Env = append(cmd.Env, "ESLINT_USE_FLAT_CONFIG=true")
25+
2526
cmd.Args = append(cmd.Args, "-c", configFile)
2627
}
2728

@@ -54,6 +55,14 @@ func RunEslint(repositoryToAnalyseDirectory string, eslintInstallationDirectory
5455
// fmt.Println(cmd.Env)
5556
// fmt.Println(cmd)
5657

57-
// TODO eslint returns 1 when it finds errors, so we're not propagating it
58-
cmd.Run()
58+
// Run the command and handle errors
59+
err := cmd.Run()
60+
if err != nil {
61+
// ESLint returns 1 when it finds errors, which is not a failure
62+
if exitErr, ok := err.(*exec.ExitError); ok && exitErr.ExitCode() == 1 {
63+
return nil
64+
}
65+
return fmt.Errorf("failed to run ESLint: %w", err)
66+
}
67+
return nil
5968
}

tools/pmdRunner.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package tools
22

33
import (
44
"codacy/cli-v2/config"
5+
"fmt"
56
"os"
67
"os/exec"
78
"strings"
@@ -56,7 +57,7 @@ func RunPmd(repositoryToAnalyseDirectory string, pmdBinary string, pathsToCheck
5657
// Exit code 4 means violations found – treat as success
5758
return nil
5859
}
59-
return err
60+
return fmt.Errorf("failed to run PMD: %w", err)
6061
}
6162
return nil
6263
}

tools/pylintRunner.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ func RunPylint(workDirectory string, toolInfo *plugins.ToolInfo, files []string,
5959
// Pylint returns non-zero exit code when it finds issues
6060
// We should not treat this as an error
6161
if _, ok := err.(*exec.ExitError); !ok {
62-
return fmt.Errorf("failed to run pylint: %w", err)
62+
return fmt.Errorf("failed to run Pylint: %w", err)
6363
}
6464
}
6565

tools/trivyRunner.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package tools
22

33
import (
44
"codacy/cli-v2/config"
5+
"fmt"
56
"os"
67
"os/exec"
78
)
@@ -35,5 +36,9 @@ func RunTrivy(repositoryToAnalyseDirectory string, trivyBinary string, pathsToCh
3536
cmd.Stderr = os.Stderr
3637
cmd.Stdout = os.Stdout
3738

38-
return cmd.Run()
39+
err := cmd.Run()
40+
if err != nil {
41+
return fmt.Errorf("failed to run Trivy: %w", err)
42+
}
43+
return nil
3944
}

utils/sarif.go

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -181,12 +181,18 @@ func createEmptySarifReport() []byte {
181181
return sarifData
182182
}
183183

184+
type SimpleSarifReport struct {
185+
Version string `json:"version"`
186+
Schema string `json:"$schema"`
187+
Runs []json.RawMessage `json:"runs"`
188+
}
189+
184190
// MergeSarifOutputs combines multiple SARIF files into a single output file
185191
func MergeSarifOutputs(inputFiles []string, outputFile string) error {
186-
var mergedSarif SarifReport
192+
var mergedSarif SimpleSarifReport
187193
mergedSarif.Version = "2.1.0"
188194
mergedSarif.Schema = "https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json"
189-
mergedSarif.Runs = make([]Run, 0)
195+
mergedSarif.Runs = make([]json.RawMessage, 0)
190196

191197
for _, file := range inputFiles {
192198
data, err := os.ReadFile(file)
@@ -198,7 +204,7 @@ func MergeSarifOutputs(inputFiles []string, outputFile string) error {
198204
return fmt.Errorf("failed to read SARIF file %s: %w", file, err)
199205
}
200206

201-
var sarif SarifReport
207+
var sarif SimpleSarifReport
202208
if err := json.Unmarshal(data, &sarif); err != nil {
203209
return fmt.Errorf("failed to parse SARIF file %s: %w", file, err)
204210
}

0 commit comments

Comments
 (0)