Skip to content

Commit a95a19d

Browse files
Merge pull request #119 from codacy/pluto-1380
feature: fetch codacy default values for all tools patterns when no token init - PLUTO-1380
2 parents 237e427 + 9b41044 commit a95a19d

File tree

7 files changed

+416
-32
lines changed

7 files changed

+416
-32
lines changed

cmd/init.go

Lines changed: 71 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package cmd
22

33
import (
4+
codacyclient "codacy/cli-v2/codacy-client"
45
"codacy/cli-v2/config"
56
"codacy/cli-v2/domain"
67
"codacy/cli-v2/tools"
@@ -23,20 +24,13 @@ import (
2324

2425
const CodacyApiBase = "https://app.codacy.com"
2526

26-
type InitFlags struct {
27-
apiToken string
28-
provider string
29-
organization string
30-
repository string
31-
}
32-
33-
var initFlags InitFlags
27+
var initFlags domain.InitFlags
3428

3529
func init() {
36-
initCmd.Flags().StringVar(&initFlags.apiToken, "api-token", "", "optional codacy api token, if defined configurations will be fetched from codacy")
37-
initCmd.Flags().StringVar(&initFlags.provider, "provider", "", "provider (gh/bb/gl) to fetch configurations from codacy, required when api-token is provided")
38-
initCmd.Flags().StringVar(&initFlags.organization, "organization", "", "remote organization name to fetch configurations from codacy, required when api-token is provided")
39-
initCmd.Flags().StringVar(&initFlags.repository, "repository", "", "remote repository name to fetch configurations from codacy, required when api-token is provided")
30+
initCmd.Flags().StringVar(&initFlags.ApiToken, "api-token", "", "optional codacy api token, if defined configurations will be fetched from codacy")
31+
initCmd.Flags().StringVar(&initFlags.Provider, "provider", "", "provider (gh/bb/gl) to fetch configurations from codacy, required when api-token is provided")
32+
initCmd.Flags().StringVar(&initFlags.Organization, "organization", "", "remote organization name to fetch configurations from codacy, required when api-token is provided")
33+
initCmd.Flags().StringVar(&initFlags.Repository, "repository", "", "remote repository name to fetch configurations from codacy, required when api-token is provided")
4034
rootCmd.AddCommand(initCmd)
4135
}
4236

@@ -56,11 +50,11 @@ var initCmd = &cobra.Command{
5650
log.Fatalf("Failed to create tools-configs directory: %v", err)
5751
}
5852

59-
cliLocalMode := len(initFlags.apiToken) == 0
53+
cliLocalMode := len(initFlags.ApiToken) == 0
6054

6155
if cliLocalMode {
6256
fmt.Println()
63-
fmt.Println("ℹ️ No project token was specified, skipping fetch configurations")
57+
fmt.Println("ℹ️ No project token was specified, fetching codacy default configurations")
6458
noTools := []tools.Tool{}
6559
err := createConfigurationFiles(noTools, cliLocalMode)
6660
if err != nil {
@@ -71,7 +65,7 @@ var initCmd = &cobra.Command{
7165
log.Fatal(err)
7266
}
7367
} else {
74-
err := buildRepositoryConfigurationFiles(initFlags.apiToken)
68+
err := buildRepositoryConfigurationFiles(initFlags.ApiToken)
7569
if err != nil {
7670
log.Fatal(err)
7771
}
@@ -265,7 +259,7 @@ func buildRepositoryConfigurationFiles(token string) error {
265259
Timeout: 10 * time.Second,
266260
}
267261

268-
apiTools, err := tools.GetRepositoryTools(CodacyApiBase, token, initFlags.provider, initFlags.organization, initFlags.repository)
262+
apiTools, err := tools.GetRepositoryTools(CodacyApiBase, token, initFlags.Provider, initFlags.Organization, initFlags.Repository)
269263
if err != nil {
270264
return err
271265
}
@@ -282,7 +276,7 @@ func buildRepositoryConfigurationFiles(token string) error {
282276
}
283277

284278
// Generate languages configuration based on API tools response
285-
if err := tools.CreateLanguagesConfigFile(apiTools, toolsConfigDir, uuidToName, token, initFlags.provider, initFlags.organization, initFlags.repository); err != nil {
279+
if err := tools.CreateLanguagesConfigFile(apiTools, toolsConfigDir, uuidToName, token, initFlags.Provider, initFlags.Organization, initFlags.Repository); err != nil {
286280
return fmt.Errorf("failed to create languages configuration file: %w", err)
287281
}
288282

@@ -300,9 +294,9 @@ func buildRepositoryConfigurationFiles(token string) error {
300294

301295
url := fmt.Sprintf("%s/api/v3/analysis/organizations/%s/%s/repositories/%s/tools/%s/patterns?enabled=true&limit=1000",
302296
CodacyApiBase,
303-
initFlags.provider,
304-
initFlags.organization,
305-
initFlags.repository,
297+
initFlags.Provider,
298+
initFlags.Organization,
299+
initFlags.Repository,
306300
tool.Uuid)
307301

308302
// Create a new GET request
@@ -493,6 +487,7 @@ func createDefaultTrivyConfigFile(toolsConfigDir string) error {
493487
// createDefaultEslintConfigFile creates a default eslint.config.mjs configuration file
494488
func createDefaultEslintConfigFile(toolsConfigDir string) error {
495489
// Use empty tool configuration to get default settings
490+
//
496491
emptyConfig := []domain.PatternConfiguration{}
497492
content := tools.CreateEslintConfig(emptyConfig)
498493

@@ -560,7 +555,6 @@ func createLizardConfigFile(toolsConfigDir string, patternConfiguration []domain
560555
patterns[i] = pattern.PatternDefinition
561556
}
562557

563-
fmt.Println("Lizard configuration created based on Codacy settings")
564558
}
565559

566560
content, err := lizard.CreateLizardConfig(patterns)
@@ -573,16 +567,52 @@ func createLizardConfigFile(toolsConfigDir string, patternConfiguration []domain
573567

574568
// buildDefaultConfigurationFiles creates default configuration files for all tools
575569
func buildDefaultConfigurationFiles(toolsConfigDir string) error {
576-
// Create default Lizard configuration
577-
if err := createLizardConfigFile(toolsConfigDir, []domain.PatternConfiguration{}); err != nil {
578-
return fmt.Errorf("failed to create default Lizard configuration: %w", err)
579-
}
580570

581-
// Add other default tool configurations here as needed
582-
// For example:
583-
// if err := createDefaultEslintConfigFile(toolsConfigDir); err != nil {
584-
// return fmt.Errorf("failed to create default ESLint configuration: %w", err)
585-
// }
571+
for _, tool := range AvailableTools {
572+
patternsConfig, err := codacyclient.GetDefaultToolPatternsConfig(initFlags, tool)
573+
if err != nil {
574+
return fmt.Errorf("failed to get default tool patterns config: %w", err)
575+
}
576+
switch tool {
577+
case ESLint:
578+
eslintConfigurationString := tools.CreateEslintConfig(patternsConfig)
579+
580+
eslintConfigFile, err := os.Create(filepath.Join(toolsConfigDir, "eslint.config.mjs"))
581+
if err != nil {
582+
return fmt.Errorf("failed to create eslint config file: %v", err)
583+
}
584+
defer eslintConfigFile.Close()
585+
586+
_, err = eslintConfigFile.WriteString(eslintConfigurationString)
587+
if err != nil {
588+
return fmt.Errorf("failed to write eslint config: %v", err)
589+
}
590+
case Trivy:
591+
if err := createTrivyConfigFile(patternsConfig, toolsConfigDir); err != nil {
592+
return fmt.Errorf("failed to create default Trivy configuration: %w", err)
593+
}
594+
case PMD:
595+
if err := createPMDConfigFile(patternsConfig, toolsConfigDir); err != nil {
596+
return fmt.Errorf("failed to create default PMD configuration: %w", err)
597+
}
598+
case PyLint:
599+
if err := createPylintConfigFile(patternsConfig, toolsConfigDir); err != nil {
600+
return fmt.Errorf("failed to create default Pylint configuration: %w", err)
601+
}
602+
case DartAnalyzer:
603+
if err := createDartAnalyzerConfigFile(patternsConfig, toolsConfigDir); err != nil {
604+
return fmt.Errorf("failed to create default Dart Analyzer configuration: %w", err)
605+
}
606+
case Semgrep:
607+
if err := createSemgrepConfigFile(patternsConfig, toolsConfigDir); err != nil {
608+
return fmt.Errorf("failed to create default Semgrep configuration: %w", err)
609+
}
610+
case Lizard:
611+
if err := createLizardConfigFile(toolsConfigDir, patternsConfig); err != nil {
612+
return fmt.Errorf("failed to create default Lizard configuration: %w", err)
613+
}
614+
}
615+
}
586616

587617
return nil
588618
}
@@ -596,3 +626,14 @@ const (
596626
Semgrep string = "6792c561-236d-41b7-ba5e-9d6bee0d548b"
597627
Lizard string = "76348462-84b3-409a-90d3-955e90abfb87"
598628
)
629+
630+
// AvailableTools lists all tool UUIDs supported by Codacy CLI.
631+
var AvailableTools = []string{
632+
ESLint,
633+
Trivy,
634+
PMD,
635+
PyLint,
636+
DartAnalyzer,
637+
Semgrep,
638+
Lizard,
639+
}

cmd/init_test.go

Lines changed: 66 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
package cmd
22

33
import (
4+
"codacy/cli-v2/config"
45
"codacy/cli-v2/tools"
6+
"codacy/cli-v2/utils"
57
"os"
68
"path/filepath"
79
"testing"
@@ -161,7 +163,7 @@ func TestCleanConfigDirectory(t *testing.T) {
161163

162164
for _, file := range testFiles {
163165
filePath := filepath.Join(tempDir, file)
164-
err := os.WriteFile(filePath, []byte("test content"), 0644)
166+
err := os.WriteFile(filePath, []byte("test content"), utils.DefaultFilePerms)
165167
assert.NoError(t, err, "Failed to create test file: %s", filePath)
166168
}
167169

@@ -179,3 +181,66 @@ func TestCleanConfigDirectory(t *testing.T) {
179181
assert.NoError(t, err)
180182
assert.Equal(t, 0, len(files), "Expected 0 files after cleaning, got %d", len(files))
181183
}
184+
185+
func TestInitCommand_NoToken(t *testing.T) {
186+
tempDir := t.TempDir()
187+
originalWD, err := os.Getwd()
188+
assert.NoError(t, err, "Failed to get current working directory")
189+
defer os.Chdir(originalWD)
190+
191+
// Use the real plugins/tools/semgrep/rules.yaml file
192+
rulesPath := filepath.Join("plugins", "tools", "semgrep", "rules.yaml")
193+
if _, err := os.Stat(rulesPath); os.IsNotExist(err) {
194+
t.Skip("plugins/tools/semgrep/rules.yaml not found; skipping test")
195+
}
196+
197+
// Change to the temp directory to simulate a new project
198+
err = os.Chdir(tempDir)
199+
assert.NoError(t, err, "Failed to change working directory to tempDir")
200+
201+
// Simulate running init with no token
202+
initFlags.ApiToken = ""
203+
initFlags.Provider = ""
204+
initFlags.Organization = ""
205+
initFlags.Repository = ""
206+
207+
// Call the Run logic from initCmd
208+
if err := config.Config.CreateLocalCodacyDir(); err != nil {
209+
t.Fatalf("Failed to create local codacy directory: %v", err)
210+
}
211+
212+
toolsConfigDir := config.Config.ToolsConfigDirectory()
213+
if err := os.MkdirAll(toolsConfigDir, utils.DefaultFilePerms); err != nil {
214+
t.Fatalf("Failed to create tools-configs directory: %v", err)
215+
}
216+
217+
cliLocalMode := len(initFlags.ApiToken) == 0
218+
if cliLocalMode {
219+
noTools := []tools.Tool{}
220+
err := createConfigurationFiles(noTools, cliLocalMode)
221+
assert.NoError(t, err, "createConfigurationFiles should not return an error")
222+
if err := buildDefaultConfigurationFiles(toolsConfigDir); err != nil {
223+
t.Fatalf("Failed to build default configuration files: %v", err)
224+
}
225+
}
226+
227+
// Assert that the expected config files are created
228+
codacyDir := config.Config.LocalCodacyDirectory()
229+
expectedFiles := []string{
230+
"tools-configs/eslint.config.mjs",
231+
"tools-configs/trivy.yaml",
232+
"tools-configs/ruleset.xml",
233+
"tools-configs/pylint.rc",
234+
"tools-configs/analysis_options.yaml",
235+
"tools-configs/semgrep.yaml",
236+
"tools-configs/lizard.yaml",
237+
"codacy.yaml",
238+
"cli-config.yaml",
239+
}
240+
241+
for _, file := range expectedFiles {
242+
filePath := filepath.Join(codacyDir, file)
243+
_, err := os.Stat(filePath)
244+
assert.NoError(t, err, "Expected config file %s to be created", file)
245+
}
246+
}

0 commit comments

Comments
 (0)