Skip to content

Commit e8fada6

Browse files
wip
2 parents ed511ef + 93219d2 commit e8fada6

File tree

9 files changed

+143
-36
lines changed

9 files changed

+143
-36
lines changed

.codacy/cli-config.yaml

Lines changed: 0 additions & 1 deletion
This file was deleted.

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,4 +24,5 @@ go.work.sum
2424
.idea/
2525
.vscode/
2626

27-
cli-v2
27+
# Codacy CLI
28+
cli-v2

cmd/analyze.go

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ var outputFormat string
2020
var sarifPath string
2121
var commitUuid string
2222
var projectToken string
23-
var pmdRulesetFile string
2423

2524
type Sarif struct {
2625
Runs []struct {
@@ -96,7 +95,6 @@ func init() {
9695
analyzeCmd.Flags().StringVarP(&toolToAnalyze, "tool", "t", "", "Which tool to run analysis with")
9796
analyzeCmd.Flags().StringVar(&outputFormat, "format", "", "Output format (use 'sarif' for SARIF format)")
9897
analyzeCmd.Flags().BoolVar(&autoFix, "fix", false, "Apply auto fix to your issues when available")
99-
analyzeCmd.Flags().StringVar(&pmdRulesetFile, "rulesets", "", "Path to PMD ruleset file")
10098
rootCmd.AddCommand(analyzeCmd)
10199
}
102100

@@ -209,7 +207,7 @@ func runPmdAnalysis(workDirectory string, pathsToCheck []string, outputFile stri
209207
pmd := config.Config.Tools()["pmd"]
210208
pmdBinary := pmd.Binaries["pmd"]
211209

212-
err := tools.RunPmd(workDirectory, pmdBinary, pathsToCheck, outputFile, outputFormat, pmdRulesetFile)
210+
err := tools.RunPmd(workDirectory, pmdBinary, pathsToCheck, outputFile, outputFormat, "")
213211
if err != nil {
214212
log.Fatalf("Error running PMD: %v", err)
215213
}

cmd/init.go

Lines changed: 59 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,15 @@ import (
44
"codacy/cli-v2/config"
55
"codacy/cli-v2/domain"
66
"codacy/cli-v2/tools"
7+
"codacy/cli-v2/utils"
78
"encoding/json"
89
"errors"
910
"fmt"
1011
"io"
1112
"log"
1213
"net/http"
1314
"os"
15+
"path/filepath"
1416
"time"
1517

1618
"github.com/spf13/cobra"
@@ -53,6 +55,7 @@ var initCmd = &cobra.Command{
5355
if err != nil {
5456
log.Fatal(err)
5557
}
58+
createGitIgnoreFile()
5659
}
5760
fmt.Println()
5861
fmt.Println("✅ Successfully initialized Codacy configuration!")
@@ -64,6 +67,26 @@ var initCmd = &cobra.Command{
6467
},
6568
}
6669

70+
func createGitIgnoreFile() error {
71+
gitIgnorePath := filepath.Join(config.Config.LocalCodacyDirectory(), ".gitignore")
72+
gitIgnoreFile, err := os.Create(gitIgnorePath)
73+
if err != nil {
74+
return fmt.Errorf("failed to create .gitignore file: %w", err)
75+
}
76+
defer gitIgnoreFile.Close()
77+
78+
content := `# Codacy CLI
79+
tools-configs/
80+
.gitignore
81+
cli-config.yaml
82+
`
83+
if _, err := gitIgnoreFile.WriteString(content); err != nil {
84+
return fmt.Errorf("failed to write to .gitignore file: %w", err)
85+
}
86+
87+
return nil
88+
}
89+
6790
func createConfigurationFiles(tools []tools.Tool, cliLocalMode bool) error {
6891
configFile, err := os.Create(config.Config.ProjectConfigFile())
6992
defer configFile.Close()
@@ -137,6 +160,13 @@ func cliConfigFileTemplate(cliLocalMode bool) string {
137160
func buildRepositoryConfigurationFiles(token string) error {
138161
fmt.Println("Fetching repository configuration from codacy using api token ...")
139162

163+
toolsConfigDir := config.Config.ToolsConfigDirectory()
164+
165+
// Create tools-configs directory if it doesn't exist
166+
if err := os.MkdirAll(toolsConfigDir, utils.DefaultDirPerms); err != nil {
167+
return fmt.Errorf("failed to create tools-configs directory: %w", err)
168+
}
169+
140170
client := &http.Client{
141171
Timeout: 10 * time.Second,
142172
}
@@ -212,12 +242,13 @@ func buildRepositoryConfigurationFiles(token string) error {
212242

213243
// map tool uuid to tool name
214244
func createToolFileConfigurations(tool tools.Tool, patternConfiguration []domain.PatternConfiguration) error {
245+
toolsConfigDir := config.Config.ToolsConfigDirectory()
215246
switch tool.Uuid {
216247
case ESLint:
217248
if len(patternConfiguration) > 0 {
218249
eslintConfigurationString := tools.CreateEslintConfig(patternConfiguration)
219250

220-
eslintConfigFile, err := os.Create("eslint.config.mjs")
251+
eslintConfigFile, err := os.Create(filepath.Join(toolsConfigDir, "eslint.config.mjs"))
221252
if err != nil {
222253
return fmt.Errorf("failed to create eslint config file: %v", err)
223254
}
@@ -229,67 +260,79 @@ func createToolFileConfigurations(tool tools.Tool, patternConfiguration []domain
229260
}
230261
fmt.Println("ESLint configuration created based on Codacy settings")
231262
} else {
232-
err := createDefaultEslintConfigFile()
263+
err := createDefaultEslintConfigFile(toolsConfigDir)
233264
if err != nil {
234265
return fmt.Errorf("failed to create default ESLint config: %v", err)
235266
}
236267
fmt.Println("Default ESLint configuration created")
237268
}
238269
case Trivy:
239270
if len(patternConfiguration) > 0 {
240-
createTrivyConfigFile(patternConfiguration)
271+
err := createTrivyConfigFile(patternConfiguration, toolsConfigDir)
272+
if err != nil {
273+
return fmt.Errorf("failed to create Trivy config: %v", err)
274+
}
241275
} else {
242-
createDefaultTrivyConfigFile()
276+
err := createDefaultTrivyConfigFile(toolsConfigDir)
277+
if err != nil {
278+
return fmt.Errorf("failed to create default Trivy config: %v", err)
279+
}
243280
}
244281
fmt.Println("Trivy configuration created based on Codacy settings")
245282
case PMD:
246283
if len(patternConfiguration) > 0 {
247-
createPMDConfigFile(patternConfiguration)
284+
err := createPMDConfigFile(patternConfiguration, toolsConfigDir)
285+
if err != nil {
286+
return fmt.Errorf("failed to create PMD config: %v", err)
287+
}
248288
} else {
249-
createDefaultPMDConfigFile()
289+
err := createDefaultPMDConfigFile(toolsConfigDir)
290+
if err != nil {
291+
return fmt.Errorf("failed to create default PMD config: %v", err)
292+
}
250293
}
251294
fmt.Println("PMD configuration created based on Codacy settings")
252295
}
253296
return nil
254297
}
255298

256-
func createPMDConfigFile(config []domain.PatternConfiguration) error {
299+
func createPMDConfigFile(config []domain.PatternConfiguration, toolsConfigDir string) error {
257300
pmdConfigurationString := tools.CreatePmdConfig(config)
258-
return os.WriteFile("pmd-ruleset.xml", []byte(pmdConfigurationString), 0644)
301+
return os.WriteFile(filepath.Join(toolsConfigDir, "pmd-ruleset.xml"), []byte(pmdConfigurationString), utils.DefaultRW)
259302
}
260303

261-
func createDefaultPMDConfigFile() error {
304+
func createDefaultPMDConfigFile(toolsConfigDir string) error {
262305
content := tools.CreatePmdConfig([]domain.PatternConfiguration{})
263-
return os.WriteFile("pmd-ruleset.xml", []byte(content), 0644)
306+
return os.WriteFile(filepath.Join(toolsConfigDir, "pmd-ruleset.xml"), []byte(content), utils.DefaultRW)
264307
}
265308

266309
// createTrivyConfigFile creates a trivy.yaml configuration file based on the API configuration
267-
func createTrivyConfigFile(config []domain.PatternConfiguration) error {
310+
func createTrivyConfigFile(config []domain.PatternConfiguration, toolsConfigDir string) error {
268311

269312
trivyConfigurationString := tools.CreateTrivyConfig(config)
270313

271314
// Write to file
272-
return os.WriteFile("trivy.yaml", []byte(trivyConfigurationString), 0644)
315+
return os.WriteFile(filepath.Join(toolsConfigDir, "trivy.yaml"), []byte(trivyConfigurationString), utils.DefaultRW)
273316
}
274317

275318
// createDefaultTrivyConfigFile creates a default trivy.yaml configuration file
276-
func createDefaultTrivyConfigFile() error {
319+
func createDefaultTrivyConfigFile(toolsConfigDir string) error {
277320
// Use empty tool configuration to get default settings
278321
emptyConfig := []domain.PatternConfiguration{}
279322
content := tools.CreateTrivyConfig(emptyConfig)
280323

281324
// Write to file
282-
return os.WriteFile("trivy.yaml", []byte(content), 0644)
325+
return os.WriteFile(filepath.Join(toolsConfigDir, "trivy.yaml"), []byte(content), utils.DefaultRW)
283326
}
284327

285328
// createDefaultEslintConfigFile creates a default eslint.config.mjs configuration file
286-
func createDefaultEslintConfigFile() error {
329+
func createDefaultEslintConfigFile(toolsConfigDir string) error {
287330
// Use empty tool configuration to get default settings
288331
emptyConfig := []domain.PatternConfiguration{}
289332
content := tools.CreateEslintConfig(emptyConfig)
290333

291334
// Write to file
292-
return os.WriteFile("eslint.config.mjs", []byte(content), 0644)
335+
return os.WriteFile(filepath.Join(toolsConfigDir, "eslint.config.mjs"), []byte(content), utils.DefaultRW)
293336
}
294337

295338
const (

config/config.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ type ConfigType struct {
1515
runtimesDirectory string
1616
toolsDirectory string
1717
localCodacyDirectory string
18+
toolsConfigDirectory string
1819
projectConfigFile string
1920
cliConfigFile string
2021

@@ -42,6 +43,10 @@ func (c *ConfigType) LocalCodacyDirectory() string {
4243
return c.localCodacyDirectory
4344
}
4445

46+
func (c *ConfigType) ToolsConfigsDirectory() string {
47+
return c.toolsConfigDirectory
48+
}
49+
4550
func (c *ConfigType) ProjectConfigFile() string {
4651
return c.projectConfigFile
4752
}
@@ -88,11 +93,16 @@ func (c *ConfigType) AddTools(configs []plugins.ToolConfig) error {
8893
return nil
8994
}
9095

96+
func (c *ConfigType) ToolsConfigDirectory() string {
97+
return c.toolsConfigDirectory
98+
}
99+
91100
func (c *ConfigType) setupCodacyPaths() {
92101
c.globalCacheDirectory = filepath.Join(c.homePath, ".cache", "codacy")
93102
c.runtimesDirectory = filepath.Join(c.globalCacheDirectory, "runtimes")
94103
c.toolsDirectory = filepath.Join(c.globalCacheDirectory, "tools")
95104
c.localCodacyDirectory = ".codacy"
105+
c.toolsConfigDirectory = filepath.Join(c.localCodacyDirectory, "tools-configs")
96106

97107
c.projectConfigFile = filepath.Join(c.localCodacyDirectory, "codacy.yaml")
98108
c.cliConfigFile = filepath.Join(c.localCodacyDirectory, "cli-config.yaml")

tools/eslintRunner.go

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package tools
22

33
import (
4+
"codacy/cli-v2/config"
45
"os"
56
"os/exec"
67
"path/filepath"
@@ -14,6 +15,15 @@ func RunEslint(repositoryToAnalyseDirectory string, eslintInstallationDirectory
1415
eslintJsPath := filepath.Join(eslintInstallationNodeModules, ".bin", "eslint")
1516

1617
cmd := exec.Command(nodeBinary, eslintJsPath)
18+
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+
23+
// Add config file from tools-configs directory
24+
configFile := filepath.Join(config.Config.ToolsConfigDirectory(), "eslint.config.mjs")
25+
cmd.Args = append(cmd.Args, "-c", configFile)
26+
1727
if autoFix {
1828
cmd.Args = append(cmd.Args, "--fix")
1929
}
@@ -39,9 +49,9 @@ func RunEslint(repositoryToAnalyseDirectory string, eslintInstallationDirectory
3949
nodePathEnv := "NODE_PATH=" + eslintInstallationNodeModules
4050
cmd.Env = append(cmd.Env, nodePathEnv)
4151

42-
//DEBUG
43-
//fmt.Println(cmd.Env)
44-
//fmt.Println(cmd)
52+
// DEBUG
53+
// fmt.Println(cmd.Env)
54+
// fmt.Println(cmd)
4555

4656
// TODO eslint returns 1 when it finds errors, so we're not propagating it
4757
cmd.Run()

tools/pmdRunner.go

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,55 @@
11
package tools
22

33
import (
4+
"codacy/cli-v2/config"
45
"os"
56
"os/exec"
7+
"path/filepath"
68
"strings"
79
)
810

911
// RunPmd executes PMD static code analyzer with the specified options
12+
//
13+
// Parameters:
14+
// - repositoryToAnalyseDirectory: The root directory of the repository to analyze
15+
// - pmdBinary: Path to the PMD executable
16+
// - pathsToCheck: List of specific paths to analyze, if empty analyzes whole repository
17+
// - outputFile: Path where analysis results should be written
18+
// - outputFormat: Format for the output (e.g. "sarif")
19+
// - rulesetFile: Path to custom ruleset XML file, if empty uses default ruleset
20+
//
21+
// Returns:
22+
// - error: nil if analysis succeeds or violations found, error otherwise
1023
func RunPmd(repositoryToAnalyseDirectory string, pmdBinary string, pathsToCheck []string, outputFile string, outputFormat string, rulesetFile string) error {
11-
cmdArgs := []string{"pmd"}
24+
cmd := exec.Command(pmdBinary, "pmd")
25+
26+
// Add config file from tools-configs directory if not specified
27+
if rulesetFile == "" {
28+
configFile := filepath.Join(config.Config.ToolsConfigDirectory(), "pmd-ruleset.xml")
29+
cmd.Args = append(cmd.Args, "-R", configFile)
30+
} else {
31+
cmd.Args = append(cmd.Args, "-R", rulesetFile)
32+
}
1233

1334
// Add source directories (comma-separated list for PMD)
1435
if len(pathsToCheck) > 0 {
1536
dirArg := strings.Join(pathsToCheck, ",")
16-
cmdArgs = append(cmdArgs, "-d", dirArg)
37+
cmd.Args = append(cmd.Args, "-d", dirArg)
1738
} else {
1839
// Fall back to whole repo if no specific paths given
19-
cmdArgs = append(cmdArgs, "-d", repositoryToAnalyseDirectory)
20-
}
21-
22-
// Add ruleset
23-
if rulesetFile != "" {
24-
cmdArgs = append(cmdArgs, "-R", rulesetFile)
40+
cmd.Args = append(cmd.Args, "-d", repositoryToAnalyseDirectory)
2541
}
2642

2743
// Format
2844
if outputFormat != "" {
29-
cmdArgs = append(cmdArgs, "-f", outputFormat)
45+
cmd.Args = append(cmd.Args, "-f", outputFormat)
3046
}
3147

3248
// Output file
3349
if outputFile != "" {
34-
cmdArgs = append(cmdArgs, "-r", outputFile)
50+
cmd.Args = append(cmd.Args, "-r", outputFile)
3551
}
3652

37-
cmd := exec.Command(pmdBinary, cmdArgs...)
38-
3953
cmd.Dir = repositoryToAnalyseDirectory
4054
cmd.Stderr = os.Stderr
4155
cmd.Stdout = os.Stdout

tools/trivyRunner.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,20 @@
11
package tools
22

33
import (
4+
"codacy/cli-v2/config"
45
"os"
56
"os/exec"
7+
"path/filepath"
68
)
79

810
// RunTrivy executes Trivy vulnerability scanner with the specified options
911
func RunTrivy(repositoryToAnalyseDirectory string, trivyBinary string, pathsToCheck []string, outputFile string, outputFormat string) error {
1012
cmd := exec.Command(trivyBinary, "fs")
1113

14+
// Add config file from tools-configs directory
15+
configFile := filepath.Join(config.Config.ToolsConfigDirectory(), "trivy.yaml")
16+
cmd.Args = append(cmd.Args, "--config", configFile)
17+
1218
// Add format options
1319
if outputFile != "" {
1420
cmd.Args = append(cmd.Args, "--output", outputFile)

utils/files.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package utils
2+
3+
const (
4+
5+
// FilePermission represents the default file permission (rw-r--r--)
6+
// This permission gives:
7+
// - read/write (rw-) permissions to the owner
8+
// - read-only (r--) permissions to the group
9+
// - read-only (r--) permissions to others
10+
DefaultRW = 0644
11+
12+
// DefaultDirPerms represents the default directory permission (rwxr-xr-x)
13+
// This permission gives:
14+
// - read/write/execute (rwx) permissions to the owner
15+
// - read/execute (r-x) permissions to the group
16+
// - read/execute (r-x) permissions to others
17+
//
18+
// Execute permission on directories is required to:
19+
// - List directory contents (ls)
20+
// - Access files within the directory (cd)
21+
// - Create/delete files in the directory
22+
// Without execute permission, users cannot traverse into or use the directory,
23+
// even if they have read/write permissions on files inside it
24+
25+
DefaultDirPerms = 0755 // For directories
26+
)

0 commit comments

Comments
 (0)