Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 12 additions & 5 deletions cmd/analyze.go
Original file line number Diff line number Diff line change
Expand Up @@ -272,10 +272,10 @@ var versionedToolNames = map[string]map[int]string{
}

var simpleToolAliases = map[string]string{
"lizard": "Lizard",
"lizard": "Lizard",
"opengrep": "Opengrep",
"pylint": "pylintpython3",
"trivy": "Trivy",
"pylint": "pylintpython3",
"trivy": "Trivy",
}

func getToolName(toolName string, version string) string {
Expand Down Expand Up @@ -328,8 +328,15 @@ func checkIfConfigExistsAndIsNeeded(toolName string, cliLocalMode bool) error {

// Check if the config file exists
if _, err := os.Stat(toolConfigPath); os.IsNotExist(err) {
// Config file does not exist - create it if we have the means to do so
if (!cliLocalMode && initFlags.ApiToken != "") || cliLocalMode {
repoConfigPath := filepath.Join(config.Config.RepositoryDirectory(), configFileName)
if _, repoErr := os.Stat(repoConfigPath); repoErr == nil {
// Config not in .codacy/tools-configs/ - check if it exists in the repo root
logger.Info("Config file found in repository root for tool, skipping config creation", logrus.Fields{
"tool": toolName,
"toolConfigPath": repoConfigPath,
})
return nil
} else if (!cliLocalMode && initFlags.ApiToken != "") || cliLocalMode {
if err := configsetup.CreateToolConfigurationFile(toolName, initFlags); err != nil {
return fmt.Errorf("failed to create config file for tool %s: %w", toolName, err)
}
Expand Down
142 changes: 99 additions & 43 deletions cmd/analyze_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -332,49 +332,81 @@ func TestCheckIfConfigExistsAndIsNeeded(t *testing.T) {
}()

tests := []struct {
name string
toolName string
cliLocalMode bool
apiToken string
configFileExists bool
expectError bool
description string
name string
toolName string
cliLocalMode bool
apiToken string
configFileExists bool
repoRootConfigExists bool
expectError bool
expectConfigCreatedInToolsDir bool
description string
}{
{
name: "tool_without_config_file",
toolName: "unsupported-tool",
cliLocalMode: false,
apiToken: "test-token",
configFileExists: false,
expectError: false,
description: "Tool that doesn't use config files should return without error",
name: "tool_without_config_file",
toolName: "unsupported-tool",
cliLocalMode: false,
apiToken: "test-token",
configFileExists: false,
repoRootConfigExists: false,
expectError: false,
expectConfigCreatedInToolsDir: false,
description: "Tool that doesn't use config files should return without error",
},
{
name: "config_file_exists",
toolName: "eslint",
cliLocalMode: false,
apiToken: "test-token",
configFileExists: true,
expectError: false,
description: "When config file exists, should find it successfully",
name: "config_file_exists_in_tools_dir",
toolName: "eslint",
cliLocalMode: false,
apiToken: "test-token",
configFileExists: true,
repoRootConfigExists: false,
expectError: false,
expectConfigCreatedInToolsDir: true,
description: "When config file exists in tools-configs, should find it successfully",
},
{
name: "remote_mode_without_token_no_config",
toolName: "eslint",
cliLocalMode: false,
apiToken: "",
configFileExists: false,
expectError: false,
description: "Remote mode without token should show appropriate message",
name: "remote_mode_without_token_no_config",
toolName: "eslint",
cliLocalMode: false,
apiToken: "",
configFileExists: false,
repoRootConfigExists: false,
expectError: false,
expectConfigCreatedInToolsDir: false,
description: "Remote mode without token and no config anywhere should not create defaults",
},
{
name: "local_mode_no_config",
toolName: "eslint",
cliLocalMode: true,
apiToken: "",
configFileExists: false,
expectError: false,
description: "Local mode should create config file if tools-configs directory exists",
name: "local_mode_no_config",
toolName: "eslint",
cliLocalMode: true,
apiToken: "",
configFileExists: false,
repoRootConfigExists: false,
expectError: false,
expectConfigCreatedInToolsDir: true,
description: "Local mode with no config anywhere should create a default config in tools-configs",
},
{
name: "local_mode_config_exists_in_repo_root",
toolName: "eslint",
cliLocalMode: true,
apiToken: "",
configFileExists: false,
repoRootConfigExists: true,
expectError: false,
expectConfigCreatedInToolsDir: false,
description: "Local mode should not create default config when user's own config exists in repo root",
},
{
name: "remote_mode_with_token_config_exists_in_repo_root",
toolName: "eslint",
cliLocalMode: false,
apiToken: "test-token",
configFileExists: false,
repoRootConfigExists: true,
expectError: false,
expectConfigCreatedInToolsDir: false,
description: "Remote mode should not create default config when user's own config exists in repo root",
},
}

Expand All @@ -392,7 +424,7 @@ func TestCheckIfConfigExistsAndIsNeeded(t *testing.T) {
// Mock config to use our temporary directory BEFORE creating files
config.Config = *config.NewConfigType(tmpDir, tmpDir, tmpDir)

// Create config file if needed - using the same path logic as the function under test
// Create config file in tools-configs if needed
if tt.configFileExists && constants.ToolConfigFileNames[tt.toolName] != "" {
// Use config.Config.ToolsConfigDirectory() to get the exact same path the function will use
toolsConfigDir := config.Config.ToolsConfigDirectory()
Expand All @@ -408,6 +440,13 @@ func TestCheckIfConfigExistsAndIsNeeded(t *testing.T) {
require.NoError(t, err, "Config file should exist at %s", configPath)
}

// Create config file in repo root if needed
if tt.repoRootConfigExists && constants.ToolConfigFileNames[tt.toolName] != "" {
repoRootConfigPath := filepath.Join(config.Config.RepositoryDirectory(), constants.ToolConfigFileNames[tt.toolName])
err = os.WriteFile(repoRootConfigPath, []byte("user's own config"), constants.DefaultFilePerms)
require.NoError(t, err)
}

// Setup initFlags
initFlags = domain.InitFlags{
ApiToken: tt.apiToken,
Expand All @@ -423,6 +462,30 @@ func TestCheckIfConfigExistsAndIsNeeded(t *testing.T) {
// Execute the function
err = checkIfConfigExistsAndIsNeeded(tt.toolName, tt.cliLocalMode)

// Verify results
if tt.expectError {
assert.Error(t, err, tt.description)
} else {
assert.NoError(t, err, tt.description)
}
// Verify whether a config was created in .codacy/tools-configs/
if constants.ToolConfigFileNames[tt.toolName] != "" {
toolsConfigDir := config.Config.ToolsConfigDirectory()
generatedConfigPath := filepath.Join(toolsConfigDir, constants.ToolConfigFileNames[tt.toolName])
_, statErr := os.Stat(generatedConfigPath)
configCreated := statErr == nil

if tt.expectConfigCreatedInToolsDir {
assert.True(t, configCreated,
"%s: expected a config file to exist in tools-configs at %s",
tt.description, generatedConfigPath)
} else {
assert.True(t, os.IsNotExist(statErr),
"%s: expected NO config file to be created in tools-configs, but found one at %s",
tt.description, generatedConfigPath)
}
}

// Clean up any files that might have been created by the function under test
if !tt.configFileExists && constants.ToolConfigFileNames[tt.toolName] != "" {
toolsConfigDir := config.Config.ToolsConfigDirectory()
Expand All @@ -431,13 +494,6 @@ func TestCheckIfConfigExistsAndIsNeeded(t *testing.T) {
os.Remove(configPath)
}
}

// Verify results
if tt.expectError {
assert.Error(t, err, tt.description)
} else {
assert.NoError(t, err, tt.description)
}
})
}
}
Expand Down
Loading