Skip to content

Commit c9c7dd1

Browse files
Feature: add config reset command [PLUTO-1407] (#139)
- Introduced a new `config reset` command to reset Codacy configuration to default or repository-specific settings. - Added YAML parsing for CLI mode configuration from `.codacy/cli-config.yaml`.
1 parent 9b1d125 commit c9c7dd1

File tree

8 files changed

+812
-606
lines changed

8 files changed

+812
-606
lines changed

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,7 @@ codacy-cli
3535

3636
#Macos
3737
.DS_Store
38+
39+
40+
#Ignore vscode AI rules
41+
.github/copilot-instructions.md

cmd/analyze.go

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -264,10 +264,6 @@ func loadsToolAndPatterns(toolName string) (Tool, []Pattern) {
264264
break
265265
}
266266
}
267-
// TO DO - PANIC
268-
//if tool == nil {
269-
// return nil, nil
270-
//}
271267
var patterns []Pattern
272268
var hasNext bool = true
273269
cursor := ""
@@ -390,10 +386,6 @@ func runLizardAnalysis(workDirectory string, pathsToCheck []string, outputFile s
390386
var patterns []domain.PatternDefinition
391387
var err error
392388

393-
//this logic is here because I want to pass the config to the runner which is good for:
394-
//Separation of concerns, runner will simply run the tool now
395-
//Easier testing, since config is now passed
396-
//Avoiding fetching the default patterns in tests (unless we want to maintain codacy directory with the configs)
397389
if exists {
398390
// Configuration exists, read from file
399391
patterns, err = lizard.ReadConfig(configFile)

cmd/config.go

Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
package cmd
2+
3+
import (
4+
"fmt"
5+
"log"
6+
"os"
7+
8+
"codacy/cli-v2/cmd/configsetup"
9+
"codacy/cli-v2/config"
10+
"codacy/cli-v2/domain"
11+
"codacy/cli-v2/utils"
12+
13+
"github.com/spf13/cobra"
14+
)
15+
16+
// configResetInitFlags holds the flags for the config reset command.
17+
var configResetInitFlags domain.InitFlags
18+
19+
var configCmd = &cobra.Command{
20+
Use: "config",
21+
Short: "Manage Codacy configuration",
22+
}
23+
24+
var configResetCmd = &cobra.Command{
25+
Use: "reset",
26+
Short: "Reset Codacy configuration to default or repository-specific settings",
27+
Long: "Resets the Codacy configuration files and tool-specific configurations. " +
28+
"This command will overwrite an existing configuration with local default configurations " +
29+
"if no API token is provided (and current mode is not 'remote'). If an API token is provided, it will fetch and apply " +
30+
"repository-specific configurations from the Codacy API, effectively resetting to those.",
31+
Run: func(cmd *cobra.Command, args []string) {
32+
// Get current CLI mode from config
33+
currentCliMode, err := config.Config.GetCliMode()
34+
if err != nil {
35+
// Log the error for debugging purposes
36+
log.Printf("Warning: Could not determine CLI mode from cli-config.yaml: %v. Defaulting to 'local' mode.", err)
37+
// Show a user-facing warning on stdout
38+
fmt.Println("⚠️ Warning: Could not read or parse .codacy/cli-config.yaml. Defaulting to 'local' CLI mode.")
39+
fmt.Println(" You might want to run 'codacy-cli init' or 'codacy-cli config reset --api-token ...' to correctly set up your configuration.")
40+
fmt.Println()
41+
currentCliMode = "local" // Default to local as per existing logic
42+
}
43+
44+
apiTokenFlagProvided := len(configResetInitFlags.ApiToken) > 0
45+
46+
// If current mode is 'remote', prevent resetting to local without explicit API token for a remote reset.
47+
if currentCliMode == "remote" && !apiTokenFlagProvided {
48+
fmt.Println("Error: Your Codacy CLI is currently configured in 'remote' (cloud) mode.")
49+
fmt.Println("To reset your configuration using remote settings, you must provide the --api-token, --provider, --organization, and --repository flags.")
50+
fmt.Println("Running 'config reset' without these flags is not permitted while configured for 'remote' mode.")
51+
fmt.Println("This prevents an accidental switch to a local default configuration.")
52+
fmt.Println()
53+
if errHelp := cmd.Help(); errHelp != nil {
54+
log.Printf("Warning: Failed to display command help: %v\n", errHelp)
55+
}
56+
os.Exit(1)
57+
}
58+
59+
// Validate flags: if API token is provided, other related flags must also be provided.
60+
if apiTokenFlagProvided {
61+
if configResetInitFlags.Provider == "" || configResetInitFlags.Organization == "" || configResetInitFlags.Repository == "" {
62+
fmt.Println("Error: When using --api-token, you must also provide --provider, --organization, and --repository flags.")
63+
fmt.Println("Please provide all required flags and try again.")
64+
fmt.Println()
65+
if errHelp := cmd.Help(); errHelp != nil {
66+
log.Fatalf("Failed to display command help: %v", errHelp)
67+
}
68+
os.Exit(1)
69+
}
70+
}
71+
72+
codacyConfigFile := config.Config.ProjectConfigFile()
73+
// Check if the main configuration file exists
74+
if _, err := os.Stat(codacyConfigFile); os.IsNotExist(err) {
75+
fmt.Println("Configuration file (.codacy/codacy.yaml) not found, running initialization logic...")
76+
runConfigResetLogic(cmd, args, configResetInitFlags)
77+
} else {
78+
fmt.Println("Resetting existing Codacy configuration...")
79+
runConfigResetLogic(cmd, args, configResetInitFlags)
80+
}
81+
},
82+
}
83+
84+
// runConfigResetLogic contains the core logic for resetting or initializing the configuration.
85+
// It mirrors the behavior of the original init command but uses shared functions from the configsetup package.
86+
func runConfigResetLogic(cmd *cobra.Command, args []string, flags domain.InitFlags) {
87+
// Create local .codacy directory first
88+
if err := config.Config.CreateLocalCodacyDir(); err != nil {
89+
log.Fatalf("Failed to create local codacy directory: %v", err)
90+
}
91+
92+
// Create .codacy/tools-configs directory
93+
toolsConfigDir := config.Config.ToolsConfigDirectory()
94+
if err := os.MkdirAll(toolsConfigDir, utils.DefaultDirPerms); err != nil {
95+
log.Fatalf("Failed to create tools-configs directory: %v", err)
96+
}
97+
98+
// Determine if running in local mode (no API token)
99+
cliLocalMode := len(flags.ApiToken) == 0
100+
101+
if cliLocalMode {
102+
fmt.Println()
103+
fmt.Println("ℹ️ Resetting to local default configurations.")
104+
noTools := []domain.Tool{} // Empty slice for tools as we are in local mode without specific toolset from API initially
105+
if err := configsetup.CreateConfigurationFiles(noTools, cliLocalMode); err != nil {
106+
log.Fatalf("Failed to create base configuration files: %v", err)
107+
}
108+
// Create default configuration files for tools
109+
if err := configsetup.BuildDefaultConfigurationFiles(toolsConfigDir, flags); err != nil {
110+
log.Fatalf("Failed to build default tool configuration files: %v", err)
111+
}
112+
// Create the languages configuration file for local mode
113+
if err := configsetup.CreateLanguagesConfigFileLocal(toolsConfigDir); err != nil {
114+
log.Fatalf("Failed to create local languages configuration file: %v", err)
115+
}
116+
} else {
117+
// API token provided, fetch configuration from Codacy
118+
fmt.Println("API token specified. Fetching and applying repository-specific configurations from Codacy...")
119+
if err := configsetup.BuildRepositoryConfigurationFiles(flags); err != nil {
120+
log.Fatalf("Failed to build repository-specific configuration files: %v", err)
121+
}
122+
}
123+
124+
// Create or update .gitignore file in .codacy directory
125+
if err := configsetup.CreateGitIgnoreFile(); err != nil {
126+
log.Printf("Warning: Failed to create or update .codacy/.gitignore: %v", err) // Log as warning, not fatal
127+
}
128+
129+
fmt.Println()
130+
fmt.Println("✅ Successfully reset Codacy configuration!")
131+
fmt.Println()
132+
fmt.Println("🔧 Next steps:")
133+
fmt.Println(" 1. Run 'codacy-cli install' to install all dependencies based on the new/updated configuration.")
134+
fmt.Println(" 2. Run 'codacy-cli analyze' to start analyzing your code.")
135+
fmt.Println()
136+
}
137+
138+
func init() {
139+
// Define flags for the config reset command. These are the same flags used by the init command.
140+
configResetCmd.Flags().StringVar(&configResetInitFlags.ApiToken, "api-token", "", "Optional Codacy API token. If defined, configurations will be fetched from Codacy.")
141+
configResetCmd.Flags().StringVar(&configResetInitFlags.Provider, "provider", "", "Provider (e.g., gh, bb, gl) to fetch configurations from Codacy. Required when api-token is provided.")
142+
configResetCmd.Flags().StringVar(&configResetInitFlags.Organization, "organization", "", "Remote organization name to fetch configurations from Codacy. Required when api-token is provided.")
143+
configResetCmd.Flags().StringVar(&configResetInitFlags.Repository, "repository", "", "Remote repository name to fetch configurations from Codacy. Required when api-token is provided.")
144+
145+
// Add the reset subcommand to the config command
146+
configCmd.AddCommand(configResetCmd)
147+
// Add the config command to the root command
148+
rootCmd.AddCommand(configCmd)
149+
}

0 commit comments

Comments
 (0)