Skip to content
5 changes: 5 additions & 0 deletions cmd/analyze.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"codacy/cli-v2/tools"
"codacy/cli-v2/tools/lizard"
reviveTool "codacy/cli-v2/tools/revive"
"codacy/cli-v2/utils/logger"
"encoding/json"
"fmt"
"log"
Expand All @@ -18,6 +19,7 @@ import (

codacyclient "codacy/cli-v2/codacy-client"

"github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"gopkg.in/yaml.v3"
)
Expand Down Expand Up @@ -373,6 +375,9 @@ func runTool(workDirectory string, toolName string, pathsToCheck []string, outpu
func validatePaths(paths []string) error {
for _, path := range paths {
if _, err := os.Stat(path); os.IsNotExist(err) {
logger.Error("Analysis failed because path does not exist", logrus.Fields{
"path": path,
})
return fmt.Errorf("❌ Error: cannot find file or directory '%s'", path)
}
}
Expand Down
59 changes: 26 additions & 33 deletions cmd/configsetup/setup.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ import (
"codacy/cli-v2/tools/pylint"
reviveTool "codacy/cli-v2/tools/revive"
"codacy/cli-v2/utils"

"gopkg.in/yaml.v3"
)

// Configuration file names - extracted as constants to avoid duplication
Expand Down Expand Up @@ -194,33 +196,24 @@ func (r *reviveConfigCreator) GetConfigFileName() string { return "revive.toml"
func (r *reviveConfigCreator) GetToolName() string { return "Revive" }

func CreateLanguagesConfigFileLocal(toolsConfigDir string) error {
content := `tools:
- name: pylint
languages: [Python]
extensions: [.py]
- name: eslint
languages: [JavaScript, TypeScript, JSX, TSX]
extensions: [.js, .jsx, .ts, .tsx]
- name: pmd
languages: [Java, JavaScript, JSP, Velocity, XML, Apex, Scala, Ruby, VisualForce]
extensions: [.java, .js, .jsp, .vm, .xml, .cls, .trigger, .scala, .rb, .page, .component]
- name: trivy
languages: [Multiple]
extensions: []
- name: dartanalyzer
languages: [Dart]
extensions: [.dart]
- name: lizard
languages: [C, CPP, Java, "C#", JavaScript, TypeScript, VueJS, "Objective-C", Swift, Python, Ruby, "TTCN-3", PHP, Scala, GDScript, Golang, Lua, Rust, Fortran, Kotlin, Solidity, Erlang, Zig, Perl]
extensions: [.c, .cpp, .cc, .h, .hpp, .java, .cs, .js, .jsx, .ts, .tsx, .vue, .m, .swift, .py, .rb, .ttcn, .php, .scala, .gd, .go, .lua, .rs, .f, .f90, .kt, .sol, .erl, .zig, .pl]
- name: semgrep
languages: [C, CPP, "C#", Generic, Go, Java, JavaScript, JSON, Kotlin, Python, TypeScript, Ruby, Rust, JSX, PHP, Scala, Swift, Terraform]
extensions: [.c, .cpp, .h, .hpp, .cs, .go, .java, .js, .json, .kt, .py, .ts, .rb, .rs, .jsx, .php, .scala, .swift, .tf, .tfvars]
- name: codacy-enigma-cli
languages: [Multiple]
extensions: []`

return writeConfigFile(filepath.Join(toolsConfigDir, LanguagesConfigFileName), []byte(content))
// 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, LanguagesConfigFileName), data)
}

func CreateGitIgnoreFile() error {
Expand Down Expand Up @@ -441,19 +434,19 @@ func BuildRepositoryConfigurationFiles(flags domain.InitFlags) error {

logVersionConflicts(familyToVersions, toolsWithLatestVersion)

// Generate languages configuration based on API tools response
// Create main config files with all enabled API tools (including cli-config.yaml)
if err := CreateConfigurationFiles(toolsWithLatestVersion, false); 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)

// Create main config files with all enabled API tools
if err := CreateConfigurationFiles(toolsWithLatestVersion, false); err != nil {
return err
}

// Generate config files for tools not using their own config file
return createToolConfigurationFiles(configuredToolsWithUI, flags)
}
Expand Down
38 changes: 38 additions & 0 deletions codacy-client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,26 @@ func GetRepositoryTools(initFlags domain.InitFlags) ([]domain.Tool, error) {
return nil, err
}

// Get global tools with languages to populate the Languages field
globalTools, err := GetToolsVersions()
if err != nil {
fmt.Printf("Warning: Failed to get global tools for languages: %v\n", err)
return toolsResponse.Data, nil // Return repository tools without languages
}

// Create a map of UUID to languages from global tools
uuidToLanguages := make(map[string][]string)
for _, globalTool := range globalTools {
uuidToLanguages[globalTool.Uuid] = globalTool.Languages
}

// Populate Languages field in repository tools
for i := range toolsResponse.Data {
if languages, exists := uuidToLanguages[toolsResponse.Data[i].Uuid]; exists {
toolsResponse.Data[i].Languages = languages
}
}

return toolsResponse.Data, nil
}

Expand Down Expand Up @@ -253,3 +273,21 @@ func GetRepositoryLanguages(initFlags domain.InitFlags) ([]domain.Language, erro

return languagesResponse.Languages, nil
}

// GetLanguageTools fetches the default language file extensions from the API
func GetLanguageTools() ([]domain.LanguageTool, error) {
baseURL := fmt.Sprintf("%s/api/v3/languages/tools", CodacyApiBase)

bodyResponse, err := getRequest(baseURL, "")
if err != nil {
return nil, fmt.Errorf("failed to get language tools: %w", err)
}

var languageToolsResponse domain.LanguageToolsResponse
err = json.Unmarshal(bodyResponse, &languageToolsResponse)
if err != nil {
return nil, fmt.Errorf("failed to unmarshal language tools response: %w", err)
}

return languageToolsResponse.Data, nil
}
11 changes: 11 additions & 0 deletions domain/language.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,17 @@ type LanguagesResponse struct {
Languages []Language `json:"languages"`
}

// LanguageTool represents a language tool with its file extensions from the API
type LanguageTool struct {
Name string `json:"name"`
FileExtensions []string `json:"fileExtensions"`
}

// LanguageToolsResponse represents the structure of the language tools API response
type LanguageToolsResponse struct {
Data []LanguageTool `json:"data"`
}

// ToolLanguageInfo contains language and extension information for a tool
type ToolLanguageInfo struct {
Name string `yaml:"name"`
Expand Down
11 changes: 6 additions & 5 deletions domain/tool.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,12 @@ type ToolsResponse struct {

// Tool represents a tool in the Codacy API
type Tool struct {
Uuid string `json:"uuid"`
Name string `json:"name"`
Version string `json:"version"`
ShortName string `json:"shortName"`
Prefix string `json:"prefix"`
Uuid string `json:"uuid"`
Name string `json:"name"`
Version string `json:"version"`
ShortName string `json:"shortName"`
Prefix string `json:"prefix"`
Languages []string `json:"languages"`
Settings struct {
Enabled bool `json:"isEnabled"`
HasConfigurationFile bool `json:"hasConfigurationFile"`
Expand Down
1 change: 1 addition & 0 deletions integration-tests/config-discover/expected/codacy.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@ tools:
- pmd@7.11.0
- pylint@3.3.6
- semgrep@1.78.0
- trivy@0.59.1
Original file line number Diff line number Diff line change
@@ -1,25 +1,25 @@
tools:
- name: codacy-enigma-cli
languages: [Multiple]
extensions: []
- name: dartanalyzer
languages: [Dart]
extensions: [.dart]
- name: eslint
languages: [JavaScript, TypeScript, JSX, TSX]
extensions: [.js, .jsx, .ts, .tsx]
languages: [Javascript, TypeScript]
extensions: [.js, .jsm, .jsx, .mjs, .ts, .tsx, .vue]
- name: lizard
languages: [C, CPP, Java, C#, JavaScript, TypeScript, VueJS, Objective-C, Swift, Python, Ruby, TTCN-3, PHP, Scala, GDScript, Golang, Lua, Rust, Fortran, Kotlin, Solidity, Erlang, Zig, Perl]
extensions: [.c, .cpp, .cc, .h, .hpp, .java, .cs, .js, .jsx, .ts, .tsx, .vue, .m, .swift, .py, .rb, .ttcn, .php, .scala, .gd, .go, .lua, .rs, .f, .f90, .kt, .sol, .erl, .zig, .pl]
languages: [C, CPP, CSharp, Erlang, Fortran, Go, Java, Javascript, Kotlin, Lua, Objective C, PHP, Python, Ruby, Rust, Scala, Solidity, Swift, TypeScript]
Copy link
Copy Markdown
Contributor Author

@andrzej-janczak andrzej-janczak Jun 25, 2025

Choose a reason for hiding this comment

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

Need to sort for it test consistency.
Also It looks better visually btw πŸ˜‰

Also sorts keys - tool name

extensions: [.c, .cc, .cpp, .cs, .cxx, .gemspec, .go, .h, .hpp, .ino, .java, .jbuilder, .js, .jsm, .jsx, .kt, .kts, .m, .mjs, .opal, .php, .podspec, .py, .rake, .rb, .rlib, .rs, .scala, .swift, .ts, .tsx, .vue]
- name: pmd
languages: [Java, JavaScript, JSP, Velocity, XML, Apex, Scala, Ruby, VisualForce]
extensions: [.java, .js, .jsp, .vm, .xml, .cls, .trigger, .scala, .rb, .page, .component]
languages: [Apex, JSP, Java, Javascript, PLSQL, SQL, Velocity, VisualForce, XML]
extensions: [.cls, .component, .fnc, .java, .js, .jsm, .jsp, .jsx, .mjs, .page, .pck, .pkb, .pkh, .pks, .plb, .pld, .plh, .pls, .pom, .prc, .sql, .tpb, .tps, .trg, .trigger, .tyb, .typ, .vm, .vue, .wsdl, .xml, .xsl]
- name: pylint
languages: [Python]
extensions: [.py]
- name: revive
languages: [Go]
extensions: [.go]
- name: semgrep
languages: [C, CPP, C#, Generic, Go, Java, JavaScript, JSON, Kotlin, Python, TypeScript, Ruby, Rust, JSX, PHP, Scala, Swift, Terraform]
extensions: [.c, .cpp, .h, .hpp, .cs, .go, .java, .js, .json, .kt, .py, .ts, .rb, .rs, .jsx, .php, .scala, .swift, .tf, .tfvars]
languages: [Apex, C, CPP, CSharp, Dockerfile, Go, Java, Javascript, Kotlin, PHP, PLSQL, Python, Ruby, Rust, SQL, Scala, Shell, Swift, Terraform, TypeScript, YAML]
extensions: [.bash, .c, .cc, .cls, .cpp, .cs, .cxx, .dockerfile, .fnc, .gemspec, .go, .h, .hpp, .ino, .java, .jbuilder, .js, .jsm, .jsx, .kt, .kts, .mjs, .opal, .pck, .php, .pkb, .pkh, .pks, .plb, .pld, .plh, .pls, .podspec, .prc, .py, .rake, .rb, .rlib, .rs, .scala, .sh, .sql, .swift, .tf, .tpb, .tps, .trg, .trigger, .ts, .tsx, .tyb, .typ, .vue, .yaml, .yml]
- name: trivy
languages: [Multiple]
extensions: []
languages: [C, CPP, CSharp, Dart, Dockerfile, Elixir, Go, JSON, Java, Javascript, PHP, Python, Ruby, Rust, Scala, Swift, Terraform, TypeScript, XML, YAML]
extensions: [.c, .cc, .cpp, .cs, .cxx, .dart, .dockerfile, .ex, .exs, .gemspec, .go, .h, .hpp, .ino, .java, .jbuilder, .js, .jsm, .json, .jsx, .mjs, .opal, .php, .podspec, .pom, .py, .rake, .rb, .rlib, .rs, .scala, .swift, .tf, .ts, .tsx, .vue, .wsdl, .xml, .xsl, .yaml, .yml]
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
tools:
- name: pylint
languages: [Python]
extensions: [.py]
- name: eslint
languages: [Javascript]
extensions: [.js, .jsm, .jsx, .mjs, .vue]
- name: lizard
languages: [Java, JavaScript, Python]
languages: [Java, Javascript, Python]
extensions: [.java, .js, .jsm, .jsx, .mjs, .py, .vue]
- name: pmd
languages: [Java, JavaScript]
languages: [Java, Javascript]
extensions: [.java, .js, .jsm, .jsx, .mjs, .vue]
- name: eslint
languages: [JavaScript]
extensions: [.js, .jsm, .jsx, .mjs, .vue]
- name: trivy
languages: [Multiple]
extensions: []
- name: pylint
languages: [Python]
extensions: [.py]
- name: semgrep
languages: [Java, JavaScript, JSON, Python]
extensions: [.java, .js, .jsm, .json, .jsx, .mjs, .py, .vue]
languages: [Java, Javascript, Python]
extensions: [.java, .js, .jsm, .jsx, .mjs, .py, .vue]
- name: trivy
languages: [JSON, Java, Javascript, Python]
extensions: [.java, .js, .jsm, .json, .jsx, .mjs, .py, .vue]
Original file line number Diff line number Diff line change
@@ -1,25 +1,25 @@
tools:
- name: pylint
languages: [Python]
extensions: [.py]
- name: eslint
languages: [JavaScript, TypeScript, JSX, TSX]
extensions: [.js, .jsx, .ts, .tsx]
- name: pmd
languages: [Java, JavaScript, JSP, Velocity, XML, Apex, Scala, Ruby, VisualForce]
extensions: [.java, .js, .jsp, .vm, .xml, .cls, .trigger, .scala, .rb, .page, .component]
- name: trivy
languages: [Multiple]
extensions: []
- name: dartanalyzer
languages: [Dart]
extensions: [.dart]
- name: eslint
languages: [Javascript, TypeScript]
extensions: [.js, .jsm, .jsx, .mjs, .ts, .tsx, .vue]
- name: lizard
languages: [C, CPP, Java, "C#", JavaScript, TypeScript, VueJS, "Objective-C", Swift, Python, Ruby, "TTCN-3", PHP, Scala, GDScript, Golang, Lua, Rust, Fortran, Kotlin, Solidity, Erlang, Zig, Perl]
extensions: [.c, .cpp, .cc, .h, .hpp, .java, .cs, .js, .jsx, .ts, .tsx, .vue, .m, .swift, .py, .rb, .ttcn, .php, .scala, .gd, .go, .lua, .rs, .f, .f90, .kt, .sol, .erl, .zig, .pl]
languages: [C, CPP, CSharp, Erlang, Fortran, Go, Java, Javascript, Kotlin, Lua, Objective C, PHP, Python, Ruby, Rust, Scala, Solidity, Swift, TypeScript]
extensions: [.c, .cc, .cpp, .cs, .cxx, .gemspec, .go, .h, .hpp, .ino, .java, .jbuilder, .js, .jsm, .jsx, .kt, .kts, .m, .mjs, .opal, .php, .podspec, .py, .rake, .rb, .rlib, .rs, .scala, .swift, .ts, .tsx, .vue]
- name: pmd
languages: [Apex, JSP, Java, Javascript, PLSQL, SQL, Velocity, VisualForce, XML]
extensions: [.cls, .component, .fnc, .java, .js, .jsm, .jsp, .jsx, .mjs, .page, .pck, .pkb, .pkh, .pks, .plb, .pld, .plh, .pls, .pom, .prc, .sql, .tpb, .tps, .trg, .trigger, .tyb, .typ, .vm, .vue, .wsdl, .xml, .xsl]
- name: pylint
languages: [Python]
extensions: [.py]
- name: revive
languages: [Go]
extensions: [.go]
- name: semgrep
languages: [C, CPP, "C#", Generic, Go, Java, JavaScript, JSON, Kotlin, Python, TypeScript, Ruby, Rust, JSX, PHP, Scala, Swift, Terraform]
extensions: [.c, .cpp, .h, .hpp, .cs, .go, .java, .js, .json, .kt, .py, .ts, .rb, .rs, .jsx, .php, .scala, .swift, .tf, .tfvars]
- name: codacy-enigma-cli
languages: [Multiple]
extensions: []
languages: [Apex, C, CPP, CSharp, Dockerfile, Go, Java, Javascript, Kotlin, PHP, PLSQL, Python, Ruby, Rust, SQL, Scala, Shell, Swift, Terraform, TypeScript, YAML]
extensions: [.bash, .c, .cc, .cls, .cpp, .cs, .cxx, .dockerfile, .fnc, .gemspec, .go, .h, .hpp, .ino, .java, .jbuilder, .js, .jsm, .jsx, .kt, .kts, .mjs, .opal, .pck, .php, .pkb, .pkh, .pks, .plb, .pld, .plh, .pls, .podspec, .prc, .py, .rake, .rb, .rlib, .rs, .scala, .sh, .sql, .swift, .tf, .tpb, .tps, .trg, .trigger, .ts, .tsx, .tyb, .typ, .vue, .yaml, .yml]
- name: trivy
languages: [C, CPP, CSharp, Dart, Dockerfile, Elixir, Go, JSON, Java, Javascript, PHP, Python, Ruby, Rust, Scala, Swift, Terraform, TypeScript, XML, YAML]
extensions: [.c, .cc, .cpp, .cs, .cxx, .dart, .dockerfile, .ex, .exs, .gemspec, .go, .h, .hpp, .ino, .java, .jbuilder, .js, .jsm, .json, .jsx, .mjs, .opal, .php, .podspec, .pom, .py, .rake, .rb, .rlib, .rs, .scala, .swift, .tf, .ts, .tsx, .vue, .wsdl, .xml, .xsl, .yaml, .yml]
Loading