Skip to content

Commit 47057f0

Browse files
using API repo languages to create languages-config file
1 parent 90d3e58 commit 47057f0

File tree

5 files changed

+323
-94
lines changed

5 files changed

+323
-94
lines changed

cmd/init.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -268,7 +268,7 @@ func buildRepositoryConfigurationFiles(token string) error {
268268
}
269269

270270
// Generate languages configuration based on API tools response
271-
if err := tools.CreateLanguagesConfigFile(apiTools, toolsConfigDir, uuidToName); err != nil {
271+
if err := tools.CreateLanguagesConfigFile(apiTools, toolsConfigDir, uuidToName, token, initFlags.provider, initFlags.organization, initFlags.repository); err != nil {
272272
return fmt.Errorf("failed to create languages configuration file: %w", err)
273273
}
274274

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ require (
3434
github.com/nwaples/rardecode/v2 v2.0.0-beta.2 // indirect
3535
github.com/pierrec/lz4/v4 v4.1.15 // indirect
3636
github.com/spf13/pflag v1.0.5 // indirect
37-
github.com/stretchr/testify v1.9.0
37+
github.com/stretchr/testify v1.10.0
3838
github.com/therootcompany/xz v1.0.1 // indirect
3939
github.com/ulikunitz/xz v0.5.10 // indirect
4040
go4.org v0.0.0-20200411211856-f5505b9728dd // indirect

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,8 @@ github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81P
129129
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
130130
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
131131
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
132+
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
133+
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
132134
github.com/therootcompany/xz v1.0.1 h1:CmOtsn1CbtmyYiusbfmhmkpAAETj0wBIH6kCYaX+xzw=
133135
github.com/therootcompany/xz v1.0.1/go.mod h1:3K3UH1yCKgBneZYhuQUvJ9HPD19UEXEI0BWbMn8qNMY=
134136
github.com/ulikunitz/xz v0.5.6/go.mod h1:2bypXElzHzzJZwzH67Y6wb67pO62Rzfn7BSiF4ABRW8=

tools/language_config.go

Lines changed: 119 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,22 @@
11
package tools
22

33
import (
4+
"encoding/json"
45
"fmt"
6+
"io"
7+
"net/http"
58
"os"
69
"path/filepath"
10+
"strings"
11+
"time"
712

813
"codacy/cli-v2/utils"
914

1015
"gopkg.in/yaml.v3"
1116
)
1217

18+
const CodacyApiBase = "https://app.codacy.com"
19+
1320
// ToolLanguageInfo contains language and extension information for a tool
1421
type ToolLanguageInfo struct {
1522
Name string `yaml:"name"`
@@ -23,7 +30,7 @@ type LanguagesConfig struct {
2330
}
2431

2532
// CreateLanguagesConfigFile creates languages-config.yaml based on API response
26-
func CreateLanguagesConfigFile(apiTools []Tool, toolsConfigDir string, toolIDMap map[string]string) error {
33+
func CreateLanguagesConfigFile(apiTools []Tool, toolsConfigDir string, toolIDMap map[string]string, apiToken string, provider string, organization string, repository string) error {
2734
// Map tool names to their language/extension information
2835
toolLanguageMap := map[string]ToolLanguageInfo{
2936
"cppcheck": {
@@ -61,6 +68,11 @@ func CreateLanguagesConfigFile(apiTools []Tool, toolsConfigDir string, toolIDMap
6168
// Build a list of tool language info for enabled tools
6269
var configTools []ToolLanguageInfo
6370

71+
repositoryLanguages, err := getRepositoryLanguages(apiToken, provider, organization, repository)
72+
if err != nil {
73+
return fmt.Errorf("failed to get repository languages: %w", err)
74+
}
75+
6476
for _, tool := range apiTools {
6577
shortName, exists := toolIDMap[tool.Uuid]
6678
if !exists {
@@ -71,7 +83,27 @@ func CreateLanguagesConfigFile(apiTools []Tool, toolsConfigDir string, toolIDMap
7183
// Get language info for this tool
7284
langInfo, exists := toolLanguageMap[shortName]
7385
if exists {
74-
configTools = append(configTools, langInfo)
86+
// Special case for Trivy - always include it
87+
if shortName == "trivy" {
88+
configTools = append(configTools, langInfo)
89+
continue
90+
}
91+
92+
// Filter languages based on repository languages
93+
var filteredLanguages []string
94+
for _, lang := range langInfo.Languages {
95+
// Convert both to lowercase for case-insensitive comparison
96+
lowerLang := strings.ToLower(lang)
97+
if extensions, exists := repositoryLanguages[lowerLang]; exists && len(extensions) > 0 {
98+
filteredLanguages = append(filteredLanguages, lang)
99+
}
100+
}
101+
102+
// Only add tool if it has languages that exist in the repository
103+
if len(filteredLanguages) > 0 {
104+
langInfo.Languages = filteredLanguages
105+
configTools = append(configTools, langInfo)
106+
}
75107
}
76108
}
77109

@@ -102,3 +134,88 @@ func CreateLanguagesConfigFile(apiTools []Tool, toolsConfigDir string, toolIDMap
102134
fmt.Println("Created languages configuration file based on enabled tools")
103135
return nil
104136
}
137+
138+
// https://app.codacy.com/api/v3/organizations/gh/troubleshoot-codacy/repositories/eslint-test-examples/settings/languages
139+
func getRepositoryLanguages(apiToken string, provider string, organization string, repository string) (map[string][]string, error) {
140+
client := &http.Client{
141+
Timeout: 10 * time.Second,
142+
}
143+
144+
url := fmt.Sprintf("%s/api/v3/organizations/%s/%s/repositories/%s/settings/languages",
145+
CodacyApiBase,
146+
provider,
147+
organization,
148+
repository)
149+
150+
// Create a new GET request
151+
req, err := http.NewRequest("GET", url, nil)
152+
if err != nil {
153+
return nil, fmt.Errorf("failed to create request: %w", err)
154+
}
155+
156+
// Set the API token header
157+
req.Header.Set("api-token", apiToken)
158+
159+
// Send the request
160+
resp, err := client.Do(req)
161+
if err != nil {
162+
return nil, fmt.Errorf("failed to send request: %w", err)
163+
}
164+
defer resp.Body.Close()
165+
166+
if resp.StatusCode != 200 {
167+
return nil, fmt.Errorf("failed to get repository languages: status code %d", resp.StatusCode)
168+
}
169+
170+
// Read the response body
171+
body, err := io.ReadAll(resp.Body)
172+
if err != nil {
173+
return nil, fmt.Errorf("failed to read response body: %w", err)
174+
}
175+
176+
// Define the response structure
177+
type LanguageResponse struct {
178+
Name string `json:"name"`
179+
CodacyDefaults []string `json:"codacyDefaults"`
180+
Extensions []string `json:"extensions"`
181+
Enabled bool `json:"enabled"`
182+
Detected bool `json:"detected"`
183+
}
184+
185+
type LanguagesResponse struct {
186+
Languages []LanguageResponse `json:"languages"`
187+
}
188+
189+
var response LanguagesResponse
190+
if err := json.Unmarshal(body, &response); err != nil {
191+
return nil, fmt.Errorf("failed to unmarshal response: %w", err)
192+
}
193+
194+
// Create map to store language name -> combined extensions
195+
result := make(map[string][]string)
196+
197+
// Filter and process languages
198+
for _, lang := range response.Languages {
199+
if lang.Enabled && lang.Detected {
200+
// Combine and deduplicate extensions
201+
extensions := make(map[string]struct{})
202+
for _, ext := range lang.CodacyDefaults {
203+
extensions[ext] = struct{}{}
204+
}
205+
for _, ext := range lang.Extensions {
206+
extensions[ext] = struct{}{}
207+
}
208+
209+
// Convert map to slice
210+
extSlice := make([]string, 0, len(extensions))
211+
for ext := range extensions {
212+
extSlice = append(extSlice, ext)
213+
}
214+
215+
// Add to result map with lowercase key for case-insensitive matching
216+
result[strings.ToLower(lang.Name)] = extSlice
217+
}
218+
}
219+
220+
return result, nil
221+
}

0 commit comments

Comments
 (0)