Skip to content

Commit 0142cac

Browse files
authored
Merge pull request #60 from codacy/pick-right-config-PLUTO-1383
fix: Only pass configuration file if created, otherwise fallback to native tool PLUTO-1383
2 parents d0b14b3 + cbca7b2 commit 0142cac

File tree

11 files changed

+205
-33
lines changed

11 files changed

+205
-33
lines changed

cmd/analyze.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,7 @@ func runPmdAnalysis(workDirectory string, pathsToCheck []string, outputFile stri
211211
pmd := config.Config.Tools()["pmd"]
212212
pmdBinary := pmd.Binaries["pmd"]
213213

214-
err := tools.RunPmd(workDirectory, pmdBinary, pathsToCheck, outputFile, outputFormat, "")
214+
err := tools.RunPmd(workDirectory, pmdBinary, pathsToCheck, outputFile, outputFormat, config.Config)
215215
if err != nil {
216216
log.Fatalf("Error running PMD: %v", err)
217217
}

cmd/init.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -327,12 +327,12 @@ func createToolFileConfigurations(tool tools.Tool, patternConfiguration []domain
327327

328328
func createPMDConfigFile(config []domain.PatternConfiguration, toolsConfigDir string) error {
329329
pmdConfigurationString := tools.CreatePmdConfig(config)
330-
return os.WriteFile(filepath.Join(toolsConfigDir, "pmd-ruleset.xml"), []byte(pmdConfigurationString), utils.DefaultFilePerms)
330+
return os.WriteFile(filepath.Join(toolsConfigDir, "ruleset.xml"), []byte(pmdConfigurationString), utils.DefaultFilePerms)
331331
}
332332

333333
func createDefaultPMDConfigFile(toolsConfigDir string) error {
334334
content := tools.CreatePmdConfig([]domain.PatternConfiguration{})
335-
return os.WriteFile(filepath.Join(toolsConfigDir, "pmd-ruleset.xml"), []byte(content), utils.DefaultFilePerms)
335+
return os.WriteFile(filepath.Join(toolsConfigDir, "ruleset.xml"), []byte(content), utils.DefaultFilePerms)
336336

337337
}
338338

config/config.go

Lines changed: 39 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ import (
1111
)
1212

1313
type ConfigType struct {
14-
homePath string
14+
repositoryDirectory string
15+
1516
globalCacheDirectory string
1617
runtimesDirectory string
1718
toolsDirectory string
@@ -24,8 +25,8 @@ type ConfigType struct {
2425
tools map[string]*plugins.ToolInfo
2526
}
2627

27-
func (c *ConfigType) HomePath() string {
28-
return c.homePath
28+
func (c *ConfigType) RepositoryDirectory() string {
29+
return c.repositoryDirectory
2930
}
3031

3132
func (c *ConfigType) CodacyDirectory() string {
@@ -98,15 +99,42 @@ func (c *ConfigType) ToolsConfigDirectory() string {
9899
return c.toolsConfigDirectory
99100
}
100101

101-
func (c *ConfigType) setupCodacyPaths() {
102-
c.globalCacheDirectory = filepath.Join(c.homePath, ".cache", "codacy")
102+
func NewConfigType(repositoryDirectory string, repositoryCache string, globalCache string) *ConfigType {
103+
c := &ConfigType{}
104+
105+
c.repositoryDirectory = repositoryDirectory
106+
c.localCodacyDirectory = repositoryCache
107+
c.globalCacheDirectory = globalCache
108+
103109
c.runtimesDirectory = filepath.Join(c.globalCacheDirectory, "runtimes")
104110
c.toolsDirectory = filepath.Join(c.globalCacheDirectory, "tools")
105-
c.localCodacyDirectory = ".codacy"
106111
c.toolsConfigDirectory = filepath.Join(c.localCodacyDirectory, "tools-configs")
107112

108113
c.projectConfigFile = filepath.Join(c.localCodacyDirectory, "codacy.yaml")
109114
c.cliConfigFile = filepath.Join(c.localCodacyDirectory, "cli-config.yaml")
115+
116+
c.runtimes = make(map[string]*plugins.RuntimeInfo)
117+
c.tools = make(map[string]*plugins.ToolInfo)
118+
return c
119+
}
120+
121+
// TODO: Consider not having a global config and instead pass the config object around
122+
func setupGlobalConfig(repositoryDirectory string, repositoryCache string, globalCache string) {
123+
newConfig := NewConfigType(repositoryDirectory, repositoryCache, globalCache)
124+
125+
Config.repositoryDirectory = newConfig.repositoryDirectory
126+
Config.localCodacyDirectory = newConfig.localCodacyDirectory
127+
Config.globalCacheDirectory = newConfig.globalCacheDirectory
128+
129+
Config.runtimesDirectory = newConfig.runtimesDirectory
130+
Config.toolsDirectory = newConfig.toolsDirectory
131+
Config.toolsConfigDirectory = newConfig.toolsConfigDirectory
132+
133+
Config.projectConfigFile = newConfig.projectConfigFile
134+
Config.cliConfigFile = newConfig.cliConfigFile
135+
136+
Config.runtimes = newConfig.runtimes
137+
Config.tools = newConfig.tools
110138
}
111139

112140
func (c *ConfigType) CreateCodacyDirs() error {
@@ -136,11 +164,12 @@ func Init() {
136164
if err != nil {
137165
log.Fatal(err)
138166
}
139-
Config.homePath = homePath
167+
// Repository directory is the current working directory
168+
repositoryDirectory := ""
169+
repositoryCache := ".codacy"
170+
globalCache := filepath.Join(homePath, ".cache", "codacy")
140171

141-
Config.setupCodacyPaths()
142-
Config.runtimes = make(map[string]*plugins.RuntimeInfo)
143-
Config.tools = make(map[string]*plugins.ToolInfo)
172+
setupGlobalConfig(repositoryDirectory, repositoryCache, globalCache)
144173
}
145174

146175
// IsRuntimeInstalled checks if a runtime is already installed

tools/eslintRunner.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,10 @@ func RunEslint(repositoryToAnalyseDirectory string, eslintInstallationDirectory
2020
// https://eslint.org/docs/v8.x/use/configure/configuration-files-new
2121
cmd.Env = append(cmd.Env, "ESLINT_USE_FLAT_CONFIG=true")
2222

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)
23+
// Add config file from tools-configs directory if it exists
24+
if configFile, exists := ConfigFileExists(config.Config, "eslint.config.mjs"); exists {
25+
cmd.Args = append(cmd.Args, "-c", configFile)
26+
}
2627

2728
if autoFix {
2829
cmd.Args = append(cmd.Args, "--fix")

tools/pmdRunner.go

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import (
44
"codacy/cli-v2/config"
55
"os"
66
"os/exec"
7-
"path/filepath"
87
"strings"
98
)
109

@@ -20,15 +19,12 @@ import (
2019
//
2120
// Returns:
2221
// - error: nil if analysis succeeds or violations found, error otherwise
23-
func RunPmd(repositoryToAnalyseDirectory string, pmdBinary string, pathsToCheck []string, outputFile string, outputFormat string, rulesetFile string) error {
22+
func RunPmd(repositoryToAnalyseDirectory string, pmdBinary string, pathsToCheck []string, outputFile string, outputFormat string, config config.ConfigType) error {
2423
cmd := exec.Command(pmdBinary, "pmd")
2524

26-
// Add config file from tools-configs directory if not specified
27-
if rulesetFile == "" {
28-
configFile := filepath.Join(config.Config.ToolsConfigDirectory(), "pmd-ruleset.xml")
25+
// Add config file from tools-configs directory if it exists
26+
if configFile, exists := ConfigFileExists(config, "ruleset.xml"); exists {
2927
cmd.Args = append(cmd.Args, "-R", configFile)
30-
} else {
31-
cmd.Args = append(cmd.Args, "-R", rulesetFile)
3228
}
3329

3430
// Add source directories (comma-separated list for PMD)

tools/pmdRunner_test.go

Lines changed: 9 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
"encoding/json"
56
"log"
67
"os"
@@ -51,19 +52,24 @@ func TestRunPmdToFile(t *testing.T) {
5152

5253
// Use the correct path relative to tools directory
5354
testDirectory := filepath.Join(currentDirectory, "testdata", "repositories", "pmd")
55+
repositoryCache := filepath.Join(testDirectory, ".codacy")
56+
globalCache := filepath.Join(homeDirectory, ".cache/codacy")
57+
5458
tempResultFile := filepath.Join(os.TempDir(), "pmd.sarif")
5559
defer os.Remove(tempResultFile)
5660

61+
config := *config.NewConfigType(testDirectory, repositoryCache, globalCache)
62+
5763
// Use absolute paths
5864
repositoryToAnalyze := testDirectory
5965
// Use the standard ruleset file for testing the PMD runner functionality
60-
rulesetFile := filepath.Join(testDirectory, "pmd-ruleset.xml")
66+
//rulesetFile := filepath.Join(testDirectory, "ruleset.xml")
6167

6268
// Use the same path as defined in plugin.yaml
63-
pmdBinary := filepath.Join(homeDirectory, ".cache/codacy/tools/[email protected]/pmd-bin-6.55.0/bin/run.sh")
69+
pmdBinary := filepath.Join(globalCache, "tools/[email protected]/pmd-bin-6.55.0/bin/run.sh")
6470

6571
// Run PMD
66-
err = RunPmd(repositoryToAnalyze, pmdBinary, nil, tempResultFile, "sarif", rulesetFile)
72+
err = RunPmd(repositoryToAnalyze, pmdBinary, nil, tempResultFile, "sarif", config)
6773
if err != nil {
6874
t.Fatalf("Failed to run pmd: %v", err)
6975
}

tools/pylintRunner.go

Lines changed: 5 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
"codacy/cli-v2/plugins"
56
"codacy/cli-v2/utils"
67
"fmt"
@@ -19,9 +20,10 @@ func RunPylint(workDirectory string, toolInfo *plugins.ToolInfo, files []string,
1920
// Always use JSON output format since we'll convert to SARIF if needed
2021
args = append(args, "--output-format=json")
2122

22-
// Use the configuration file from .codacy/tools-configs/pylintrc
23-
configPath := filepath.Join(workDirectory, ".codacy", "tools-configs", "pylint.rc")
24-
args = append(args, fmt.Sprintf("--rcfile=%s", configPath))
23+
// Check if a config file exists in the expected location and use it if present
24+
if configFile, exists := ConfigFileExists(config.Config, "pylint.rc"); exists {
25+
args = append(args, fmt.Sprintf("--rcfile=%s", configFile))
26+
}
2527

2628
// Create a temporary file for JSON output if we need to convert to SARIF
2729
var tempFile string

tools/runnerUtils.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package tools
2+
3+
import (
4+
"codacy/cli-v2/config"
5+
"os"
6+
"path/filepath"
7+
)
8+
9+
// ConfigFileExists checks if a specific configuration file exists in the .codacy/tools-configs/
10+
// or on the root of the repository directory.
11+
//
12+
// Parameters:
13+
// - conf: The configuration object containing the tools config directory
14+
// - fileName: The configuration file name to check for
15+
//
16+
// Returns:
17+
// - string: The relative path to the configuration file (for cmd args)
18+
// - bool: True if the file exists, false otherwise
19+
func ConfigFileExists(conf config.ConfigType, fileName string) (string, bool) {
20+
generatedConfigFile := filepath.Join(conf.ToolsConfigDirectory(), fileName)
21+
existingConfigFile := filepath.Join(conf.RepositoryDirectory(), fileName)
22+
23+
if _, err := os.Stat(generatedConfigFile); err == nil {
24+
return generatedConfigFile, true
25+
} else if _, err := os.Stat(existingConfigFile); err == nil {
26+
return existingConfigFile, true
27+
}
28+
29+
return "", false
30+
}

tools/runnerUtils_test.go

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
package tools
2+
3+
import (
4+
"codacy/cli-v2/config"
5+
"os"
6+
"path/filepath"
7+
"testing"
8+
9+
"github.com/stretchr/testify/assert"
10+
)
11+
12+
func TestConfigFileExistsInToolsConfigDirectory(t *testing.T) {
13+
// Create a test directory structure
14+
tempDir := t.TempDir()
15+
repoDir := filepath.Join(tempDir, "src")
16+
repositoryCache := filepath.Join(repoDir, ".codacy")
17+
18+
// Create configuration
19+
config := *config.NewConfigType(repoDir, repositoryCache, "unused-global-cache")
20+
21+
// Create .codacy/tools-configs directory
22+
configDir := filepath.Join(repoDir, ".codacy", "tools-configs")
23+
err := os.MkdirAll(configDir, 0755)
24+
assert.NoError(t, err, "Failed to create test directory structure")
25+
26+
// Create a test config file on the configDir
27+
generatedConfigFile := filepath.Join(configDir, "generated-config.yaml")
28+
err = os.WriteFile(generatedConfigFile, []byte("test content"), 0644)
29+
assert.NoError(t, err, "Failed to create test config file")
30+
31+
// Test case: Config file exists in tools config directory
32+
configPath, exists := ConfigFileExists(config, "generated-config.yaml")
33+
assert.True(t, exists, "Config file should exist in tools config directory")
34+
assert.Equal(t, filepath.Join(config.ToolsConfigDirectory(), "generated-config.yaml"), configPath,
35+
"Config path should be correctly formed relative path")
36+
}
37+
38+
func TestConfigFileExistsInRepositoryDirectory(t *testing.T) {
39+
// Create a test directory structure
40+
tempDir := t.TempDir()
41+
repoDir := filepath.Join(tempDir, "src")
42+
repositoryCache := filepath.Join(repoDir, ".codacy")
43+
44+
// Create configuration
45+
config := *config.NewConfigType(repoDir, repositoryCache, "unused-global-cache")
46+
47+
// Create .codacy/tools-configs directory
48+
configDir := filepath.Join(repoDir, ".codacy", "tools-configs")
49+
err := os.MkdirAll(configDir, 0755)
50+
assert.NoError(t, err, "Failed to create test directory structure")
51+
52+
// Create a test config file on the repository directory
53+
existingConfigFile := filepath.Join(repoDir, "existing-config.yaml")
54+
err = os.WriteFile(existingConfigFile, []byte("test content"), 0644)
55+
assert.NoError(t, err, "Failed to create test config file")
56+
57+
// Test case: The existing config file gets picked up
58+
configPath, exists := ConfigFileExists(config, "existing-config.yaml")
59+
assert.True(t, exists, "Config file should exist in tools config directory")
60+
assert.Equal(t, filepath.Join(config.RepositoryDirectory(), "existing-config.yaml"), configPath,
61+
"Config path should be correctly formed relative path")
62+
}
63+
64+
func TestConfigFilePrefersToolsConfigDirectory(t *testing.T) {
65+
// Create a test directory structure
66+
tempDir := t.TempDir()
67+
repoDir := filepath.Join(tempDir, "src")
68+
repositoryCache := filepath.Join(repoDir, ".codacy")
69+
70+
// Create configuration
71+
config := *config.NewConfigType(repoDir, repositoryCache, "unused-global-cache")
72+
73+
// Create .codacy/tools-configs directory
74+
configDir := filepath.Join(repoDir, ".codacy", "tools-configs")
75+
err := os.MkdirAll(configDir, 0755)
76+
assert.NoError(t, err, "Failed to create test directory structure")
77+
78+
// Create a test config file in both locations
79+
generatedConfigFile := filepath.Join(configDir, "some-config.yaml")
80+
existingConfigFile := filepath.Join(repoDir, "some-config.yaml")
81+
82+
err = os.WriteFile(generatedConfigFile, []byte("tools config content"), 0644)
83+
assert.NoError(t, err, "Failed to create test config file in tools config directory")
84+
85+
err = os.WriteFile(existingConfigFile, []byte("repository config content"), 0644)
86+
assert.NoError(t, err, "Failed to create test config file in repository directory")
87+
88+
// Test case: Config file in tools config directory is preferred
89+
configPath, exists := ConfigFileExists(config, "some-config.yaml")
90+
assert.True(t, exists, "Config file should exist")
91+
assert.Equal(t, filepath.Join(config.ToolsConfigDirectory(), "some-config.yaml"), configPath,
92+
"Config path should prefer tools config directory")
93+
}
94+
95+
func TestConfigFileDoesNotExist(t *testing.T) {
96+
// Create a test directory structure
97+
tempDir := t.TempDir()
98+
repoDir := filepath.Join(tempDir, "src")
99+
repositoryCache := filepath.Join(repoDir, ".codacy")
100+
101+
// Create configuration
102+
config := *config.NewConfigType(repoDir, repositoryCache, "unused-global-cache")
103+
104+
// Test case: Config file does not exist
105+
configPath, exists := ConfigFileExists(config, "non-existent-config.yaml")
106+
assert.False(t, exists, "Config file should not exist")
107+
assert.Equal(t, "", configPath, "Config path should be empty for non-existent file")
108+
}
File renamed without changes.

0 commit comments

Comments
 (0)