Skip to content

Commit a75e2a7

Browse files
feature: implement tool configuration creation for discovered languages
- Added functionality to create configuration files for tools relevant to detected programming languages. - Enhanced the `config` command to generate configurations based on discovered tools, improving user experience. - Refactored the configuration file creation logic to support both local and remote modes. - Updated user feedback messages to reflect changes in the configuration directory structure.
1 parent 77a77b6 commit a75e2a7

File tree

2 files changed

+178
-37
lines changed

2 files changed

+178
-37
lines changed

cmd/config.go

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -218,8 +218,27 @@ var configDiscoverCmd = &cobra.Command{
218218
}
219219
fmt.Printf("Updated %s with relevant tools.\n", filepath.Base(codacyYAMLPath))
220220

221+
// Determine which tools are relevant for discovered languages and create their configurations
222+
discoveredToolNames := make(map[string]struct{})
223+
for toolName, toolInfo := range defaultToolLangMap {
224+
for _, toolLang := range toolInfo.Languages {
225+
if _, detected := detectedLanguages[toolLang]; detected {
226+
discoveredToolNames[toolName] = struct{}{}
227+
break
228+
}
229+
}
230+
}
231+
232+
// Create tool configuration files for discovered tools
233+
if len(discoveredToolNames) > 0 {
234+
fmt.Printf("\nCreating tool configurations for discovered tools...\n")
235+
if err := configsetup.CreateConfigurationFilesForDiscoveredTools(discoveredToolNames, toolsConfigDir, configResetInitFlags); err != nil {
236+
log.Printf("Warning: Failed to create some tool configurations: %v", err)
237+
}
238+
}
239+
221240
fmt.Println("\n✅ Successfully discovered languages and updated configurations.")
222-
fmt.Println(" Please review the changes in '.codacy/codacy.yaml' and '.codacy/tools-configs/languages-config.yaml'.")
241+
fmt.Println(" Please review the changes in '.codacy/codacy.yaml' and '.codacy/tools-configs/' directory.")
223242
},
224243
}
225244

cmd/configsetup/setup.go

Lines changed: 158 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -468,45 +468,16 @@ func createLizardConfigFile(toolsConfigDir string, patternConfiguration []domain
468468

469469
// buildDefaultConfigurationFiles creates default configuration files for all tools
470470
func BuildDefaultConfigurationFiles(toolsConfigDir string, flags domain.InitFlags) error {
471+
// Get all supported tool UUIDs
472+
var allUUIDs []string
471473
for uuid := range domain.SupportedToolsMetadata {
472-
patternsConfig, err := codacyclient.GetDefaultToolPatternsConfig(flags, uuid)
473-
if err != nil {
474-
return fmt.Errorf("failed to get default tool patterns config: %w", err)
475-
}
476-
switch uuid {
477-
case domain.ESLint:
478-
if err := tools.CreateEslintConfig(toolsConfigDir, patternsConfig); err != nil {
479-
return fmt.Errorf("failed to create eslint config file: %v", err)
480-
}
481-
case domain.Trivy:
482-
if err := createTrivyConfigFile(patternsConfig, toolsConfigDir); err != nil {
483-
return fmt.Errorf("failed to create default Trivy configuration: %w", err)
484-
}
485-
case domain.PMD:
486-
if err := createPMDConfigFile(patternsConfig, toolsConfigDir); err != nil {
487-
return fmt.Errorf("failed to create default PMD configuration: %w", err)
488-
}
489-
case domain.PyLint:
490-
if err := createPylintConfigFile(patternsConfig, toolsConfigDir); err != nil {
491-
return fmt.Errorf("failed to create default Pylint configuration: %w", err)
492-
}
493-
case domain.DartAnalyzer:
494-
if err := createDartAnalyzerConfigFile(patternsConfig, toolsConfigDir); err != nil {
495-
return fmt.Errorf("failed to create default Dart Analyzer configuration: %w", err)
496-
}
497-
case domain.Semgrep:
498-
if err := createSemgrepConfigFile(patternsConfig, toolsConfigDir); err != nil {
499-
return fmt.Errorf("failed to create default Semgrep configuration: %w", err)
500-
}
501-
case domain.Lizard:
502-
if err := createLizardConfigFile(toolsConfigDir, patternsConfig); err != nil {
503-
return fmt.Errorf("failed to create default Lizard configuration: %w", err)
504-
}
505-
case domain.PMD7, domain.ESLint9:
506-
continue
474+
// Skip PMD7 and ESLint9 as per existing logic
475+
if uuid != domain.PMD7 && uuid != domain.ESLint9 {
476+
allUUIDs = append(allUUIDs, uuid)
507477
}
508478
}
509-
return nil
479+
480+
return createToolConfigurationsForUUIDs(allUUIDs, toolsConfigDir, flags)
510481
}
511482

512483
// KeepToolsWithLatestVersion filters the tools to keep only the latest version of each tool family.
@@ -556,3 +527,154 @@ func KeepToolsWithLatestVersion(tools []domain.Tool) (
556527

557528
return
558529
}
530+
531+
// CreateConfigurationFilesForDiscoveredTools creates tool configuration files for discovered tools
532+
// It determines the CLI mode and creates appropriate configurations for the tools
533+
func CreateConfigurationFilesForDiscoveredTools(discoveredToolNames map[string]struct{}, toolsConfigDir string, initFlags domain.InitFlags) error {
534+
// Determine CLI mode
535+
currentCliMode, err := config.Config.GetCliMode()
536+
if err != nil {
537+
log.Printf("Warning: Could not determine CLI mode: %v. Assuming local mode for tool configuration creation.", err)
538+
currentCliMode = "local" // Default to local
539+
}
540+
541+
if currentCliMode == "remote" && initFlags.ApiToken != "" {
542+
// Remote mode - create configurations based on cloud repository settings
543+
return createRemoteToolConfigurationsForDiscovered(discoveredToolNames, toolsConfigDir, initFlags)
544+
} else {
545+
// Local mode - create default configurations for discovered tools
546+
return createDefaultConfigurationsForSpecificTools(discoveredToolNames, toolsConfigDir, initFlags)
547+
}
548+
}
549+
550+
// createRemoteToolConfigurationsForDiscovered creates tool configurations for remote mode based on cloud settings
551+
func createRemoteToolConfigurationsForDiscovered(discoveredToolNames map[string]struct{}, toolsConfigDir string, initFlags domain.InitFlags) error {
552+
// Get repository tools from API
553+
apiTools, err := tools.GetRepositoryTools(initFlags)
554+
if err != nil {
555+
return fmt.Errorf("failed to get repository tools from cloud: %w", err)
556+
}
557+
558+
// Filter to only tools that were discovered and enabled in cloud
559+
var enabledDiscoveredTools []domain.Tool
560+
for _, tool := range apiTools {
561+
if tool.Settings.Enabled {
562+
if meta, ok := domain.SupportedToolsMetadata[tool.Uuid]; ok {
563+
if _, discovered := discoveredToolNames[meta.Name]; discovered {
564+
enabledDiscoveredTools = append(enabledDiscoveredTools, tool)
565+
}
566+
}
567+
}
568+
}
569+
570+
if len(enabledDiscoveredTools) == 0 {
571+
fmt.Println("No discovered tools are enabled in cloud configuration.")
572+
return nil
573+
}
574+
575+
// Filter out tools that use their own configuration files
576+
configuredTools := tools.FilterToolsByConfigUsage(enabledDiscoveredTools)
577+
578+
fmt.Printf("Creating configurations for %d discovered tools enabled in cloud...\n", len(configuredTools))
579+
580+
// Create configuration files for each tool using existing logic
581+
for _, tool := range configuredTools {
582+
apiToolConfigurations, err := codacyclient.GetRepositoryToolPatterns(initFlags, tool.Uuid)
583+
if err != nil {
584+
log.Printf("Warning: Failed to get tool patterns for %s: %v", tool.Name, err)
585+
continue
586+
}
587+
588+
if err := createToolFileConfigurations(tool, apiToolConfigurations); err != nil {
589+
log.Printf("Warning: Failed to create configuration for %s: %v", tool.Name, err)
590+
continue
591+
}
592+
}
593+
594+
return nil
595+
}
596+
597+
// createDefaultConfigurationsForSpecificTools creates default configurations for specific tools only
598+
// This reuses the existing BuildDefaultConfigurationFiles logic but filters for specific tools
599+
func createDefaultConfigurationsForSpecificTools(discoveredToolNames map[string]struct{}, toolsConfigDir string, initFlags domain.InitFlags) error {
600+
fmt.Printf("Creating default configurations for %d discovered tools...\n", len(discoveredToolNames))
601+
602+
// Convert tool names to UUIDs
603+
var discoveredUUIDs []string
604+
for toolName := range discoveredToolNames {
605+
for uuid, meta := range domain.SupportedToolsMetadata {
606+
if meta.Name == toolName {
607+
discoveredUUIDs = append(discoveredUUIDs, uuid)
608+
break
609+
}
610+
}
611+
}
612+
613+
if len(discoveredUUIDs) == 0 {
614+
log.Printf("Warning: No recognized tools found among discovered tools")
615+
return nil
616+
}
617+
618+
// Create configurations for discovered tools only
619+
return createToolConfigurationsForUUIDs(discoveredUUIDs, toolsConfigDir, initFlags)
620+
}
621+
622+
// createToolConfigurationsForUUIDs creates tool configurations for specific UUIDs
623+
// This extracts the common logic from BuildDefaultConfigurationFiles
624+
func createToolConfigurationsForUUIDs(uuids []string, toolsConfigDir string, initFlags domain.InitFlags) error {
625+
for _, uuid := range uuids {
626+
patternsConfig, err := codacyclient.GetDefaultToolPatternsConfig(initFlags, uuid)
627+
if err != nil {
628+
if meta, ok := domain.SupportedToolsMetadata[uuid]; ok {
629+
log.Printf("Warning: Failed to get default patterns for %s: %v", meta.Name, err)
630+
} else {
631+
log.Printf("Warning: Failed to get default patterns for UUID %s: %v", uuid, err)
632+
}
633+
continue
634+
}
635+
636+
if err := createToolConfigurationFile(uuid, patternsConfig, toolsConfigDir); err != nil {
637+
if meta, ok := domain.SupportedToolsMetadata[uuid]; ok {
638+
log.Printf("Warning: Failed to create configuration for %s: %v", meta.Name, err)
639+
} else {
640+
log.Printf("Warning: Failed to create configuration for UUID %s: %v", uuid, err)
641+
}
642+
continue
643+
}
644+
645+
// Print success message
646+
if meta, ok := domain.SupportedToolsMetadata[uuid]; ok {
647+
fmt.Printf("Created %s configuration\n", meta.Name)
648+
}
649+
}
650+
651+
return nil
652+
}
653+
654+
// createToolConfigurationFile creates a single tool configuration file based on UUID
655+
// This extracts the switch logic to avoid duplication
656+
func createToolConfigurationFile(uuid string, patternsConfig []domain.PatternConfiguration, toolsConfigDir string) error {
657+
switch uuid {
658+
case domain.ESLint, domain.ESLint9:
659+
return tools.CreateEslintConfig(toolsConfigDir, patternsConfig)
660+
case domain.Trivy:
661+
return createTrivyConfigFile(patternsConfig, toolsConfigDir)
662+
case domain.PMD:
663+
return createPMDConfigFile(patternsConfig, toolsConfigDir)
664+
case domain.PMD7:
665+
return createPMD7ConfigFile(patternsConfig, toolsConfigDir)
666+
case domain.PyLint:
667+
return createPylintConfigFile(patternsConfig, toolsConfigDir)
668+
case domain.DartAnalyzer:
669+
return createDartAnalyzerConfigFile(patternsConfig, toolsConfigDir)
670+
case domain.Semgrep:
671+
return createSemgrepConfigFile(patternsConfig, toolsConfigDir)
672+
case domain.Lizard:
673+
return createLizardConfigFile(toolsConfigDir, patternsConfig)
674+
default:
675+
if meta, ok := domain.SupportedToolsMetadata[uuid]; ok {
676+
return fmt.Errorf("configuration creation not implemented for tool %s", meta.Name)
677+
}
678+
return fmt.Errorf("configuration creation not implemented for UUID %s", uuid)
679+
}
680+
}

0 commit comments

Comments
 (0)