From a07e0f3f0e49fc294e570ba0a35f707b56331612 Mon Sep 17 00:00:00 2001 From: Alejandro Rizzo Date: Mon, 20 Oct 2025 14:54:56 +0100 Subject: [PATCH 1/8] fix: fix Lizard runner --- tools/lizard/lizardRunner.go | 91 +++++++++++++++++++++--------------- 1 file changed, 53 insertions(+), 38 deletions(-) diff --git a/tools/lizard/lizardRunner.go b/tools/lizard/lizardRunner.go index 8cab894d..a606e992 100644 --- a/tools/lizard/lizardRunner.go +++ b/tools/lizard/lizardRunner.go @@ -6,6 +6,8 @@ import ( "codacy/cli-v2/constants" "codacy/cli-v2/domain" "codacy/cli-v2/tools" + "codacy/cli-v2/utils/logger" + "github.com/sirupsen/logrus" "encoding/json" "fmt" "os" @@ -19,6 +21,7 @@ func RunLizard(workDirectory string, binary string, files []string, outputFile s var patterns []domain.PatternDefinition var errConfigs error + if exists { // Configuration exists, read from file patterns, errConfigs = ReadConfig(configFile) @@ -36,6 +39,7 @@ func RunLizard(workDirectory string, binary string, files []string, outputFile s return fmt.Errorf("no valid patterns found in configuration") } + // Construct base command with lizard module args := []string{"-m", "lizard", "-V"} @@ -46,66 +50,77 @@ func RunLizard(workDirectory string, binary string, files []string, outputFile s args = append(args, ".") } + // For non-SARIF output, let Lizard handle file output directly if outputFormat != "sarif" && outputFile != "" { args = append(args, "-o", outputFile) } + // Run the command cmd := exec.Command(binary, args...) cmd.Dir = workDirectory - cmd.Stderr = os.Stderr + var err error + var stderr bytes.Buffer + + cmd.Stderr = &stderr + // For SARIF output, we need to capture and parse the output if outputFormat == "sarif" { var stdout bytes.Buffer cmd.Stdout = &stdout - err = cmd.Run() + cmd.Run() + + if stderr.Len() > 0 { + logger.Debug("Failed to run Lizard: ", logrus.Fields{ + "error": err.Error(), + "stderr": string(stderr.Bytes()), + }) + + return fmt.Errorf("failed to run Lizard: %w", err) + } + + // Parse the output and generate issues + results, parseErr := parseLizardResults(stdout.String()) + if parseErr != nil { + return fmt.Errorf("failed to parse Lizard output: %w", parseErr) + } + issues := generateIssuesFromResults(results, patterns) + + // Convert issues to SARIF Report + sarifReport := convertIssuesToSarif(issues, patterns) + // Marshal SARIF Report report to Sarif + sarifData, err := json.MarshalIndent(sarifReport, "", " ") if err != nil { - // Lizard returns 1 when it finds issues, which is not a failure - if exitErr, ok := err.(*exec.ExitError); ok && exitErr.ExitCode() == 1 { - // Parse the output and generate issues - results, parseErr := parseLizardResults(stdout.String()) - if parseErr != nil { - return fmt.Errorf("failed to parse Lizard output: %w", parseErr) - } - - issues := generateIssuesFromResults(results, patterns) - - // Convert issues to SARIF Report - sarifReport := convertIssuesToSarif(issues, patterns) - - // Marshal SARIF Report report to Sarif - sarifData, err := json.MarshalIndent(sarifReport, "", " ") - if err != nil { - return fmt.Errorf("failed to marshal SARIF report: %w", err) - } - - // Write SARIF output to file if specified, else stdout - if outputFile != "" { - err = os.WriteFile(outputFile, sarifData, constants.DefaultFilePerms) - if err != nil { - return fmt.Errorf("failed to write SARIF output: %w", err) - } - } else { - fmt.Println(string(sarifData)) - } - - return nil + return fmt.Errorf("failed to marshal SARIF report: %w", err) + } + + // Write SARIF output to file if specified, else stdout + if outputFile != "" { + err = os.WriteFile(outputFile, sarifData, constants.DefaultFilePerms) + if err != nil { + return fmt.Errorf("failed to write SARIF output: %w", err) } - return fmt.Errorf("failed to run Lizard: %w", err) + } else { + fmt.Println(string(sarifData)) } + + return nil + } else { // For non-SARIF output, let Lizard handle stdout cmd.Stdout = os.Stdout err = cmd.Run() - if err != nil { - // Lizard returns 1 when it finds issues, which is not a failure - if exitErr, ok := err.(*exec.ExitError); ok && exitErr.ExitCode() == 1 { - return nil - } + + if stderr.Len() > 0 { + logger.Debug("Failed to run Lizard: ", logrus.Fields{ + "error": err.Error(), + "stderr": string(stderr.Bytes()), + }) + return fmt.Errorf("failed to run Lizard: %w", err) } } From 9247e50ca7170f80bcd49521e2f47f7ca4c01667 Mon Sep 17 00:00:00 2001 From: Alejandro Rizzo Date: Mon, 20 Oct 2025 15:37:06 +0100 Subject: [PATCH 2/8] fix: refactor setup and fix Lizard remote init --- cmd/configsetup/codacy_yaml.go | 174 ++++++ cmd/configsetup/config_creators.go | 65 +++ cmd/configsetup/default_config.go | 239 +++++++++ cmd/configsetup/repository_config.go | 160 ++++++ cmd/configsetup/setup.go | 769 +-------------------------- cmd/configsetup/tool_creators.go | 176 ++++++ tools/lizard/lizardConfigCreator.go | 26 +- 7 files changed, 829 insertions(+), 780 deletions(-) create mode 100644 cmd/configsetup/codacy_yaml.go create mode 100644 cmd/configsetup/config_creators.go create mode 100644 cmd/configsetup/default_config.go create mode 100644 cmd/configsetup/repository_config.go create mode 100644 cmd/configsetup/tool_creators.go diff --git a/cmd/configsetup/codacy_yaml.go b/cmd/configsetup/codacy_yaml.go new file mode 100644 index 00000000..c3f1ba6f --- /dev/null +++ b/cmd/configsetup/codacy_yaml.go @@ -0,0 +1,174 @@ +package configsetup + +import ( + "fmt" + "log" + "sort" + "strings" + + "codacy/cli-v2/domain" + "codacy/cli-v2/plugins" +) + +// RuntimePluginConfig holds the structure of the runtime plugin.yaml file +type RuntimePluginConfig struct { + Name string `yaml:"name"` + Description string `yaml:"description"` + DefaultVersion string `yaml:"default_version"` +} + +func ConfigFileTemplate(tools []domain.Tool) string { + toolsMap := make(map[string]bool) + toolVersions := make(map[string]string) + neededRuntimes := make(map[string]bool) + + toolsWithLatestVersion, _, _ := KeepToolsWithLatestVersion(tools) + + // Get versions and runtime dependencies + defaultVersions := plugins.GetToolVersions() + runtimeVersions := plugins.GetRuntimeVersions() + runtimeDependencies := plugins.GetToolRuntimeDependencies() + + // Process enabled tools + for _, tool := range toolsWithLatestVersion { + toolsMap[tool.Uuid] = true + toolVersions[tool.Uuid] = getToolVersion(tool, defaultVersions) + addRequiredRuntime(tool.Uuid, neededRuntimes, runtimeDependencies) + } + + var sb strings.Builder + + // Build runtimes section + buildRuntimesSection(&sb, tools, neededRuntimes, runtimeVersions, runtimeDependencies) + + // Build tools section + buildToolsSection(&sb, tools, toolsMap, toolVersions, defaultVersions) + + return sb.String() +} + +// getToolVersion returns the version for a tool, preferring tool.Version over default +func getToolVersion(tool domain.Tool, defaultVersions map[string]string) string { + if tool.Version != "" { + return tool.Version + } + if meta, ok := domain.SupportedToolsMetadata[tool.Uuid]; ok { + if defaultVersion, ok := defaultVersions[meta.Name]; ok { + return defaultVersion + } + } + return "" +} + +// addRequiredRuntime adds the runtime requirement for a tool +func addRequiredRuntime(toolUuid string, neededRuntimes map[string]bool, runtimeDependencies map[string]string) { + if meta, ok := domain.SupportedToolsMetadata[toolUuid]; ok { + if runtime, ok := runtimeDependencies[meta.Name]; ok { + if meta.Name == "dartanalyzer" { + // For dartanalyzer, default to dart runtime + neededRuntimes["dart"] = true + } else { + neededRuntimes[runtime] = true + } + } + } +} + +// buildRuntimesSection builds the runtimes section of the configuration +func buildRuntimesSection(sb *strings.Builder, tools []domain.Tool, neededRuntimes map[string]bool, runtimeVersions map[string]string, runtimeDependencies map[string]string) { + sb.WriteString("runtimes:\n") + + if len(tools) == 0 { + // In local mode with no tools specified, include all necessary runtimes + addAllSupportedRuntimes(neededRuntimes, runtimeDependencies) + } + + writeRuntimesList(sb, neededRuntimes, runtimeVersions) +} + +// addAllSupportedRuntimes adds all runtimes needed by supported tools +func addAllSupportedRuntimes(neededRuntimes map[string]bool, runtimeDependencies map[string]string) { + supportedTools, err := plugins.GetSupportedTools() + if err != nil { + log.Printf("Warning: failed to get supported tools: %v", err) + return + } + + for toolName := range supportedTools { + if runtime, ok := runtimeDependencies[toolName]; ok { + if toolName == "dartanalyzer" { + neededRuntimes["dart"] = true + } else { + neededRuntimes[runtime] = true + } + } + } +} + +// writeRuntimesList writes the sorted runtimes list to the string builder +func writeRuntimesList(sb *strings.Builder, neededRuntimes map[string]bool, runtimeVersions map[string]string) { + var sortedRuntimes []string + for runtime := range neededRuntimes { + sortedRuntimes = append(sortedRuntimes, runtime) + } + sort.Strings(sortedRuntimes) + + for _, runtime := range sortedRuntimes { + sb.WriteString(fmt.Sprintf(" - %s@%s\n", runtime, runtimeVersions[runtime])) + } +} + +// buildToolsSection builds the tools section of the configuration +func buildToolsSection(sb *strings.Builder, tools []domain.Tool, toolsMap map[string]bool, toolVersions map[string]string, defaultVersions map[string]string) { + sb.WriteString("tools:\n") + + if len(tools) > 0 { + writeEnabledTools(sb, toolsMap, toolVersions) + } else { + writeAllSupportedTools(sb, defaultVersions) + } +} + +// writeEnabledTools writes the enabled tools to the string builder +func writeEnabledTools(sb *strings.Builder, toolsMap map[string]bool, toolVersions map[string]string) { + var sortedTools []string + for uuid, meta := range domain.SupportedToolsMetadata { + if toolsMap[uuid] { + sortedTools = append(sortedTools, meta.Name) + } + } + sort.Strings(sortedTools) + + for _, name := range sortedTools { + for uuid, meta := range domain.SupportedToolsMetadata { + if meta.Name == name && toolsMap[uuid] { + version := toolVersions[uuid] + sb.WriteString(fmt.Sprintf(" - %s@%s\n", name, version)) + break + } + } + } +} + +// writeAllSupportedTools writes all supported tools to the string builder +func writeAllSupportedTools(sb *strings.Builder, defaultVersions map[string]string) { + supportedTools, err := plugins.GetSupportedTools() + if err != nil { + log.Printf("Warning: failed to get supported tools: %v", err) + return + } + + var sortedTools []string + for toolName := range supportedTools { + if version, ok := defaultVersions[toolName]; ok && version != "" { + sortedTools = append(sortedTools, toolName) + } + } + sort.Strings(sortedTools) + + for _, toolName := range sortedTools { + if version, ok := defaultVersions[toolName]; ok { + sb.WriteString(fmt.Sprintf(" - %s@%s\n", toolName, version)) + } + } +} diff --git a/cmd/configsetup/config_creators.go b/cmd/configsetup/config_creators.go new file mode 100644 index 00000000..4a63adad --- /dev/null +++ b/cmd/configsetup/config_creators.go @@ -0,0 +1,65 @@ +package configsetup + +import ( + "fmt" + "path/filepath" + + "codacy/cli-v2/config" + "codacy/cli-v2/constants" + "codacy/cli-v2/domain" + "codacy/cli-v2/tools" + + "gopkg.in/yaml.v3" +) + +func CreateLanguagesConfigFileLocal(toolsConfigDir string) error { + // Build tool language configurations from API + configTools, err := tools.BuildLanguagesConfigFromAPI() + if err != nil { + return fmt.Errorf("failed to build languages config from API: %w", err) + } + + // Create the config structure + config := domain.LanguagesConfig{ + Tools: configTools, + } + + // Marshal to YAML + data, err := yaml.Marshal(config) + if err != nil { + return fmt.Errorf("failed to marshal languages config to YAML: %w", err) + } + + return writeConfigFile(filepath.Join(toolsConfigDir, constants.LanguagesConfigFileName), data) +} + +func CreateGitIgnoreFile() error { + gitIgnorePath := filepath.Join(config.Config.LocalCodacyDirectory(), constants.GitIgnoreFileName) + content := "# Codacy CLI\ntools-configs/\n.gitignore\ncli-config.yaml\nlogs/\n" + return writeConfigFile(gitIgnorePath, []byte(content)) +} + +func CreateConfigurationFiles(tools []domain.Tool, cliLocalMode bool, flags domain.InitFlags) error { + // Create project config file + configContent := ConfigFileTemplate(tools) + if err := writeConfigFile(config.Config.ProjectConfigFile(), []byte(configContent)); err != nil { + return fmt.Errorf("failed to write project config file: %w", err) + } + + // Create CLI config file + cliConfigContent := buildCliConfigContent(cliLocalMode, flags) + if err := writeConfigFile(config.Config.CliConfigFile(), []byte(cliConfigContent)); err != nil { + return fmt.Errorf("failed to write CLI config file: %w", err) + } + + return nil +} + +// buildCliConfigContent creates the CLI configuration content +func buildCliConfigContent(cliLocalMode bool, initFlags domain.InitFlags) string { + if cliLocalMode { + return fmt.Sprintf("mode: local") + } else { + return fmt.Sprintf("mode: remote\nprovider: %s\norganization: %s\nrepository: %s", initFlags.Provider, initFlags.Organization, initFlags.Repository) + } +} diff --git a/cmd/configsetup/default_config.go b/cmd/configsetup/default_config.go new file mode 100644 index 00000000..247ab438 --- /dev/null +++ b/cmd/configsetup/default_config.go @@ -0,0 +1,239 @@ +package configsetup + +import ( + "fmt" + "log" + "strings" + + codacyclient "codacy/cli-v2/codacy-client" + "codacy/cli-v2/config" + "codacy/cli-v2/domain" + "codacy/cli-v2/plugins" + "codacy/cli-v2/tools" +) + +// KeepToolsWithLatestVersion filters the tools to keep only the latest version of each tool family. +func KeepToolsWithLatestVersion(tools []domain.Tool) ( + toolsWithLatestVersion []domain.Tool, + uuidToName map[string]string, + familyToVersions map[string][]string, +) { + latestTools := map[string]domain.Tool{} + uuidToName = map[string]string{} + seen := map[string][]domain.Tool{} + familyToVersions = map[string][]string{} + + for _, tool := range tools { + meta, ok := domain.SupportedToolsMetadata[tool.Uuid] + if !ok { + continue + } + + // Track all tools seen per family + seen[meta.Name] = append(seen[meta.Name], tool) + + // Pick the best version + current, exists := latestTools[meta.Name] + if !exists || domain.SupportedToolsMetadata[current.Uuid].Priority > meta.Priority { + latestTools[meta.Name] = tool + uuidToName[tool.Uuid] = meta.Name + } + } + + // Populate final list and version map for logging + for family, tools := range seen { + var versions []string + for _, t := range tools { + v := t.Version + if v == "" { + v = "(unknown)" + } + versions = append(versions, v) + } + familyToVersions[family] = versions + } + + for _, tool := range latestTools { + toolsWithLatestVersion = append(toolsWithLatestVersion, tool) + } + + return +} + +// BuildDefaultConfigurationFiles creates default configuration files for all tools +func BuildDefaultConfigurationFiles(toolsConfigDir string, flags domain.InitFlags) error { + // Get default tool versions to determine correct UUIDs + defaultVersions := plugins.GetToolVersions() + + // Get unique tool names from metadata + toolNames := make(map[string]struct{}) + for _, meta := range domain.SupportedToolsMetadata { + toolNames[meta.Name] = struct{}{} + } + + // Convert tool names to correct UUIDs based on versions + var allUUIDs []string + for toolName := range toolNames { + uuid := selectCorrectToolUUID(toolName, defaultVersions) + if uuid != "" { + allUUIDs = append(allUUIDs, uuid) + } + } + + return createToolConfigurationsForUUIDs(allUUIDs, toolsConfigDir, flags) +} + +// CreateConfigurationFilesForDiscoveredTools creates tool configuration files for discovered tools +func CreateConfigurationFilesForDiscoveredTools(discoveredToolNames map[string]struct{}, toolsConfigDir string, initFlags domain.InitFlags) error { + // Determine CLI mode + currentCliMode, err := config.Config.GetCliMode() + if err != nil { + log.Printf("Warning: Could not determine CLI mode: %v. Assuming local mode for tool configuration creation.", err) + currentCliMode = "local" // Default to local + } + + if currentCliMode == "remote" && initFlags.ApiToken != "" { + // Remote mode - create configurations based on cloud repository settings + return createRemoteToolConfigurationsForDiscovered(discoveredToolNames, initFlags) + } else { + // Local mode - create default configurations for discovered tools + return createDefaultConfigurationsForSpecificTools(discoveredToolNames, toolsConfigDir, initFlags) + } +} + +// createRemoteToolConfigurationsForDiscovered creates tool configurations for remote mode based on cloud settings +func createRemoteToolConfigurationsForDiscovered(discoveredToolNames map[string]struct{}, initFlags domain.InitFlags) error { + + // Get repository tools from API + apiTools, err := tools.GetRepositoryTools(initFlags) + if err != nil { + return fmt.Errorf("failed to get repository tools from cloud: %w", err) + } + + // Filter to only tools that were discovered and enabled in cloud + var enabledDiscoveredTools []domain.Tool + for _, tool := range apiTools { + if tool.Settings.Enabled { + if meta, ok := domain.SupportedToolsMetadata[tool.Uuid]; ok { + if _, discovered := discoveredToolNames[meta.Name]; discovered { + enabledDiscoveredTools = append(enabledDiscoveredTools, tool) + } + } + } + } + + if len(enabledDiscoveredTools) == 0 { + fmt.Println("No discovered tools are enabled in cloud configuration.") + return nil + } + + // Filter out tools that use their own configuration files + configuredTools := tools.FilterToolsByConfigUsage(enabledDiscoveredTools) + + fmt.Printf("Creating configurations for %d discovered tools enabled in cloud...\n", len(configuredTools)) + + // Create configuration files for each tool using existing logic + return createToolConfigurationFiles(configuredTools, initFlags) +} + +// selectCorrectToolUUID selects the correct UUID for a tool based on its version +func selectCorrectToolUUID(toolName string, defaultVersions map[string]string) string { + version, hasVersion := defaultVersions[toolName] + + // Special case for PMD: choose PMD7 UUID for version 7.x, PMD UUID for version 6.x + if toolName == "pmd" && hasVersion { + if strings.HasPrefix(version, "7.") { + return domain.PMD7 + } else { + return domain.PMD + } + } + + // Special case for ESLint: choose ESLint9 UUID for version 9.x, ESLint UUID for older versions + if toolName == "eslint" && hasVersion { + if strings.HasPrefix(version, "9.") { + return domain.ESLint9 + } else { + return domain.ESLint + } + } + + // For other tools, find the first matching UUID + for uuid, meta := range domain.SupportedToolsMetadata { + if meta.Name == toolName { + return uuid + } + } + + return "" +} + +// createDefaultConfigurationsForSpecificTools creates default configurations for specific tools only +func createDefaultConfigurationsForSpecificTools(discoveredToolNames map[string]struct{}, toolsConfigDir string, initFlags domain.InitFlags) error { + fmt.Printf("Creating default configurations for %d discovered tools...\n", len(discoveredToolNames)) + + // Get default tool versions to determine correct UUIDs + defaultVersions := plugins.GetToolVersions() + + // Convert tool names to UUIDs, selecting the correct UUID based on version + var discoveredUUIDs []string + for toolName := range discoveredToolNames { + uuid := selectCorrectToolUUID(toolName, defaultVersions) + if uuid != "" { + discoveredUUIDs = append(discoveredUUIDs, uuid) + } + } + + if len(discoveredUUIDs) == 0 { + log.Printf("Warning: No recognized tools found among discovered tools") + return nil + } + + // Create configurations for discovered tools only + return createToolConfigurationsForUUIDs(discoveredUUIDs, toolsConfigDir, initFlags) +} + +// createToolConfigurationsForUUIDs creates tool configurations for specific UUIDs +func createToolConfigurationsForUUIDs(uuids []string, toolsConfigDir string, initFlags domain.InitFlags) error { + for _, uuid := range uuids { + patternsConfig, err := codacyclient.GetDefaultToolPatternsConfig(initFlags, uuid, true) + if err != nil { + logToolConfigWarning(uuid, "Failed to get default patterns", err) + continue + } + + if err := createSingleToolConfiguration(uuid, patternsConfig, toolsConfigDir); err != nil { + logToolConfigWarning(uuid, "Failed to create configuration", err) + continue + } + + // Print success message + if meta, ok := domain.SupportedToolsMetadata[uuid]; ok { + fmt.Printf("Created %s configuration\n", meta.Name) + } + } + + return nil +} + +// logToolConfigWarning logs a warning message for tool configuration issues +func logToolConfigWarning(uuid, message string, err error) { + if meta, ok := domain.SupportedToolsMetadata[uuid]; ok { + log.Printf("Warning: %s for %s: %v", message, meta.Name, err) + } else { + log.Printf("Warning: %s for UUID %s: %v", message, uuid, err) + } +} + +// createSingleToolConfiguration creates a single tool configuration file based on UUID using the registry +func createSingleToolConfiguration(uuid string, patternsConfig []domain.PatternConfiguration, toolsConfigDir string) error { + creator, exists := toolConfigRegistry[uuid] + if !exists { + if meta, ok := domain.SupportedToolsMetadata[uuid]; ok { + return fmt.Errorf("configuration creation not implemented for tool %s", meta.Name) + } + return fmt.Errorf("configuration creation not implemented for UUID %s", uuid) + } + + return creator.CreateConfig(toolsConfigDir, patternsConfig) +} diff --git a/cmd/configsetup/repository_config.go b/cmd/configsetup/repository_config.go new file mode 100644 index 00000000..075fe09c --- /dev/null +++ b/cmd/configsetup/repository_config.go @@ -0,0 +1,160 @@ +package configsetup + +import ( + "fmt" + "os" + "path/filepath" + "strings" + + codacyclient "codacy/cli-v2/codacy-client" + "codacy/cli-v2/config" + "codacy/cli-v2/constants" + "codacy/cli-v2/domain" + "codacy/cli-v2/tools" +) + +func BuildRepositoryConfigurationFiles(flags domain.InitFlags) error { + 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, constants.DefaultDirPerms); err != nil { + return fmt.Errorf("failed to create tools-configs directory: %w", err) + } + + // Clear any previous configuration files + if err := CleanConfigDirectory(toolsConfigDir); err != nil { + return fmt.Errorf("failed to clean configuration directory: %w", err) + } + + apiTools, err := tools.GetRepositoryTools(flags) + if err != nil { + return err + } + + toolsWithLatestVersion, uuidToName, familyToVersions := KeepToolsWithLatestVersion(apiTools) + + logVersionConflicts(familyToVersions, toolsWithLatestVersion) + + // Create main config files with all enabled API tools (including cli-config.yaml) + if err := CreateConfigurationFiles(toolsWithLatestVersion, false, flags); err != nil { + return err + } + + // Generate languages configuration based on API tools response (after cli-config.yaml is created) + if err := tools.CreateLanguagesConfigFile(toolsWithLatestVersion, toolsConfigDir, uuidToName, flags); err != nil { + return fmt.Errorf("failed to create languages configuration file: %w", err) + } + + // Filter out any tools that use configuration file + configuredToolsWithUI := tools.FilterToolsByConfigUsage(toolsWithLatestVersion) + + // Generate config files for tools not using their own config file + return createToolConfigurationFiles(configuredToolsWithUI, flags) +} + +// logVersionConflicts logs warnings about multiple versions of the same tool family +func logVersionConflicts(familyToVersions map[string][]string, toolsWithLatestVersion []domain.Tool) { + for family, versions := range familyToVersions { + if len(versions) > 1 { + kept := ", " + for _, tool := range toolsWithLatestVersion { + if domain.SupportedToolsMetadata[tool.Uuid].Name == family { + kept = tool.Version + break + } + } + fmt.Printf("⚠️ Multiple versions of '%s' detected: [%s], keeping %s\n", family, strings.Join(versions, ", "), kept) + } + } +} + +// createToolConfigurationFiles creates configuration files for the given tools +func createToolConfigurationFiles(tools []domain.Tool, flags domain.InitFlags) error { + for _, tool := range tools { + apiToolConfigurations, err := codacyclient.GetRepositoryToolPatterns(flags, tool.Uuid) + if err != nil { + fmt.Println("Error unmarshaling tool configurations:", err) + return err + } + + if err := createToolFileConfiguration(tool, apiToolConfigurations); err != nil { + return err + } + } + return nil +} + +// CreateToolConfigurationFile creates a configuration file for a single tool +func CreateToolConfigurationFile(toolName string, flags domain.InitFlags) error { + // Find the tool UUID by tool name + toolUuid := getToolUuidByName(toolName) + if toolUuid == "" { + return fmt.Errorf("tool '%s' not found in supported tools", toolName) + } + + patternsConfig, err := codacyclient.GetDefaultToolPatternsConfig(flags, toolUuid, true) + if err != nil { + return fmt.Errorf("failed to get default patterns: %w", err) + } + + // Get the tool object to pass to createToolFileConfiguration + tool := domain.Tool{Uuid: toolUuid} + return createToolFileConfiguration(tool, patternsConfig) +} + +// getToolUuidByName finds the UUID for a tool given its name +func getToolUuidByName(toolName string) string { + for uuid, toolInfo := range domain.SupportedToolsMetadata { + if toolInfo.Name == toolName { + return uuid + } + } + return "" +} + +// createToolFileConfiguration creates a configuration file for a single tool using the registry +func createToolFileConfiguration(tool domain.Tool, patternConfiguration []domain.PatternConfiguration) error { + creator, exists := toolConfigRegistry[tool.Uuid] + if !exists { + // Tool doesn't have a configuration creator - this is not an error + return nil + } + + toolsConfigDir := config.Config.ToolsConfigDirectory() + + // Ensure the tools-configs directory exists + if err := os.MkdirAll(toolsConfigDir, constants.DefaultDirPerms); err != nil { + return fmt.Errorf("failed to create tools-configs directory: %w", err) + } + + return creator.CreateConfig(toolsConfigDir, patternConfiguration) +} + +// CleanConfigDirectory removes all previous configuration files in the tools-configs directory +func CleanConfigDirectory(toolsConfigDir string) error { + // Check if directory exists + if _, err := os.Stat(toolsConfigDir); os.IsNotExist(err) { + return nil // Directory doesn't exist, nothing to clean + } + + // Read directory contents + entries, err := os.ReadDir(toolsConfigDir) + if err != nil { + return fmt.Errorf("failed to read config directory: %w", err) + } + + // Remove all files + for _, entry := range entries { + if !entry.IsDir() { // Only remove files, not subdirectories + filePath := filepath.Join(toolsConfigDir, entry.Name()) + if err := os.Remove(filePath); err != nil { + return fmt.Errorf("failed to remove file %s: %w", filePath, err) + } + } + } + + fmt.Println("Cleaned previous configuration files") + return nil +} diff --git a/cmd/configsetup/setup.go b/cmd/configsetup/setup.go index d19abe95..4bb59a82 100644 --- a/cmd/configsetup/setup.go +++ b/cmd/configsetup/setup.go @@ -1,25 +1,6 @@ package configsetup -import ( - "fmt" - "log" - "os" - "path/filepath" - "sort" - "strings" - - codacyclient "codacy/cli-v2/codacy-client" - "codacy/cli-v2/config" - "codacy/cli-v2/constants" - "codacy/cli-v2/domain" - "codacy/cli-v2/plugins" - "codacy/cli-v2/tools" - "codacy/cli-v2/tools/lizard" - "codacy/cli-v2/tools/pylint" - reviveTool "codacy/cli-v2/tools/revive" - - "gopkg.in/yaml.v3" -) +import "codacy/cli-v2/domain" // ToolConfigCreator defines the interface for tool configuration creators type ToolConfigCreator interface { @@ -27,751 +8,3 @@ type ToolConfigCreator interface { GetConfigFileName() string GetToolName() string } - -// toolConfigRegistry maps tool UUIDs to their configuration creators -var toolConfigRegistry = map[string]ToolConfigCreator{ - domain.ESLint: &eslintConfigCreator{}, - domain.ESLint9: &eslintConfigCreator{}, - domain.Trivy: &trivyConfigCreator{}, - domain.PMD: &pmdConfigCreator{}, - domain.PMD7: &pmd7ConfigCreator{}, - domain.PyLint: &pylintConfigCreator{}, - domain.DartAnalyzer: &dartAnalyzerConfigCreator{}, - domain.Semgrep: &semgrepConfigCreator{}, - domain.Lizard: &lizardConfigCreator{}, - domain.Revive: &reviveConfigCreator{}, -} - -// writeConfigFile is a helper function to write configuration files with consistent error handling -func writeConfigFile(filePath string, content []byte) error { - return os.WriteFile(filePath, content, constants.DefaultFilePerms) -} - -// eslintConfigCreator implements ToolConfigCreator for ESLint -type eslintConfigCreator struct{} - -func (e *eslintConfigCreator) CreateConfig(toolsConfigDir string, patterns []domain.PatternConfiguration) error { - err := tools.CreateEslintConfig(toolsConfigDir, patterns) - if err == nil { - fmt.Println("ESLint configuration created based on Codacy settings. Ignoring plugin rules. ESLint plugins are not supported yet.") - } - return err -} - -func (e *eslintConfigCreator) GetConfigFileName() string { return "eslint.config.mjs" } -func (e *eslintConfigCreator) GetToolName() string { return "ESLint" } - -// trivyConfigCreator implements ToolConfigCreator for Trivy -type trivyConfigCreator struct{} - -func (t *trivyConfigCreator) CreateConfig(toolsConfigDir string, patterns []domain.PatternConfiguration) error { - configString := tools.CreateTrivyConfig(patterns) - err := writeConfigFile(filepath.Join(toolsConfigDir, constants.TrivyConfigFileName), []byte(configString)) - if err == nil { - fmt.Println("Trivy configuration created based on Codacy settings") - } - return err -} - -func (t *trivyConfigCreator) GetConfigFileName() string { return constants.TrivyConfigFileName } -func (t *trivyConfigCreator) GetToolName() string { return "Trivy" } - -// pmdConfigCreator implements ToolConfigCreator for PMD -type pmdConfigCreator struct{} - -func (p *pmdConfigCreator) CreateConfig(toolsConfigDir string, patterns []domain.PatternConfiguration) error { - configString := tools.CreatePmd6Config(patterns) - return writeConfigFile(filepath.Join(toolsConfigDir, constants.PMDConfigFileName), []byte(configString)) -} - -func (p *pmdConfigCreator) GetConfigFileName() string { return constants.PMDConfigFileName } -func (p *pmdConfigCreator) GetToolName() string { return "PMD" } - -// pmd7ConfigCreator implements ToolConfigCreator for PMD7 -type pmd7ConfigCreator struct{} - -func (p *pmd7ConfigCreator) CreateConfig(toolsConfigDir string, patterns []domain.PatternConfiguration) error { - configString := tools.CreatePmd7Config(patterns) - err := writeConfigFile(filepath.Join(toolsConfigDir, constants.PMDConfigFileName), []byte(configString)) - if err == nil { - fmt.Println("PMD7 configuration created based on Codacy settings") - } - return err -} - -func (p *pmd7ConfigCreator) GetConfigFileName() string { return constants.PMDConfigFileName } -func (p *pmd7ConfigCreator) GetToolName() string { return "PMD7" } - -// pylintConfigCreator implements ToolConfigCreator for Pylint -type pylintConfigCreator struct{} - -func (p *pylintConfigCreator) CreateConfig(toolsConfigDir string, patterns []domain.PatternConfiguration) error { - configString := pylint.GeneratePylintRC(patterns) - err := writeConfigFile(filepath.Join(toolsConfigDir, constants.PylintConfigFileName), []byte(configString)) - if err == nil { - fmt.Println("Pylint configuration created based on Codacy settings") - } - return err -} - -func (p *pylintConfigCreator) GetConfigFileName() string { return constants.PylintConfigFileName } -func (p *pylintConfigCreator) GetToolName() string { return "Pylint" } - -// dartAnalyzerConfigCreator implements ToolConfigCreator for Dart Analyzer -type dartAnalyzerConfigCreator struct{} - -func (d *dartAnalyzerConfigCreator) CreateConfig(toolsConfigDir string, patterns []domain.PatternConfiguration) error { - configString := tools.CreateDartAnalyzerConfig(patterns) - err := writeConfigFile(filepath.Join(toolsConfigDir, constants.DartAnalyzerConfigFileName), []byte(configString)) - if err == nil { - fmt.Println("Dart configuration created based on Codacy settings") - } - return err -} - -func (d *dartAnalyzerConfigCreator) GetConfigFileName() string { - return constants.DartAnalyzerConfigFileName -} -func (d *dartAnalyzerConfigCreator) GetToolName() string { return "Dart Analyzer" } - -// semgrepConfigCreator implements ToolConfigCreator for Semgrep -type semgrepConfigCreator struct{} - -func (s *semgrepConfigCreator) CreateConfig(toolsConfigDir string, patterns []domain.PatternConfiguration) error { - configData, err := tools.GetSemgrepConfig(patterns) - if err != nil { - return fmt.Errorf("failed to create Semgrep config: %v", err) - } - err = writeConfigFile(filepath.Join(toolsConfigDir, constants.SemgrepConfigFileName), configData) - if err == nil { - fmt.Println("Semgrep configuration created based on Codacy settings") - } - return err -} - -func (s *semgrepConfigCreator) GetConfigFileName() string { return constants.SemgrepConfigFileName } -func (s *semgrepConfigCreator) GetToolName() string { return "Semgrep" } - -// lizardConfigCreator implements ToolConfigCreator for Lizard -type lizardConfigCreator struct{} - -func (l *lizardConfigCreator) CreateConfig(toolsConfigDir string, patterns []domain.PatternConfiguration) error { - patternDefinitions := make([]domain.PatternDefinition, len(patterns)) - for i, pattern := range patterns { - patternDefinitions[i] = pattern.PatternDefinition - } - err := lizard.CreateLizardConfig(toolsConfigDir, patternDefinitions) - if err != nil { - return fmt.Errorf("failed to create Lizard configuration: %w", err) - } - fmt.Println("Lizard configuration created based on Codacy settings") - return nil -} - -func (l *lizardConfigCreator) GetConfigFileName() string { return "lizard.json" } -func (l *lizardConfigCreator) GetToolName() string { return "Lizard" } - -// reviveConfigCreator implements ToolConfigCreator for Revive -type reviveConfigCreator struct{} - -func (r *reviveConfigCreator) CreateConfig(toolsConfigDir string, patterns []domain.PatternConfiguration) error { - err := createReviveConfigFile(patterns, toolsConfigDir) - if err == nil { - fmt.Println("Revive configuration created based on Codacy settings") - } - return err -} - -func (r *reviveConfigCreator) GetConfigFileName() string { return "revive.toml" } -func (r *reviveConfigCreator) GetToolName() string { return "Revive" } - -func CreateLanguagesConfigFileLocal(toolsConfigDir string) error { - // Build tool language configurations from API - configTools, err := tools.BuildLanguagesConfigFromAPI() - if err != nil { - return fmt.Errorf("failed to build languages config from API: %w", err) - } - - // Create the config structure - config := domain.LanguagesConfig{ - Tools: configTools, - } - - // Marshal to YAML - data, err := yaml.Marshal(config) - if err != nil { - return fmt.Errorf("failed to marshal languages config to YAML: %w", err) - } - - return writeConfigFile(filepath.Join(toolsConfigDir, constants.LanguagesConfigFileName), data) -} - -func CreateGitIgnoreFile() error { - gitIgnorePath := filepath.Join(config.Config.LocalCodacyDirectory(), constants.GitIgnoreFileName) - content := "# Codacy CLI\ntools-configs/\n.gitignore\ncli-config.yaml\nlogs/\n" - return writeConfigFile(gitIgnorePath, []byte(content)) -} - -func CreateConfigurationFiles(tools []domain.Tool, cliLocalMode bool, flags domain.InitFlags) error { - // Create project config file - configContent := ConfigFileTemplate(tools) - if err := writeConfigFile(config.Config.ProjectConfigFile(), []byte(configContent)); err != nil { - return fmt.Errorf("failed to write project config file: %w", err) - } - - // Create CLI config file - cliConfigContent := buildCliConfigContent(cliLocalMode, flags) - if err := writeConfigFile(config.Config.CliConfigFile(), []byte(cliConfigContent)); err != nil { - return fmt.Errorf("failed to write CLI config file: %w", err) - } - - return nil -} - -// buildCliConfigContent creates the CLI configuration content -func buildCliConfigContent(cliLocalMode bool, initFlags domain.InitFlags) string { - if cliLocalMode { - return fmt.Sprintf("mode: local") - } else { - return fmt.Sprintf("mode: remote\nprovider: %s\norganization: %s\nrepository: %s", initFlags.Provider, initFlags.Organization, initFlags.Repository) - } -} - -// RuntimePluginConfig holds the structure of the runtime plugin.yaml file -type RuntimePluginConfig struct { - Name string `yaml:"name"` - Description string `yaml:"description"` - DefaultVersion string `yaml:"default_version"` -} - -func ConfigFileTemplate(tools []domain.Tool) string { - toolsMap := make(map[string]bool) - toolVersions := make(map[string]string) - neededRuntimes := make(map[string]bool) - - toolsWithLatestVersion, _, _ := KeepToolsWithLatestVersion(tools) - - // Get versions and runtime dependencies - defaultVersions := plugins.GetToolVersions() - runtimeVersions := plugins.GetRuntimeVersions() - runtimeDependencies := plugins.GetToolRuntimeDependencies() - - // Process enabled tools - for _, tool := range toolsWithLatestVersion { - toolsMap[tool.Uuid] = true - toolVersions[tool.Uuid] = getToolVersion(tool, defaultVersions) - addRequiredRuntime(tool.Uuid, neededRuntimes, runtimeDependencies) - } - - var sb strings.Builder - - // Build runtimes section - buildRuntimesSection(&sb, tools, neededRuntimes, runtimeVersions, runtimeDependencies) - - // Build tools section - buildToolsSection(&sb, tools, toolsMap, toolVersions, defaultVersions) - - return sb.String() -} - -// getToolVersion returns the version for a tool, preferring tool.Version over default -func getToolVersion(tool domain.Tool, defaultVersions map[string]string) string { - if tool.Version != "" { - return tool.Version - } - if meta, ok := domain.SupportedToolsMetadata[tool.Uuid]; ok { - if defaultVersion, ok := defaultVersions[meta.Name]; ok { - return defaultVersion - } - } - return "" -} - -// addRequiredRuntime adds the runtime requirement for a tool -func addRequiredRuntime(toolUuid string, neededRuntimes map[string]bool, runtimeDependencies map[string]string) { - if meta, ok := domain.SupportedToolsMetadata[toolUuid]; ok { - if runtime, ok := runtimeDependencies[meta.Name]; ok { - if meta.Name == "dartanalyzer" { - // For dartanalyzer, default to dart runtime - neededRuntimes["dart"] = true - } else { - neededRuntimes[runtime] = true - } - } - } -} - -// buildRuntimesSection builds the runtimes section of the configuration -func buildRuntimesSection(sb *strings.Builder, tools []domain.Tool, neededRuntimes map[string]bool, runtimeVersions map[string]string, runtimeDependencies map[string]string) { - sb.WriteString("runtimes:\n") - - if len(tools) == 0 { - // In local mode with no tools specified, include all necessary runtimes - addAllSupportedRuntimes(neededRuntimes, runtimeDependencies) - } - - writeRuntimesList(sb, neededRuntimes, runtimeVersions) -} - -// addAllSupportedRuntimes adds all runtimes needed by supported tools -func addAllSupportedRuntimes(neededRuntimes map[string]bool, runtimeDependencies map[string]string) { - supportedTools, err := plugins.GetSupportedTools() - if err != nil { - log.Printf("Warning: failed to get supported tools: %v", err) - return - } - - for toolName := range supportedTools { - if runtime, ok := runtimeDependencies[toolName]; ok { - if toolName == "dartanalyzer" { - neededRuntimes["dart"] = true - } else { - neededRuntimes[runtime] = true - } - } - } -} - -// writeRuntimesList writes the sorted runtimes list to the string builder -func writeRuntimesList(sb *strings.Builder, neededRuntimes map[string]bool, runtimeVersions map[string]string) { - var sortedRuntimes []string - for runtime := range neededRuntimes { - sortedRuntimes = append(sortedRuntimes, runtime) - } - sort.Strings(sortedRuntimes) - - for _, runtime := range sortedRuntimes { - sb.WriteString(fmt.Sprintf(" - %s@%s\n", runtime, runtimeVersions[runtime])) - } -} - -// buildToolsSection builds the tools section of the configuration -func buildToolsSection(sb *strings.Builder, tools []domain.Tool, toolsMap map[string]bool, toolVersions map[string]string, defaultVersions map[string]string) { - sb.WriteString("tools:\n") - - if len(tools) > 0 { - writeEnabledTools(sb, toolsMap, toolVersions) - } else { - writeAllSupportedTools(sb, defaultVersions) - } -} - -// writeEnabledTools writes the enabled tools to the string builder -func writeEnabledTools(sb *strings.Builder, toolsMap map[string]bool, toolVersions map[string]string) { - var sortedTools []string - for uuid, meta := range domain.SupportedToolsMetadata { - if toolsMap[uuid] { - sortedTools = append(sortedTools, meta.Name) - } - } - sort.Strings(sortedTools) - - for _, name := range sortedTools { - for uuid, meta := range domain.SupportedToolsMetadata { - if meta.Name == name && toolsMap[uuid] { - version := toolVersions[uuid] - sb.WriteString(fmt.Sprintf(" - %s@%s\n", name, version)) - break - } - } - } -} - -// writeAllSupportedTools writes all supported tools to the string builder -func writeAllSupportedTools(sb *strings.Builder, defaultVersions map[string]string) { - supportedTools, err := plugins.GetSupportedTools() - if err != nil { - log.Printf("Warning: failed to get supported tools: %v", err) - return - } - - var sortedTools []string - for toolName := range supportedTools { - if version, ok := defaultVersions[toolName]; ok && version != "" { - sortedTools = append(sortedTools, toolName) - } - } - sort.Strings(sortedTools) - - for _, toolName := range sortedTools { - if version, ok := defaultVersions[toolName]; ok { - sb.WriteString(fmt.Sprintf(" - %s@%s\n", toolName, version)) - } - } -} - -func BuildRepositoryConfigurationFiles(flags domain.InitFlags) error { - 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, constants.DefaultDirPerms); err != nil { - return fmt.Errorf("failed to create tools-configs directory: %w", err) - } - - // Clear any previous configuration files - if err := CleanConfigDirectory(toolsConfigDir); err != nil { - return fmt.Errorf("failed to clean configuration directory: %w", err) - } - - apiTools, err := tools.GetRepositoryTools(flags) - if err != nil { - return err - } - - toolsWithLatestVersion, uuidToName, familyToVersions := KeepToolsWithLatestVersion(apiTools) - - logVersionConflicts(familyToVersions, toolsWithLatestVersion) - - // Create main config files with all enabled API tools (including cli-config.yaml) - if err := CreateConfigurationFiles(toolsWithLatestVersion, false, flags); err != nil { - return err - } - - // Generate languages configuration based on API tools response (after cli-config.yaml is created) - if err := tools.CreateLanguagesConfigFile(toolsWithLatestVersion, toolsConfigDir, uuidToName, flags); err != nil { - return fmt.Errorf("failed to create languages configuration file: %w", err) - } - - // Filter out any tools that use configuration file - configuredToolsWithUI := tools.FilterToolsByConfigUsage(toolsWithLatestVersion) - - // Generate config files for tools not using their own config file - return createToolConfigurationFiles(configuredToolsWithUI, flags) -} - -// logVersionConflicts logs warnings about multiple versions of the same tool family -func logVersionConflicts(familyToVersions map[string][]string, toolsWithLatestVersion []domain.Tool) { - for family, versions := range familyToVersions { - if len(versions) > 1 { - kept := ", " - for _, tool := range toolsWithLatestVersion { - if domain.SupportedToolsMetadata[tool.Uuid].Name == family { - kept = tool.Version - break - } - } - fmt.Printf("⚠️ Multiple versions of '%s' detected: [%s], keeping %s\n", family, strings.Join(versions, ", "), kept) - } - } -} - -// createToolConfigurationFiles creates configuration files for the given tools -func createToolConfigurationFiles(tools []domain.Tool, flags domain.InitFlags) error { - for _, tool := range tools { - apiToolConfigurations, err := codacyclient.GetRepositoryToolPatterns(flags, tool.Uuid) - if err != nil { - fmt.Println("Error unmarshaling tool configurations:", err) - return err - } - - if err := createToolFileConfiguration(tool, apiToolConfigurations); err != nil { - return err - } - } - return nil -} - -// CreateToolConfigurationFile creates a configuration file for a single tool -func CreateToolConfigurationFile(toolName string, flags domain.InitFlags) error { - // Find the tool UUID by tool name - toolUuid := getToolUuidByName(toolName) - if toolUuid == "" { - return fmt.Errorf("tool '%s' not found in supported tools", toolName) - } - - patternsConfig, err := codacyclient.GetDefaultToolPatternsConfig(flags, toolUuid, true) - if err != nil { - return fmt.Errorf("failed to get default patterns: %w", err) - } - - // Get the tool object to pass to createToolFileConfiguration - tool := domain.Tool{Uuid: toolUuid} - return createToolFileConfiguration(tool, patternsConfig) -} - -// getToolUuidByName finds the UUID for a tool given its name -func getToolUuidByName(toolName string) string { - for uuid, toolInfo := range domain.SupportedToolsMetadata { - if toolInfo.Name == toolName { - return uuid - } - } - return "" -} - -// createToolFileConfiguration creates a configuration file for a single tool using the registry -func createToolFileConfiguration(tool domain.Tool, patternConfiguration []domain.PatternConfiguration) error { - creator, exists := toolConfigRegistry[tool.Uuid] - if !exists { - // Tool doesn't have a configuration creator - this is not an error - return nil - } - - toolsConfigDir := config.Config.ToolsConfigDirectory() - - // Ensure the tools-configs directory exists - if err := os.MkdirAll(toolsConfigDir, constants.DefaultDirPerms); err != nil { - return fmt.Errorf("failed to create tools-configs directory: %w", err) - } - - return creator.CreateConfig(toolsConfigDir, patternConfiguration) -} - -// CleanConfigDirectory removes all previous configuration files in the tools-configs directory -func CleanConfigDirectory(toolsConfigDir string) error { - // Check if directory exists - if _, err := os.Stat(toolsConfigDir); os.IsNotExist(err) { - return nil // Directory doesn't exist, nothing to clean - } - - // Read directory contents - entries, err := os.ReadDir(toolsConfigDir) - if err != nil { - return fmt.Errorf("failed to read config directory: %w", err) - } - - // Remove all files - for _, entry := range entries { - if !entry.IsDir() { // Only remove files, not subdirectories - filePath := filepath.Join(toolsConfigDir, entry.Name()) - if err := os.Remove(filePath); err != nil { - return fmt.Errorf("failed to remove file %s: %w", filePath, err) - } - } - } - - fmt.Println("Cleaned previous configuration files") - return nil -} - -func createReviveConfigFile(config []domain.PatternConfiguration, toolsConfigDir string) error { - reviveConfigurationString := reviveTool.GenerateReviveConfig(config) - return os.WriteFile(filepath.Join(toolsConfigDir, "revive.toml"), []byte(reviveConfigurationString), constants.DefaultFilePerms) -} - -// BuildDefaultConfigurationFiles creates default configuration files for all tools -func BuildDefaultConfigurationFiles(toolsConfigDir string, flags domain.InitFlags) error { - // Get default tool versions to determine correct UUIDs - defaultVersions := plugins.GetToolVersions() - - // Get unique tool names from metadata - toolNames := make(map[string]struct{}) - for _, meta := range domain.SupportedToolsMetadata { - toolNames[meta.Name] = struct{}{} - } - - // Convert tool names to correct UUIDs based on versions - var allUUIDs []string - for toolName := range toolNames { - uuid := selectCorrectToolUUID(toolName, defaultVersions) - if uuid != "" { - allUUIDs = append(allUUIDs, uuid) - } - } - - return createToolConfigurationsForUUIDs(allUUIDs, toolsConfigDir, flags) -} - -// KeepToolsWithLatestVersion filters the tools to keep only the latest version of each tool family. -func KeepToolsWithLatestVersion(tools []domain.Tool) ( - toolsWithLatestVersion []domain.Tool, - uuidToName map[string]string, - familyToVersions map[string][]string, -) { - latestTools := map[string]domain.Tool{} - uuidToName = map[string]string{} - seen := map[string][]domain.Tool{} - familyToVersions = map[string][]string{} - - for _, tool := range tools { - meta, ok := domain.SupportedToolsMetadata[tool.Uuid] - if !ok { - continue - } - - // Track all tools seen per family - seen[meta.Name] = append(seen[meta.Name], tool) - - // Pick the best version - current, exists := latestTools[meta.Name] - if !exists || domain.SupportedToolsMetadata[current.Uuid].Priority > meta.Priority { - latestTools[meta.Name] = tool - uuidToName[tool.Uuid] = meta.Name - } - } - - // Populate final list and version map for logging - for family, tools := range seen { - var versions []string - for _, t := range tools { - v := t.Version - if v == "" { - v = "(unknown)" - } - versions = append(versions, v) - } - familyToVersions[family] = versions - } - - for _, tool := range latestTools { - toolsWithLatestVersion = append(toolsWithLatestVersion, tool) - } - - return -} - -// CreateConfigurationFilesForDiscoveredTools creates tool configuration files for discovered tools -func CreateConfigurationFilesForDiscoveredTools(discoveredToolNames map[string]struct{}, toolsConfigDir string, initFlags domain.InitFlags) error { - // Determine CLI mode - currentCliMode, err := config.Config.GetCliMode() - if err != nil { - log.Printf("Warning: Could not determine CLI mode: %v. Assuming local mode for tool configuration creation.", err) - currentCliMode = "local" // Default to local - } - - if currentCliMode == "remote" && initFlags.ApiToken != "" { - // Remote mode - create configurations based on cloud repository settings - return createRemoteToolConfigurationsForDiscovered(discoveredToolNames, initFlags) - } else { - // Local mode - create default configurations for discovered tools - return createDefaultConfigurationsForSpecificTools(discoveredToolNames, toolsConfigDir, initFlags) - } -} - -// createRemoteToolConfigurationsForDiscovered creates tool configurations for remote mode based on cloud settings -func createRemoteToolConfigurationsForDiscovered(discoveredToolNames map[string]struct{}, initFlags domain.InitFlags) error { - // Get repository tools from API - apiTools, err := tools.GetRepositoryTools(initFlags) - if err != nil { - return fmt.Errorf("failed to get repository tools from cloud: %w", err) - } - - // Filter to only tools that were discovered and enabled in cloud - var enabledDiscoveredTools []domain.Tool - for _, tool := range apiTools { - if tool.Settings.Enabled { - if meta, ok := domain.SupportedToolsMetadata[tool.Uuid]; ok { - if _, discovered := discoveredToolNames[meta.Name]; discovered { - enabledDiscoveredTools = append(enabledDiscoveredTools, tool) - } - } - } - } - - if len(enabledDiscoveredTools) == 0 { - fmt.Println("No discovered tools are enabled in cloud configuration.") - return nil - } - - // Filter out tools that use their own configuration files - configuredTools := tools.FilterToolsByConfigUsage(enabledDiscoveredTools) - - fmt.Printf("Creating configurations for %d discovered tools enabled in cloud...\n", len(configuredTools)) - - // Create configuration files for each tool using existing logic - return createToolConfigurationFiles(configuredTools, initFlags) -} - -// selectCorrectToolUUID selects the correct UUID for a tool based on its version -func selectCorrectToolUUID(toolName string, defaultVersions map[string]string) string { - version, hasVersion := defaultVersions[toolName] - - // Special case for PMD: choose PMD7 UUID for version 7.x, PMD UUID for version 6.x - if toolName == "pmd" && hasVersion { - if strings.HasPrefix(version, "7.") { - return domain.PMD7 - } else { - return domain.PMD - } - } - - // Special case for ESLint: choose ESLint9 UUID for version 9.x, ESLint UUID for older versions - if toolName == "eslint" && hasVersion { - if strings.HasPrefix(version, "9.") { - return domain.ESLint9 - } else { - return domain.ESLint - } - } - - // For other tools, find the first matching UUID - for uuid, meta := range domain.SupportedToolsMetadata { - if meta.Name == toolName { - return uuid - } - } - - return "" -} - -// createDefaultConfigurationsForSpecificTools creates default configurations for specific tools only -func createDefaultConfigurationsForSpecificTools(discoveredToolNames map[string]struct{}, toolsConfigDir string, initFlags domain.InitFlags) error { - fmt.Printf("Creating default configurations for %d discovered tools...\n", len(discoveredToolNames)) - - // Get default tool versions to determine correct UUIDs - defaultVersions := plugins.GetToolVersions() - - // Convert tool names to UUIDs, selecting the correct UUID based on version - var discoveredUUIDs []string - for toolName := range discoveredToolNames { - uuid := selectCorrectToolUUID(toolName, defaultVersions) - if uuid != "" { - discoveredUUIDs = append(discoveredUUIDs, uuid) - } - } - - if len(discoveredUUIDs) == 0 { - log.Printf("Warning: No recognized tools found among discovered tools") - return nil - } - - // Create configurations for discovered tools only - return createToolConfigurationsForUUIDs(discoveredUUIDs, toolsConfigDir, initFlags) -} - -// createToolConfigurationsForUUIDs creates tool configurations for specific UUIDs -func createToolConfigurationsForUUIDs(uuids []string, toolsConfigDir string, initFlags domain.InitFlags) error { - for _, uuid := range uuids { - patternsConfig, err := codacyclient.GetDefaultToolPatternsConfig(initFlags, uuid, true) - if err != nil { - logToolConfigWarning(uuid, "Failed to get default patterns", err) - continue - } - - if err := createSingleToolConfiguration(uuid, patternsConfig, toolsConfigDir); err != nil { - logToolConfigWarning(uuid, "Failed to create configuration", err) - continue - } - - // Print success message - if meta, ok := domain.SupportedToolsMetadata[uuid]; ok { - fmt.Printf("Created %s configuration\n", meta.Name) - } - } - - return nil -} - -// logToolConfigWarning logs a warning message for tool configuration issues -func logToolConfigWarning(uuid, message string, err error) { - if meta, ok := domain.SupportedToolsMetadata[uuid]; ok { - log.Printf("Warning: %s for %s: %v", message, meta.Name, err) - } else { - log.Printf("Warning: %s for UUID %s: %v", message, uuid, err) - } -} - -// createSingleToolConfiguration creates a single tool configuration file based on UUID using the registry -func createSingleToolConfiguration(uuid string, patternsConfig []domain.PatternConfiguration, toolsConfigDir string) error { - creator, exists := toolConfigRegistry[uuid] - if !exists { - if meta, ok := domain.SupportedToolsMetadata[uuid]; ok { - return fmt.Errorf("configuration creation not implemented for tool %s", meta.Name) - } - return fmt.Errorf("configuration creation not implemented for UUID %s", uuid) - } - - return creator.CreateConfig(toolsConfigDir, patternsConfig) -} diff --git a/cmd/configsetup/tool_creators.go b/cmd/configsetup/tool_creators.go new file mode 100644 index 00000000..21871a10 --- /dev/null +++ b/cmd/configsetup/tool_creators.go @@ -0,0 +1,176 @@ +package configsetup + +import ( + "fmt" + "os" + "path/filepath" + + "codacy/cli-v2/constants" + "codacy/cli-v2/domain" + "codacy/cli-v2/tools" + "codacy/cli-v2/tools/lizard" + "codacy/cli-v2/tools/pylint" + reviveTool "codacy/cli-v2/tools/revive" +) + +// toolConfigRegistry maps tool UUIDs to their configuration creators +var toolConfigRegistry = map[string]ToolConfigCreator{ + domain.ESLint: &eslintConfigCreator{}, + domain.ESLint9: &eslintConfigCreator{}, + domain.Trivy: &trivyConfigCreator{}, + domain.PMD: &pmdConfigCreator{}, + domain.PMD7: &pmd7ConfigCreator{}, + domain.PyLint: &pylintConfigCreator{}, + domain.DartAnalyzer: &dartAnalyzerConfigCreator{}, + domain.Semgrep: &semgrepConfigCreator{}, + domain.Lizard: &lizardConfigCreator{}, + domain.Revive: &reviveConfigCreator{}, +} + +// writeConfigFile is a helper function to write configuration files with consistent error handling +func writeConfigFile(filePath string, content []byte) error { + return os.WriteFile(filePath, content, constants.DefaultFilePerms) +} + +// eslintConfigCreator implements ToolConfigCreator for ESLint +type eslintConfigCreator struct{} + +func (e *eslintConfigCreator) CreateConfig(toolsConfigDir string, patterns []domain.PatternConfiguration) error { + err := tools.CreateEslintConfig(toolsConfigDir, patterns) + if err == nil { + fmt.Println("ESLint configuration created based on Codacy settings. Ignoring plugin rules. ESLint plugins are not supported yet.") + } + return err +} + +func (e *eslintConfigCreator) GetConfigFileName() string { return "eslint.config.mjs" } +func (e *eslintConfigCreator) GetToolName() string { return "ESLint" } + +// trivyConfigCreator implements ToolConfigCreator for Trivy +type trivyConfigCreator struct{} + +func (t *trivyConfigCreator) CreateConfig(toolsConfigDir string, patterns []domain.PatternConfiguration) error { + configString := tools.CreateTrivyConfig(patterns) + err := writeConfigFile(filepath.Join(toolsConfigDir, constants.TrivyConfigFileName), []byte(configString)) + if err == nil { + fmt.Println("Trivy configuration created based on Codacy settings") + } + return err +} + +func (t *trivyConfigCreator) GetConfigFileName() string { return constants.TrivyConfigFileName } +func (t *trivyConfigCreator) GetToolName() string { return "Trivy" } + +// pmdConfigCreator implements ToolConfigCreator for PMD +type pmdConfigCreator struct{} + +func (p *pmdConfigCreator) CreateConfig(toolsConfigDir string, patterns []domain.PatternConfiguration) error { + configString := tools.CreatePmd6Config(patterns) + return writeConfigFile(filepath.Join(toolsConfigDir, constants.PMDConfigFileName), []byte(configString)) +} + +func (p *pmdConfigCreator) GetConfigFileName() string { return constants.PMDConfigFileName } +func (p *pmdConfigCreator) GetToolName() string { return "PMD" } + +// pmd7ConfigCreator implements ToolConfigCreator for PMD7 +type pmd7ConfigCreator struct{} + +func (p *pmd7ConfigCreator) CreateConfig(toolsConfigDir string, patterns []domain.PatternConfiguration) error { + configString := tools.CreatePmd7Config(patterns) + err := writeConfigFile(filepath.Join(toolsConfigDir, constants.PMDConfigFileName), []byte(configString)) + if err == nil { + fmt.Println("PMD7 configuration created based on Codacy settings") + } + return err +} + +func (p *pmd7ConfigCreator) GetConfigFileName() string { return constants.PMDConfigFileName } +func (p *pmd7ConfigCreator) GetToolName() string { return "PMD7" } + +// pylintConfigCreator implements ToolConfigCreator for Pylint +type pylintConfigCreator struct{} + +func (p *pylintConfigCreator) CreateConfig(toolsConfigDir string, patterns []domain.PatternConfiguration) error { + configString := pylint.GeneratePylintRC(patterns) + err := writeConfigFile(filepath.Join(toolsConfigDir, constants.PylintConfigFileName), []byte(configString)) + if err == nil { + fmt.Println("Pylint configuration created based on Codacy settings") + } + return err +} + +func (p *pylintConfigCreator) GetConfigFileName() string { return constants.PylintConfigFileName } +func (p *pylintConfigCreator) GetToolName() string { return "Pylint" } + +// dartAnalyzerConfigCreator implements ToolConfigCreator for Dart Analyzer +type dartAnalyzerConfigCreator struct{} + +func (d *dartAnalyzerConfigCreator) CreateConfig(toolsConfigDir string, patterns []domain.PatternConfiguration) error { + configString := tools.CreateDartAnalyzerConfig(patterns) + err := writeConfigFile(filepath.Join(toolsConfigDir, constants.DartAnalyzerConfigFileName), []byte(configString)) + if err == nil { + fmt.Println("Dart configuration created based on Codacy settings") + } + return err +} + +func (d *dartAnalyzerConfigCreator) GetConfigFileName() string { + return constants.DartAnalyzerConfigFileName +} +func (d *dartAnalyzerConfigCreator) GetToolName() string { return "Dart Analyzer" } + +// semgrepConfigCreator implements ToolConfigCreator for Semgrep +type semgrepConfigCreator struct{} + +func (s *semgrepConfigCreator) CreateConfig(toolsConfigDir string, patterns []domain.PatternConfiguration) error { + configData, err := tools.GetSemgrepConfig(patterns) + if err != nil { + return fmt.Errorf("failed to create Semgrep config: %v", err) + } + err = writeConfigFile(filepath.Join(toolsConfigDir, constants.SemgrepConfigFileName), configData) + if err == nil { + fmt.Println("Semgrep configuration created based on Codacy settings") + } + return err +} + +func (s *semgrepConfigCreator) GetConfigFileName() string { return constants.SemgrepConfigFileName } +func (s *semgrepConfigCreator) GetToolName() string { return "Semgrep" } + +// lizardConfigCreator implements ToolConfigCreator for Lizard +type lizardConfigCreator struct{} + +func (l *lizardConfigCreator) CreateConfig(toolsConfigDir string, patterns []domain.PatternConfiguration) error { + // patternDefinitions := make([]domain.PatternDefinition, len(patterns)) + // for i, pattern := range patterns { + // patternDefinitions[i] = pattern.PatternDefinition + // } + err := lizard.CreateLizardConfig(toolsConfigDir, patterns) + if err != nil { + return fmt.Errorf("failed to create Lizard configuration: %w", err) + } + fmt.Println("Lizard configuration created based on Codacy settings") + return nil +} + +func (l *lizardConfigCreator) GetConfigFileName() string { return "lizard.json" } +func (l *lizardConfigCreator) GetToolName() string { return "Lizard" } + +// reviveConfigCreator implements ToolConfigCreator for Revive +type reviveConfigCreator struct{} + +func (r *reviveConfigCreator) CreateConfig(toolsConfigDir string, patterns []domain.PatternConfiguration) error { + err := createReviveConfigFile(patterns, toolsConfigDir) + if err == nil { + fmt.Println("Revive configuration created based on Codacy settings") + } + return err +} + +func (r *reviveConfigCreator) GetConfigFileName() string { return "revive.toml" } +func (r *reviveConfigCreator) GetToolName() string { return "Revive" } + +func createReviveConfigFile(config []domain.PatternConfiguration, toolsConfigDir string) error { + reviveConfigurationString := reviveTool.GenerateReviveConfig(config) + return os.WriteFile(filepath.Join(toolsConfigDir, "revive.toml"), []byte(reviveConfigurationString), constants.DefaultFilePerms) +} diff --git a/tools/lizard/lizardConfigCreator.go b/tools/lizard/lizardConfigCreator.go index 4871fdea..3153a8c1 100644 --- a/tools/lizard/lizardConfigCreator.go +++ b/tools/lizard/lizardConfigCreator.go @@ -13,29 +13,31 @@ import ( ) // CreateLizardConfig generates a Lizard configuration file content based on the API configuration -func CreateLizardConfig(toolsConfigDir string, patterns []domain.PatternDefinition) error { +func CreateLizardConfig(toolsConfigDir string, patterns []domain.PatternConfiguration) error { patternInfo := make(map[string]map[string]interface{}) for _, pattern := range patterns { - metricType := getMetricTypeFromPatternId(pattern.Id) + patternDefinition := pattern.PatternDefinition + metricType := getMetricTypeFromPatternId(patternDefinition.Id) + if metricType == "" { - fmt.Printf("Warning: Invalid pattern ID format: %s\n", pattern.Id) + fmt.Printf("Warning: Invalid pattern ID format: %s\n", patternDefinition.Id) continue } threshold := getThresholdFromParams(pattern.Parameters) if threshold != 0 { // Create a unique key for this pattern that includes the severity - patternKey := pattern.Id + patternKey := patternDefinition.Id patternInfo[patternKey] = map[string]interface{}{ - "id": pattern.Id, - "category": pattern.Category, - "level": pattern.Level, - "severityLevel": pattern.SeverityLevel, - "title": pattern.Title, - "description": pattern.Description, - "explanation": pattern.Explanation, - "timeToFix": pattern.TimeToFix, + "id": patternDefinition.Id, + "category": patternDefinition.Category, + "level": patternDefinition.Level, + "severityLevel": patternDefinition.SeverityLevel, + "title": patternDefinition.Title, + "description": patternDefinition.Description, + "explanation": patternDefinition.Explanation, + "timeToFix": patternDefinition.TimeToFix, "threshold": threshold, } } From a0e86f4786de274d6c4c9a22ae0b3acc50f693f0 Mon Sep 17 00:00:00 2001 From: Alejandro Rizzo Date: Mon, 20 Oct 2025 15:50:12 +0100 Subject: [PATCH 3/8] remove commented code --- cmd/configsetup/tool_creators.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/cmd/configsetup/tool_creators.go b/cmd/configsetup/tool_creators.go index 21871a10..da95ebd3 100644 --- a/cmd/configsetup/tool_creators.go +++ b/cmd/configsetup/tool_creators.go @@ -141,10 +141,6 @@ func (s *semgrepConfigCreator) GetToolName() string { return "Semgrep" } type lizardConfigCreator struct{} func (l *lizardConfigCreator) CreateConfig(toolsConfigDir string, patterns []domain.PatternConfiguration) error { - // patternDefinitions := make([]domain.PatternDefinition, len(patterns)) - // for i, pattern := range patterns { - // patternDefinitions[i] = pattern.PatternDefinition - // } err := lizard.CreateLizardConfig(toolsConfigDir, patterns) if err != nil { return fmt.Errorf("failed to create Lizard configuration: %w", err) From 9806e72c71ce656a5a027c9aab675bef62ff9e9a Mon Sep 17 00:00:00 2001 From: Alejandro Rizzo Date: Mon, 20 Oct 2025 16:25:14 +0100 Subject: [PATCH 4/8] fix copilot comments --- tools/lizard/lizardRunner.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tools/lizard/lizardRunner.go b/tools/lizard/lizardRunner.go index a606e992..e925caed 100644 --- a/tools/lizard/lizardRunner.go +++ b/tools/lizard/lizardRunner.go @@ -72,11 +72,11 @@ func RunLizard(workDirectory string, binary string, files []string, outputFile s var stdout bytes.Buffer cmd.Stdout = &stdout - cmd.Run() + err = cmd.Run() if stderr.Len() > 0 { logger.Debug("Failed to run Lizard: ", logrus.Fields{ - "error": err.Error(), + "error": err != nil ? err.Error() : "unknown error", "stderr": string(stderr.Bytes()), }) @@ -115,9 +115,9 @@ func RunLizard(workDirectory string, binary string, files []string, outputFile s cmd.Stdout = os.Stdout err = cmd.Run() - if stderr.Len() > 0 { + if stderr.Len() > 0 && err != nil { logger.Debug("Failed to run Lizard: ", logrus.Fields{ - "error": err.Error(), + "error": err != nil ? err.Error() : "unknown error", "stderr": string(stderr.Bytes()), }) From 44bb1b1bd1053c9c69748ded9ac4c39d576f131a Mon Sep 17 00:00:00 2001 From: Alejandro Rizzo Date: Mon, 20 Oct 2025 16:30:01 +0100 Subject: [PATCH 5/8] fix build errors --- tools/lizard/lizardRunner.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/lizard/lizardRunner.go b/tools/lizard/lizardRunner.go index e925caed..af95e4a2 100644 --- a/tools/lizard/lizardRunner.go +++ b/tools/lizard/lizardRunner.go @@ -74,9 +74,9 @@ func RunLizard(workDirectory string, binary string, files []string, outputFile s err = cmd.Run() - if stderr.Len() > 0 { + if stderr.Len() > 0 && err != nil { logger.Debug("Failed to run Lizard: ", logrus.Fields{ - "error": err != nil ? err.Error() : "unknown error", + "error": err.Error(), "stderr": string(stderr.Bytes()), }) @@ -117,7 +117,7 @@ func RunLizard(workDirectory string, binary string, files []string, outputFile s if stderr.Len() > 0 && err != nil { logger.Debug("Failed to run Lizard: ", logrus.Fields{ - "error": err != nil ? err.Error() : "unknown error", + "error": err.Error(), "stderr": string(stderr.Bytes()), }) From 2d4418d7b07036e21a814ae3a2cafb78dc3cfc7e Mon Sep 17 00:00:00 2001 From: Alejandro Rizzo Date: Mon, 20 Oct 2025 17:07:23 +0100 Subject: [PATCH 6/8] fix config creation when parameters are not set --- tools/lizard/lizardConfigCreator.go | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/tools/lizard/lizardConfigCreator.go b/tools/lizard/lizardConfigCreator.go index 3153a8c1..80ccc6fb 100644 --- a/tools/lizard/lizardConfigCreator.go +++ b/tools/lizard/lizardConfigCreator.go @@ -25,7 +25,14 @@ func CreateLizardConfig(toolsConfigDir string, patterns []domain.PatternConfigur continue } - threshold := getThresholdFromParams(pattern.Parameters) + // if pattern.Parameters is empty, use pattermDefinition.Parameters + parameters := pattern.Parameters + if len(parameters) == 0 { + parameters = patternDefinition.Parameters + } + + threshold := getThresholdFromParams(parameters) + if threshold != 0 { // Create a unique key for this pattern that includes the severity patternKey := patternDefinition.Id From 21e6e359d892eecf07ea31dc6e022876f8b62b88 Mon Sep 17 00:00:00 2001 From: Alejandro Rizzo Date: Tue, 21 Oct 2025 09:34:55 +0100 Subject: [PATCH 7/8] fix Codacy issues --- cmd/configsetup/codacy_yaml.go | 24 ++-- cmd/configsetup/config_creators.go | 19 ++- cmd/configsetup/default_config.go | 182 ++++++++++++++------------- cmd/configsetup/repository_config.go | 17 ++- cmd/configsetup/setup.go | 2 + cmd/configsetup/tool_creators.go | 2 + 6 files changed, 135 insertions(+), 111 deletions(-) diff --git a/cmd/configsetup/codacy_yaml.go b/cmd/configsetup/codacy_yaml.go index c3f1ba6f..a9ea0f92 100644 --- a/cmd/configsetup/codacy_yaml.go +++ b/cmd/configsetup/codacy_yaml.go @@ -1,3 +1,5 @@ +// Package configsetup provides helpers to create Codacy configuration +// files (codacy.yaml and related tool/runtime sections). package configsetup import ( @@ -17,6 +19,8 @@ type RuntimePluginConfig struct { DefaultVersion string `yaml:"default_version"` } +// ConfigFileTemplate returns the content of codacy.yaml given the enabled +// tools. It lists required runtimes and tools with their versions. func ConfigFileTemplate(tools []domain.Tool) string { toolsMap := make(map[string]bool) toolVersions := make(map[string]string) @@ -47,7 +51,7 @@ func ConfigFileTemplate(tools []domain.Tool) string { return sb.String() } -// getToolVersion returns the version for a tool, preferring tool.Version over default +// getToolVersion returns the version for a tool, preferring tool.Version over default. func getToolVersion(tool domain.Tool, defaultVersions map[string]string) string { if tool.Version != "" { return tool.Version @@ -60,9 +64,9 @@ func getToolVersion(tool domain.Tool, defaultVersions map[string]string) string return "" } -// addRequiredRuntime adds the runtime requirement for a tool -func addRequiredRuntime(toolUuid string, neededRuntimes map[string]bool, runtimeDependencies map[string]string) { - if meta, ok := domain.SupportedToolsMetadata[toolUuid]; ok { +// addRequiredRuntime adds the runtime requirement for a tool. +func addRequiredRuntime(toolUUID string, neededRuntimes map[string]bool, runtimeDependencies map[string]string) { + if meta, ok := domain.SupportedToolsMetadata[toolUUID]; ok { if runtime, ok := runtimeDependencies[meta.Name]; ok { if meta.Name == "dartanalyzer" { // For dartanalyzer, default to dart runtime @@ -74,7 +78,7 @@ func addRequiredRuntime(toolUuid string, neededRuntimes map[string]bool, runtime } } -// buildRuntimesSection builds the runtimes section of the configuration +// buildRuntimesSection builds the runtimes section of the configuration. func buildRuntimesSection(sb *strings.Builder, tools []domain.Tool, neededRuntimes map[string]bool, runtimeVersions map[string]string, runtimeDependencies map[string]string) { sb.WriteString("runtimes:\n") @@ -86,7 +90,7 @@ func buildRuntimesSection(sb *strings.Builder, tools []domain.Tool, neededRuntim writeRuntimesList(sb, neededRuntimes, runtimeVersions) } -// addAllSupportedRuntimes adds all runtimes needed by supported tools +// addAllSupportedRuntimes adds all runtimes needed by supported tools. func addAllSupportedRuntimes(neededRuntimes map[string]bool, runtimeDependencies map[string]string) { supportedTools, err := plugins.GetSupportedTools() if err != nil { @@ -105,7 +109,7 @@ func addAllSupportedRuntimes(neededRuntimes map[string]bool, runtimeDependencies } } -// writeRuntimesList writes the sorted runtimes list to the string builder +// writeRuntimesList writes the sorted runtimes list to the string builder. func writeRuntimesList(sb *strings.Builder, neededRuntimes map[string]bool, runtimeVersions map[string]string) { var sortedRuntimes []string for runtime := range neededRuntimes { @@ -118,7 +122,7 @@ func writeRuntimesList(sb *strings.Builder, neededRuntimes map[string]bool, runt } } -// buildToolsSection builds the tools section of the configuration +// buildToolsSection builds the tools section of the configuration. func buildToolsSection(sb *strings.Builder, tools []domain.Tool, toolsMap map[string]bool, toolVersions map[string]string, defaultVersions map[string]string) { sb.WriteString("tools:\n") @@ -129,7 +133,7 @@ func buildToolsSection(sb *strings.Builder, tools []domain.Tool, toolsMap map[st } } -// writeEnabledTools writes the enabled tools to the string builder +// writeEnabledTools writes the enabled tools to the string builder. func writeEnabledTools(sb *strings.Builder, toolsMap map[string]bool, toolVersions map[string]string) { var sortedTools []string for uuid, meta := range domain.SupportedToolsMetadata { @@ -150,7 +154,7 @@ func writeEnabledTools(sb *strings.Builder, toolsMap map[string]bool, toolVersio } } -// writeAllSupportedTools writes all supported tools to the string builder +// writeAllSupportedTools writes all supported tools to the string builder. func writeAllSupportedTools(sb *strings.Builder, defaultVersions map[string]string) { supportedTools, err := plugins.GetSupportedTools() if err != nil { diff --git a/cmd/configsetup/config_creators.go b/cmd/configsetup/config_creators.go index 4a63adad..a369de9a 100644 --- a/cmd/configsetup/config_creators.go +++ b/cmd/configsetup/config_creators.go @@ -1,3 +1,5 @@ +// Package configsetup provides helpers to create Codacy configuration +// and helper files locally. package configsetup import ( @@ -12,6 +14,8 @@ import ( "gopkg.in/yaml.v3" ) +// CreateLanguagesConfigFileLocal writes the languages configuration file to +// the provided directory using data from the Codacy API. func CreateLanguagesConfigFileLocal(toolsConfigDir string) error { // Build tool language configurations from API configTools, err := tools.BuildLanguagesConfigFromAPI() @@ -33,12 +37,16 @@ func CreateLanguagesConfigFileLocal(toolsConfigDir string) error { return writeConfigFile(filepath.Join(toolsConfigDir, constants.LanguagesConfigFileName), data) } +// CreateGitIgnoreFile creates a default .gitignore in the local Codacy +// directory to avoid committing generated files. func CreateGitIgnoreFile() error { gitIgnorePath := filepath.Join(config.Config.LocalCodacyDirectory(), constants.GitIgnoreFileName) content := "# Codacy CLI\ntools-configs/\n.gitignore\ncli-config.yaml\nlogs/\n" return writeConfigFile(gitIgnorePath, []byte(content)) } +// CreateConfigurationFiles generates project configuration files +// (codacy.yaml and cli-config.yaml). func CreateConfigurationFiles(tools []domain.Tool, cliLocalMode bool, flags domain.InitFlags) error { // Create project config file configContent := ConfigFileTemplate(tools) @@ -55,11 +63,10 @@ func CreateConfigurationFiles(tools []domain.Tool, cliLocalMode bool, flags doma return nil } -// buildCliConfigContent creates the CLI configuration content +// buildCliConfigContent creates the CLI configuration content. func buildCliConfigContent(cliLocalMode bool, initFlags domain.InitFlags) string { - if cliLocalMode { - return fmt.Sprintf("mode: local") - } else { - return fmt.Sprintf("mode: remote\nprovider: %s\norganization: %s\nrepository: %s", initFlags.Provider, initFlags.Organization, initFlags.Repository) - } + if cliLocalMode { + return fmt.Sprintf("mode: local") + } + return fmt.Sprintf("mode: remote\nprovider: %s\norganization: %s\nrepository: %s", initFlags.Provider, initFlags.Organization, initFlags.Repository) } diff --git a/cmd/configsetup/default_config.go b/cmd/configsetup/default_config.go index 247ab438..b8eafe22 100644 --- a/cmd/configsetup/default_config.go +++ b/cmd/configsetup/default_config.go @@ -1,66 +1,77 @@ +// Package configsetup contains defaults and helpers to generate +// configuration for supported tools. package configsetup import ( - "fmt" - "log" - "strings" - - codacyclient "codacy/cli-v2/codacy-client" - "codacy/cli-v2/config" - "codacy/cli-v2/domain" - "codacy/cli-v2/plugins" - "codacy/cli-v2/tools" + "fmt" + "log" + "strings" + + codacyclient "codacy/cli-v2/codacy-client" + "codacy/cli-v2/config" + "codacy/cli-v2/domain" + "codacy/cli-v2/plugins" + "codacy/cli-v2/tools" ) -// KeepToolsWithLatestVersion filters the tools to keep only the latest version of each tool family. +// KeepToolsWithLatestVersion filters the tools to keep only the latest +// version of each tool family. func KeepToolsWithLatestVersion(tools []domain.Tool) ( - toolsWithLatestVersion []domain.Tool, - uuidToName map[string]string, - familyToVersions map[string][]string, + toolsWithLatestVersion []domain.Tool, + uuidToName map[string]string, + familyToVersions map[string][]string, ) { - latestTools := map[string]domain.Tool{} - uuidToName = map[string]string{} - seen := map[string][]domain.Tool{} - familyToVersions = map[string][]string{} - - for _, tool := range tools { - meta, ok := domain.SupportedToolsMetadata[tool.Uuid] - if !ok { - continue - } + latestTools := map[string]domain.Tool{} + uuidToName = map[string]string{} + seen := map[string][]domain.Tool{} - // Track all tools seen per family - seen[meta.Name] = append(seen[meta.Name], tool) + for _, tool := range tools { + processToolForLatest(tool, latestTools, uuidToName, seen) + } - // Pick the best version - current, exists := latestTools[meta.Name] - if !exists || domain.SupportedToolsMetadata[current.Uuid].Priority > meta.Priority { - latestTools[meta.Name] = tool - uuidToName[tool.Uuid] = meta.Name - } - } + familyToVersions = buildFamilyVersionMap(seen) - // Populate final list and version map for logging - for family, tools := range seen { - var versions []string - for _, t := range tools { - v := t.Version - if v == "" { - v = "(unknown)" - } - versions = append(versions, v) - } - familyToVersions[family] = versions - } + for _, tool := range latestTools { + toolsWithLatestVersion = append(toolsWithLatestVersion, tool) + } - for _, tool := range latestTools { - toolsWithLatestVersion = append(toolsWithLatestVersion, tool) - } + return +} + +// processToolForLatest updates the latest tool per family and tracking maps. +func processToolForLatest(tool domain.Tool, latestTools map[string]domain.Tool, uuidToName map[string]string, seen map[string][]domain.Tool) { + meta, ok := domain.SupportedToolsMetadata[tool.Uuid] + if !ok { + return + } + + seen[meta.Name] = append(seen[meta.Name], tool) + + current, exists := latestTools[meta.Name] + if !exists || domain.SupportedToolsMetadata[current.Uuid].Priority > meta.Priority { + latestTools[meta.Name] = tool + uuidToName[tool.Uuid] = meta.Name + } +} - return +// buildFamilyVersionMap builds a map of tool family to discovered versions. +func buildFamilyVersionMap(seen map[string][]domain.Tool) map[string][]string { + familyToVersions := make(map[string][]string) + for family, tools := range seen { + var versions []string + for _, t := range tools { + v := t.Version + if v == "" { + v = "(unknown)" + } + versions = append(versions, v) + } + familyToVersions[family] = versions + } + return familyToVersions } -// BuildDefaultConfigurationFiles creates default configuration files for all tools +// BuildDefaultConfigurationFiles creates default configuration files for all tools. func BuildDefaultConfigurationFiles(toolsConfigDir string, flags domain.InitFlags) error { // Get default tool versions to determine correct UUIDs defaultVersions := plugins.GetToolVersions() @@ -83,7 +94,7 @@ func BuildDefaultConfigurationFiles(toolsConfigDir string, flags domain.InitFlag return createToolConfigurationsForUUIDs(allUUIDs, toolsConfigDir, flags) } -// CreateConfigurationFilesForDiscoveredTools creates tool configuration files for discovered tools +// CreateConfigurationFilesForDiscoveredTools creates tool configuration files for discovered tools. func CreateConfigurationFilesForDiscoveredTools(discoveredToolNames map[string]struct{}, toolsConfigDir string, initFlags domain.InitFlags) error { // Determine CLI mode currentCliMode, err := config.Config.GetCliMode() @@ -92,18 +103,16 @@ func CreateConfigurationFilesForDiscoveredTools(discoveredToolNames map[string]s currentCliMode = "local" // Default to local } - if currentCliMode == "remote" && initFlags.ApiToken != "" { - // Remote mode - create configurations based on cloud repository settings - return createRemoteToolConfigurationsForDiscovered(discoveredToolNames, initFlags) - } else { - // Local mode - create default configurations for discovered tools - return createDefaultConfigurationsForSpecificTools(discoveredToolNames, toolsConfigDir, initFlags) - } + if currentCliMode == "remote" && initFlags.ApiToken != "" { + // Remote mode - create configurations based on cloud repository settings + return createRemoteToolConfigurationsForDiscovered(discoveredToolNames, initFlags) + } + // Local mode - create default configurations for discovered tools + return createDefaultConfigurationsForSpecificTools(discoveredToolNames, toolsConfigDir, initFlags) } -// createRemoteToolConfigurationsForDiscovered creates tool configurations for remote mode based on cloud settings +// createRemoteToolConfigurationsForDiscovered creates tool configurations for remote mode based on cloud settings. func createRemoteToolConfigurationsForDiscovered(discoveredToolNames map[string]struct{}, initFlags domain.InitFlags) error { - // Get repository tools from API apiTools, err := tools.GetRepositoryTools(initFlags) if err != nil { @@ -136,39 +145,34 @@ func createRemoteToolConfigurationsForDiscovered(discoveredToolNames map[string] return createToolConfigurationFiles(configuredTools, initFlags) } -// selectCorrectToolUUID selects the correct UUID for a tool based on its version +// selectCorrectToolUUID selects the correct UUID for a tool based on its version. func selectCorrectToolUUID(toolName string, defaultVersions map[string]string) string { - version, hasVersion := defaultVersions[toolName] - - // Special case for PMD: choose PMD7 UUID for version 7.x, PMD UUID for version 6.x - if toolName == "pmd" && hasVersion { - if strings.HasPrefix(version, "7.") { - return domain.PMD7 - } else { - return domain.PMD - } - } - - // Special case for ESLint: choose ESLint9 UUID for version 9.x, ESLint UUID for older versions - if toolName == "eslint" && hasVersion { - if strings.HasPrefix(version, "9.") { - return domain.ESLint9 - } else { - return domain.ESLint - } - } - - // For other tools, find the first matching UUID - for uuid, meta := range domain.SupportedToolsMetadata { - if meta.Name == toolName { - return uuid - } - } - - return "" + version := defaultVersions[toolName] + + switch toolName { + case "pmd": + if strings.HasPrefix(version, "7.") { + return domain.PMD7 + } + return domain.PMD + case "eslint": + if strings.HasPrefix(version, "9.") { + return domain.ESLint9 + } + return domain.ESLint + } + + // For other tools, find the first matching UUID + for uuid, meta := range domain.SupportedToolsMetadata { + if meta.Name == toolName { + return uuid + } + } + + return "" } -// createDefaultConfigurationsForSpecificTools creates default configurations for specific tools only +// createDefaultConfigurationsForSpecificTools creates default configurations for specific tools only. func createDefaultConfigurationsForSpecificTools(discoveredToolNames map[string]struct{}, toolsConfigDir string, initFlags domain.InitFlags) error { fmt.Printf("Creating default configurations for %d discovered tools...\n", len(discoveredToolNames)) diff --git a/cmd/configsetup/repository_config.go b/cmd/configsetup/repository_config.go index 075fe09c..83ab2c03 100644 --- a/cmd/configsetup/repository_config.go +++ b/cmd/configsetup/repository_config.go @@ -1,3 +1,5 @@ +// Package configsetup provides functions to build repository configuration +// files based on Codacy settings. package configsetup import ( @@ -13,6 +15,8 @@ import ( "codacy/cli-v2/tools" ) +// BuildRepositoryConfigurationFiles downloads repository configuration from +// Codacy and generates local configuration files. func BuildRepositoryConfigurationFiles(flags domain.InitFlags) error { fmt.Println("Fetching repository configuration from codacy ...") @@ -87,25 +91,26 @@ func createToolConfigurationFiles(tools []domain.Tool, flags domain.InitFlags) e } // CreateToolConfigurationFile creates a configuration file for a single tool +// CreateToolConfigurationFile generates a configuration file for a single tool. func CreateToolConfigurationFile(toolName string, flags domain.InitFlags) error { // Find the tool UUID by tool name - toolUuid := getToolUuidByName(toolName) - if toolUuid == "" { + toolUUID := getToolUUIDByName(toolName) + if toolUUID == "" { return fmt.Errorf("tool '%s' not found in supported tools", toolName) } - patternsConfig, err := codacyclient.GetDefaultToolPatternsConfig(flags, toolUuid, true) + patternsConfig, err := codacyclient.GetDefaultToolPatternsConfig(flags, toolUUID, true) if err != nil { return fmt.Errorf("failed to get default patterns: %w", err) } // Get the tool object to pass to createToolFileConfiguration - tool := domain.Tool{Uuid: toolUuid} + tool := domain.Tool{Uuid: toolUUID} return createToolFileConfiguration(tool, patternsConfig) } -// getToolUuidByName finds the UUID for a tool given its name -func getToolUuidByName(toolName string) string { +// getToolUUIDByName finds the UUID for a tool given its name. +func getToolUUIDByName(toolName string) string { for uuid, toolInfo := range domain.SupportedToolsMetadata { if toolInfo.Name == toolName { return uuid diff --git a/cmd/configsetup/setup.go b/cmd/configsetup/setup.go index 4bb59a82..3b32e4c2 100644 --- a/cmd/configsetup/setup.go +++ b/cmd/configsetup/setup.go @@ -1,3 +1,5 @@ +// Package configsetup defines interfaces and shared types for building +// configuration files from Codacy settings. package configsetup import "codacy/cli-v2/domain" diff --git a/cmd/configsetup/tool_creators.go b/cmd/configsetup/tool_creators.go index da95ebd3..6674389a 100644 --- a/cmd/configsetup/tool_creators.go +++ b/cmd/configsetup/tool_creators.go @@ -1,3 +1,5 @@ +// Package configsetup contains helpers to generate tool-specific configuration +// files based on Codacy settings. package configsetup import ( From 5e3a2d050d5c1d4a00f10367fdde413fbe9c2d24 Mon Sep 17 00:00:00 2001 From: Alejandro Rizzo Date: Tue, 21 Oct 2025 09:48:51 +0100 Subject: [PATCH 8/8] fix indentation --- cmd/configsetup/codacy_yaml.go | 2 +- cmd/configsetup/config_creators.go | 8 +- cmd/configsetup/default_config.go | 154 +++++++++++++-------------- cmd/configsetup/repository_config.go | 8 +- tools/lizard/lizardConfigCreator.go | 2 +- 5 files changed, 87 insertions(+), 87 deletions(-) diff --git a/cmd/configsetup/codacy_yaml.go b/cmd/configsetup/codacy_yaml.go index a9ea0f92..2debf854 100644 --- a/cmd/configsetup/codacy_yaml.go +++ b/cmd/configsetup/codacy_yaml.go @@ -66,7 +66,7 @@ func getToolVersion(tool domain.Tool, defaultVersions map[string]string) string // addRequiredRuntime adds the runtime requirement for a tool. func addRequiredRuntime(toolUUID string, neededRuntimes map[string]bool, runtimeDependencies map[string]string) { - if meta, ok := domain.SupportedToolsMetadata[toolUUID]; ok { + if meta, ok := domain.SupportedToolsMetadata[toolUUID]; ok { if runtime, ok := runtimeDependencies[meta.Name]; ok { if meta.Name == "dartanalyzer" { // For dartanalyzer, default to dart runtime diff --git a/cmd/configsetup/config_creators.go b/cmd/configsetup/config_creators.go index a369de9a..801c890f 100644 --- a/cmd/configsetup/config_creators.go +++ b/cmd/configsetup/config_creators.go @@ -65,8 +65,8 @@ func CreateConfigurationFiles(tools []domain.Tool, cliLocalMode bool, flags doma // buildCliConfigContent creates the CLI configuration content. func buildCliConfigContent(cliLocalMode bool, initFlags domain.InitFlags) string { - if cliLocalMode { - return fmt.Sprintf("mode: local") - } - return fmt.Sprintf("mode: remote\nprovider: %s\norganization: %s\nrepository: %s", initFlags.Provider, initFlags.Organization, initFlags.Repository) + if cliLocalMode { + return fmt.Sprintf("mode: local") + } + return fmt.Sprintf("mode: remote\nprovider: %s\norganization: %s\nrepository: %s", initFlags.Provider, initFlags.Organization, initFlags.Repository) } diff --git a/cmd/configsetup/default_config.go b/cmd/configsetup/default_config.go index b8eafe22..e6a6e3f8 100644 --- a/cmd/configsetup/default_config.go +++ b/cmd/configsetup/default_config.go @@ -3,72 +3,72 @@ package configsetup import ( - "fmt" - "log" - "strings" - - codacyclient "codacy/cli-v2/codacy-client" - "codacy/cli-v2/config" - "codacy/cli-v2/domain" - "codacy/cli-v2/plugins" - "codacy/cli-v2/tools" + "fmt" + "log" + "strings" + + codacyclient "codacy/cli-v2/codacy-client" + "codacy/cli-v2/config" + "codacy/cli-v2/domain" + "codacy/cli-v2/plugins" + "codacy/cli-v2/tools" ) // KeepToolsWithLatestVersion filters the tools to keep only the latest // version of each tool family. func KeepToolsWithLatestVersion(tools []domain.Tool) ( - toolsWithLatestVersion []domain.Tool, - uuidToName map[string]string, - familyToVersions map[string][]string, + toolsWithLatestVersion []domain.Tool, + uuidToName map[string]string, + familyToVersions map[string][]string, ) { - latestTools := map[string]domain.Tool{} - uuidToName = map[string]string{} - seen := map[string][]domain.Tool{} + latestTools := map[string]domain.Tool{} + uuidToName = map[string]string{} + seen := map[string][]domain.Tool{} - for _, tool := range tools { - processToolForLatest(tool, latestTools, uuidToName, seen) - } + for _, tool := range tools { + processToolForLatest(tool, latestTools, uuidToName, seen) + } - familyToVersions = buildFamilyVersionMap(seen) + familyToVersions = buildFamilyVersionMap(seen) - for _, tool := range latestTools { - toolsWithLatestVersion = append(toolsWithLatestVersion, tool) - } + for _, tool := range latestTools { + toolsWithLatestVersion = append(toolsWithLatestVersion, tool) + } - return + return } // processToolForLatest updates the latest tool per family and tracking maps. func processToolForLatest(tool domain.Tool, latestTools map[string]domain.Tool, uuidToName map[string]string, seen map[string][]domain.Tool) { - meta, ok := domain.SupportedToolsMetadata[tool.Uuid] - if !ok { - return - } - - seen[meta.Name] = append(seen[meta.Name], tool) - - current, exists := latestTools[meta.Name] - if !exists || domain.SupportedToolsMetadata[current.Uuid].Priority > meta.Priority { - latestTools[meta.Name] = tool - uuidToName[tool.Uuid] = meta.Name - } + meta, ok := domain.SupportedToolsMetadata[tool.Uuid] + if !ok { + return + } + + seen[meta.Name] = append(seen[meta.Name], tool) + + current, exists := latestTools[meta.Name] + if !exists || domain.SupportedToolsMetadata[current.Uuid].Priority > meta.Priority { + latestTools[meta.Name] = tool + uuidToName[tool.Uuid] = meta.Name + } } // buildFamilyVersionMap builds a map of tool family to discovered versions. func buildFamilyVersionMap(seen map[string][]domain.Tool) map[string][]string { - familyToVersions := make(map[string][]string) - for family, tools := range seen { - var versions []string - for _, t := range tools { - v := t.Version - if v == "" { - v = "(unknown)" - } - versions = append(versions, v) - } - familyToVersions[family] = versions - } - return familyToVersions + familyToVersions := make(map[string][]string) + for family, tools := range seen { + var versions []string + for _, t := range tools { + v := t.Version + if v == "" { + v = "(unknown)" + } + versions = append(versions, v) + } + familyToVersions[family] = versions + } + return familyToVersions } // BuildDefaultConfigurationFiles creates default configuration files for all tools. @@ -103,12 +103,12 @@ func CreateConfigurationFilesForDiscoveredTools(discoveredToolNames map[string]s currentCliMode = "local" // Default to local } - if currentCliMode == "remote" && initFlags.ApiToken != "" { - // Remote mode - create configurations based on cloud repository settings - return createRemoteToolConfigurationsForDiscovered(discoveredToolNames, initFlags) - } - // Local mode - create default configurations for discovered tools - return createDefaultConfigurationsForSpecificTools(discoveredToolNames, toolsConfigDir, initFlags) + if currentCliMode == "remote" && initFlags.ApiToken != "" { + // Remote mode - create configurations based on cloud repository settings + return createRemoteToolConfigurationsForDiscovered(discoveredToolNames, initFlags) + } + // Local mode - create default configurations for discovered tools + return createDefaultConfigurationsForSpecificTools(discoveredToolNames, toolsConfigDir, initFlags) } // createRemoteToolConfigurationsForDiscovered creates tool configurations for remote mode based on cloud settings. @@ -147,29 +147,29 @@ func createRemoteToolConfigurationsForDiscovered(discoveredToolNames map[string] // selectCorrectToolUUID selects the correct UUID for a tool based on its version. func selectCorrectToolUUID(toolName string, defaultVersions map[string]string) string { - version := defaultVersions[toolName] - - switch toolName { - case "pmd": - if strings.HasPrefix(version, "7.") { - return domain.PMD7 - } - return domain.PMD - case "eslint": - if strings.HasPrefix(version, "9.") { - return domain.ESLint9 - } - return domain.ESLint - } - - // For other tools, find the first matching UUID - for uuid, meta := range domain.SupportedToolsMetadata { - if meta.Name == toolName { - return uuid - } - } - - return "" + version := defaultVersions[toolName] + + switch toolName { + case "pmd": + if strings.HasPrefix(version, "7.") { + return domain.PMD7 + } + return domain.PMD + case "eslint": + if strings.HasPrefix(version, "9.") { + return domain.ESLint9 + } + return domain.ESLint + } + + // For other tools, find the first matching UUID + for uuid, meta := range domain.SupportedToolsMetadata { + if meta.Name == toolName { + return uuid + } + } + + return "" } // createDefaultConfigurationsForSpecificTools creates default configurations for specific tools only. diff --git a/cmd/configsetup/repository_config.go b/cmd/configsetup/repository_config.go index 83ab2c03..45111145 100644 --- a/cmd/configsetup/repository_config.go +++ b/cmd/configsetup/repository_config.go @@ -94,18 +94,18 @@ func createToolConfigurationFiles(tools []domain.Tool, flags domain.InitFlags) e // CreateToolConfigurationFile generates a configuration file for a single tool. func CreateToolConfigurationFile(toolName string, flags domain.InitFlags) error { // Find the tool UUID by tool name - toolUUID := getToolUUIDByName(toolName) - if toolUUID == "" { + toolUUID := getToolUUIDByName(toolName) + if toolUUID == "" { return fmt.Errorf("tool '%s' not found in supported tools", toolName) } - patternsConfig, err := codacyclient.GetDefaultToolPatternsConfig(flags, toolUUID, true) + patternsConfig, err := codacyclient.GetDefaultToolPatternsConfig(flags, toolUUID, true) if err != nil { return fmt.Errorf("failed to get default patterns: %w", err) } // Get the tool object to pass to createToolFileConfiguration - tool := domain.Tool{Uuid: toolUUID} + tool := domain.Tool{Uuid: toolUUID} return createToolFileConfiguration(tool, patternsConfig) } diff --git a/tools/lizard/lizardConfigCreator.go b/tools/lizard/lizardConfigCreator.go index 80ccc6fb..a55c5b16 100644 --- a/tools/lizard/lizardConfigCreator.go +++ b/tools/lizard/lizardConfigCreator.go @@ -25,7 +25,7 @@ func CreateLizardConfig(toolsConfigDir string, patterns []domain.PatternConfigur continue } - // if pattern.Parameters is empty, use pattermDefinition.Parameters + // if pattern.Parameters is empty, use patternDefinition.Parameters parameters := pattern.Parameters if len(parameters) == 0 { parameters = patternDefinition.Parameters