Skip to content

Pluto 1382 change tools configs location #59

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 11 commits into from
Apr 8, 2025
Merged
1 change: 0 additions & 1 deletion .codacy/cli-config.yaml

This file was deleted.

3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,5 @@ go.work.sum
.idea/
.vscode/

cli-v2
# Codacy CLI
cli-v2
4 changes: 1 addition & 3 deletions cmd/analyze.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ var outputFormat string
var sarifPath string
var commitUuid string
var projectToken string
var pmdRulesetFile string

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

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

err := tools.RunPmd(workDirectory, pmdBinary, pathsToCheck, outputFile, outputFormat, pmdRulesetFile)
err := tools.RunPmd(workDirectory, pmdBinary, pathsToCheck, outputFile, outputFormat, "")
if err != nil {
log.Fatalf("Error running PMD: %v", err)
}
Expand Down
62 changes: 46 additions & 16 deletions cmd/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@ package cmd
import (
"codacy/cli-v2/config"
"codacy/cli-v2/tools"
"codacy/cli-v2/utils"
"encoding/json"
"errors"
"fmt"
"io"
"log"
"net/http"
"os"
"path/filepath"
"time"

"github.com/spf13/cobra"
Expand Down Expand Up @@ -55,6 +57,7 @@ var initCmd = &cobra.Command{
if err != nil {
log.Fatal(err)
}
createGitIgnoreFile()
}
fmt.Println()
fmt.Println("✅ Successfully initialized Codacy configuration!")
Expand All @@ -66,6 +69,26 @@ var initCmd = &cobra.Command{
},
}

func createGitIgnoreFile() error {
gitIgnorePath := filepath.Join(config.Config.LocalCodacyDirectory(), ".gitignore")
gitIgnoreFile, err := os.Create(gitIgnorePath)
if err != nil {
return fmt.Errorf("failed to create .gitignore file: %w", err)
}
defer gitIgnoreFile.Close()

content := `# Codacy CLI
tools-configs/
.gitignore
cli-config.yaml
`
if _, err := gitIgnoreFile.WriteString(content); err != nil {
return fmt.Errorf("failed to write to .gitignore file: %w", err)
}

return nil
}

func createConfigurationFiles(tools []tools.Tool, cliLocalMode bool) error {
configFile, err := os.Create(config.Config.ProjectConfigFile())
defer configFile.Close()
Expand Down Expand Up @@ -142,6 +165,13 @@ func buildRepositoryConfigurationFiles(token string) error {
fmt.Println("Building repository configuration files ...")
fmt.Println("Fetching repository configuration from codacy ...")

toolsConfigDir := config.Config.ToolsConfigDirectory()

// Create tools-configs directory if it doesn't exist
if err := os.MkdirAll(toolsConfigDir, utils.DefaultDirPerms); err != nil {
return fmt.Errorf("failed to create tools-configs directory: %w", err)
}

// API call to fetch settings
url := CodacyApiBase + "/2.0/project/analysis/configuration"

Expand Down Expand Up @@ -198,7 +228,7 @@ func buildRepositoryConfigurationFiles(token string) error {
eslintDomainConfiguration := convertAPIToolConfigurationToDomain(*eslintApiConfiguration)
eslintConfigurationString := tools.CreateEslintConfig(eslintDomainConfiguration)

eslintConfigFile, err := os.Create("eslint.config.mjs")
eslintConfigFile, err := os.Create(filepath.Join(toolsConfigDir, "eslint.config.mjs"))
if err != nil {
return fmt.Errorf("failed to create eslint config file: %v", err)
}
Expand All @@ -210,7 +240,7 @@ func buildRepositoryConfigurationFiles(token string) error {
}
fmt.Println("ESLint configuration created based on Codacy settings")
} else {
err = createDefaultEslintConfigFile()
err = createDefaultEslintConfigFile(toolsConfigDir)
if err != nil {
return fmt.Errorf("failed to create default ESLint config: %v", err)
}
Expand All @@ -220,13 +250,13 @@ func buildRepositoryConfigurationFiles(token string) error {
// Trivy configuration
trivyApiConfiguration := extractTrivyConfiguration(apiToolConfigurations)
if trivyApiConfiguration != nil {
err = createTrivyConfigFile(*trivyApiConfiguration)
err = createTrivyConfigFile(*trivyApiConfiguration, toolsConfigDir)
if err != nil {
return fmt.Errorf("failed to create Trivy config: %v", err)
}
fmt.Println("Trivy configuration created based on Codacy settings")
} else {
err = createDefaultTrivyConfigFile()
err = createDefaultTrivyConfigFile(toolsConfigDir)
if err != nil {
return fmt.Errorf("failed to create default Trivy config: %v", err)
}
Expand All @@ -236,13 +266,13 @@ func buildRepositoryConfigurationFiles(token string) error {
// PMD configuration
pmdApiConfiguration := extractPMDConfiguration(apiToolConfigurations)
if pmdApiConfiguration != nil {
err = createPMDConfigFile(*pmdApiConfiguration)
err = createPMDConfigFile(*pmdApiConfiguration, toolsConfigDir)
if err != nil {
return fmt.Errorf("failed to create PMD config: %v", err)
}
fmt.Println("PMD configuration created based on Codacy settings")
} else {
err = createDefaultPMDConfigFile()
err = createDefaultPMDConfigFile(toolsConfigDir)
if err != nil {
return fmt.Errorf("failed to create default PMD config: %v", err)
}
Expand Down Expand Up @@ -318,16 +348,16 @@ func extractPMDConfiguration(toolConfigurations []CodacyToolConfiguration) *Coda
return nil
}

func createPMDConfigFile(config CodacyToolConfiguration) error {
func createPMDConfigFile(config CodacyToolConfiguration, toolsConfigDir string) error {
pmdDomainConfiguration := convertAPIToolConfigurationToDomain(config)
pmdConfigurationString := tools.CreatePmdConfig(pmdDomainConfiguration)
return os.WriteFile("pmd-ruleset.xml", []byte(pmdConfigurationString), 0644)
return os.WriteFile(filepath.Join(toolsConfigDir, "pmd-ruleset.xml"), []byte(pmdConfigurationString), utils.DefaultRW)
}

func createDefaultPMDConfigFile() error {
func createDefaultPMDConfigFile(toolsConfigDir string) error {
emptyConfig := tools.ToolConfiguration{}
content := tools.CreatePmdConfig(emptyConfig)
return os.WriteFile("pmd-ruleset.xml", []byte(content), 0644)
return os.WriteFile(filepath.Join(toolsConfigDir, "pmd-ruleset.xml"), []byte(content), utils.DefaultRW)
}

type CodacyToolConfiguration struct {
Expand All @@ -347,15 +377,15 @@ type ParameterConfiguration struct {
}

// createTrivyConfigFile creates a trivy.yaml configuration file based on the API configuration
func createTrivyConfigFile(config CodacyToolConfiguration) error {
func createTrivyConfigFile(config CodacyToolConfiguration, toolsConfigDir string) error {
// Convert CodacyToolConfiguration to tools.ToolConfiguration
trivyDomainConfiguration := convertAPIToolConfigurationForTrivy(config)

// Use the shared CreateTrivyConfig function to generate the config content
trivyConfigurationString := tools.CreateTrivyConfig(trivyDomainConfiguration)

// Write to file
return os.WriteFile("trivy.yaml", []byte(trivyConfigurationString), 0644)
return os.WriteFile(filepath.Join(toolsConfigDir, "trivy.yaml"), []byte(trivyConfigurationString), utils.DefaultRW)
}

// convertAPIToolConfigurationForTrivy converts API tool configuration to domain model for Trivy
Expand Down Expand Up @@ -399,21 +429,21 @@ func convertAPIToolConfigurationForTrivy(config CodacyToolConfiguration) tools.T
}

// createDefaultTrivyConfigFile creates a default trivy.yaml configuration file
func createDefaultTrivyConfigFile() error {
func createDefaultTrivyConfigFile(toolsConfigDir string) error {
// Use empty tool configuration to get default settings
emptyConfig := tools.ToolConfiguration{}
content := tools.CreateTrivyConfig(emptyConfig)

// Write to file
return os.WriteFile("trivy.yaml", []byte(content), 0644)
return os.WriteFile(filepath.Join(toolsConfigDir, "trivy.yaml"), []byte(content), utils.DefaultRW)
}

// createDefaultEslintConfigFile creates a default eslint.config.mjs configuration file
func createDefaultEslintConfigFile() error {
func createDefaultEslintConfigFile(toolsConfigDir string) error {
// Use empty tool configuration to get default settings
emptyConfig := tools.ToolConfiguration{}
content := tools.CreateEslintConfig(emptyConfig)

// Write to file
return os.WriteFile("eslint.config.mjs", []byte(content), 0644)
return os.WriteFile(filepath.Join(toolsConfigDir, "eslint.config.mjs"), []byte(content), utils.DefaultRW)
}
10 changes: 10 additions & 0 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
runtimesDirectory string
toolsDirectory string
localCodacyDirectory string
toolsConfigDirectory string
projectConfigFile string
cliConfigFile string

Expand Down Expand Up @@ -42,6 +43,10 @@
return c.localCodacyDirectory
}

func (c *ConfigType) ToolsConfigsDirectory() string {

Check notice on line 46 in config/config.go

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

config/config.go#L46

exported method ConfigType.ToolsConfigsDirectory should have comment or be unexported
return c.toolsConfigDirectory
}

func (c *ConfigType) ProjectConfigFile() string {
return c.projectConfigFile
}
Expand Down Expand Up @@ -88,11 +93,16 @@
return nil
}

func (c *ConfigType) ToolsConfigDirectory() string {

Check notice on line 96 in config/config.go

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

config/config.go#L96

exported method ConfigType.ToolsConfigDirectory should have comment or be unexported
return c.toolsConfigDirectory
}

func (c *ConfigType) setupCodacyPaths() {
c.globalCacheDirectory = filepath.Join(c.homePath, ".cache", "codacy")
c.runtimesDirectory = filepath.Join(c.globalCacheDirectory, "runtimes")
c.toolsDirectory = filepath.Join(c.globalCacheDirectory, "tools")
c.localCodacyDirectory = ".codacy"
c.toolsConfigDirectory = filepath.Join(c.localCodacyDirectory, "tools-configs")

c.projectConfigFile = filepath.Join(c.localCodacyDirectory, "codacy.yaml")
c.cliConfigFile = filepath.Join(c.localCodacyDirectory, "cli-config.yaml")
Expand Down
1 change: 0 additions & 1 deletion tools/eslintConfigCreator.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ func CreateEslintConfig(configuration ToolConfiguration) string {

for _, patternConfiguration := range configuration.PatternsConfiguration {
rule := strings.TrimPrefix(patternConfiguration.PatternId, "ESLint8_")
fmt.Println("Rule:", rule)

const tempstring = "TEMPORARYSTRING"
rule = strings.ReplaceAll(rule, "__", tempstring)
Expand Down
16 changes: 13 additions & 3 deletions tools/eslintRunner.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package tools

import (
"codacy/cli-v2/config"
"os"
"os/exec"
"path/filepath"
Expand All @@ -14,6 +15,15 @@ func RunEslint(repositoryToAnalyseDirectory string, eslintInstallationDirectory
eslintJsPath := filepath.Join(eslintInstallationNodeModules, ".bin", "eslint")

cmd := exec.Command(nodeBinary, eslintJsPath)

// For Eslint compatibility with version 8.
// https://eslint.org/docs/v8.x/use/configure/configuration-files-new
cmd.Env = append(cmd.Env, "ESLINT_USE_FLAT_CONFIG=true")

// Add config file from tools-configs directory
configFile := filepath.Join(config.Config.ToolsConfigDirectory(), "eslint.config.mjs")
cmd.Args = append(cmd.Args, "-c", configFile)

if autoFix {
cmd.Args = append(cmd.Args, "--fix")
}
Expand All @@ -39,9 +49,9 @@ func RunEslint(repositoryToAnalyseDirectory string, eslintInstallationDirectory
nodePathEnv := "NODE_PATH=" + eslintInstallationNodeModules
cmd.Env = append(cmd.Env, nodePathEnv)

//DEBUG
//fmt.Println(cmd.Env)
//fmt.Println(cmd)
// DEBUG
// fmt.Println(cmd.Env)
// fmt.Println(cmd)

// TODO eslint returns 1 when it finds errors, so we're not propagating it
cmd.Run()
Expand Down
38 changes: 26 additions & 12 deletions tools/pmdRunner.go
Original file line number Diff line number Diff line change
@@ -1,41 +1,55 @@
package tools

import (
"codacy/cli-v2/config"
"os"
"os/exec"
"path/filepath"
"strings"
)

// RunPmd executes PMD static code analyzer with the specified options
//
// Parameters:
// - repositoryToAnalyseDirectory: The root directory of the repository to analyze
// - pmdBinary: Path to the PMD executable
// - pathsToCheck: List of specific paths to analyze, if empty analyzes whole repository
// - outputFile: Path where analysis results should be written
// - outputFormat: Format for the output (e.g. "sarif")
// - rulesetFile: Path to custom ruleset XML file, if empty uses default ruleset
//
// Returns:
// - error: nil if analysis succeeds or violations found, error otherwise
func RunPmd(repositoryToAnalyseDirectory string, pmdBinary string, pathsToCheck []string, outputFile string, outputFormat string, rulesetFile string) error {
cmdArgs := []string{"pmd"}
cmd := exec.Command(pmdBinary, "pmd")

Check failure on line 24 in tools/pmdRunner.go

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

tools/pmdRunner.go#L24

Detected non-static command inside Command.

Check failure on line 24 in tools/pmdRunner.go

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

tools/pmdRunner.go#L24

OS command injection is a critical vulnerability that can lead to a full system compromise as it may allow an adversary to pass in arbitrary commands or arguments to be executed.

// Add config file from tools-configs directory if not specified
if rulesetFile == "" {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see that we pass always "" is this a WIP, or suppose to be like this on the scope of this PR? I see you removed a setting witch was PMD only (which makes sense for me to be removed). So maybe we don't even want this argument if this if is just a fake?

Meaning, instead of deciding this here, assuming that we were passing some kind of default, is to generate a file with the defaults as needed?

Copy link
Contributor Author

@andrzej-janczak andrzej-janczak Apr 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not always, in test I use a specific file and In this case it's ok.

Generally, If in future we want to be able to pass smth like analyze --config xyz.file - like ovveride, then it can stay.
If not we can delete 🤷‍♂️

configFile := filepath.Join(config.Config.ToolsConfigDirectory(), "pmd-ruleset.xml")
cmd.Args = append(cmd.Args, "-R", configFile)
} else {
cmd.Args = append(cmd.Args, "-R", rulesetFile)
}

// Add source directories (comma-separated list for PMD)
if len(pathsToCheck) > 0 {
dirArg := strings.Join(pathsToCheck, ",")
cmdArgs = append(cmdArgs, "-d", dirArg)
cmd.Args = append(cmd.Args, "-d", dirArg)
} else {
// Fall back to whole repo if no specific paths given
cmdArgs = append(cmdArgs, "-d", repositoryToAnalyseDirectory)
}

// Add ruleset
if rulesetFile != "" {
cmdArgs = append(cmdArgs, "-R", rulesetFile)
cmd.Args = append(cmd.Args, "-d", repositoryToAnalyseDirectory)
}

// Format
if outputFormat != "" {
cmdArgs = append(cmdArgs, "-f", outputFormat)
cmd.Args = append(cmd.Args, "-f", outputFormat)
}

// Output file
if outputFile != "" {
cmdArgs = append(cmdArgs, "-r", outputFile)
cmd.Args = append(cmd.Args, "-r", outputFile)
}

cmd := exec.Command(pmdBinary, cmdArgs...)

cmd.Dir = repositoryToAnalyseDirectory
cmd.Stderr = os.Stderr
cmd.Stdout = os.Stdout
Expand Down
6 changes: 6 additions & 0 deletions tools/trivyRunner.go
Original file line number Diff line number Diff line change
@@ -1,14 +1,20 @@
package tools

import (
"codacy/cli-v2/config"
"os"
"os/exec"
"path/filepath"
)

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

// Add config file from tools-configs directory
configFile := filepath.Join(config.Config.ToolsConfigDirectory(), "trivy.yaml")
cmd.Args = append(cmd.Args, "--config", configFile)

// Add format options
if outputFile != "" {
cmd.Args = append(cmd.Args, "--output", outputFile)
Expand Down
Loading