From caf519a7ec5f02410d2118d44a40f97455345d70 Mon Sep 17 00:00:00 2001 From: Sylwester Piskozub Date: Thu, 4 Dec 2025 08:26:23 +0100 Subject: [PATCH 1/2] fix config management Signed-off-by: Sylwester Piskozub --- app/cli/cmd/root.go | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/app/cli/cmd/root.go b/app/cli/cmd/root.go index 4800e2cb3..e25546bf1 100644 --- a/app/cli/cmd/root.go +++ b/app/cli/cmd/root.go @@ -102,6 +102,11 @@ func NewRootCmd(l zerolog.Logger) *cobra.Command { logger.Debug().Str("path", viper.ConfigFileUsed()).Msg("using config file") + // Config management commands don't need connection setup + if isConfigManagementCommand(cmd) { + return nil + } + if apiInsecure() { logger.Warn().Msg("API contacted in insecure mode") } @@ -203,7 +208,10 @@ func NewRootCmd(l zerolog.Logger) *cobra.Command { return nil }, PersistentPostRunE: func(_ *cobra.Command, _ []string) error { - return cleanup(ActionOpts.CPConnection) + if ActionOpts != nil { + return cleanup(ActionOpts.CPConnection) + } + return nil }, } @@ -483,3 +491,22 @@ func isAPITokenPreferred(cmd *cobra.Command) bool { func getConfigDir(appName string) string { return filepath.Join(xdg.ConfigHome, appName) } + +// isConfigManagementCommand checks if the command is a config management command +// that doesn't require action options initialization +func isConfigManagementCommand(cmd *cobra.Command) bool { + // Walk up the command tree to find the parent + current := cmd + for current.Parent() != nil { + if current.Parent().Use == "config" { + switch current.Use { + // These config subcommands don't need action options + case "reset", "view", "save": + return true + } + return false + } + current = current.Parent() + } + return false +} From 8f40649da9717c87c0e3761df1e6ba4d5e781b69 Mon Sep 17 00:00:00 2001 From: Sylwester Piskozub Date: Thu, 4 Dec 2025 10:45:36 +0100 Subject: [PATCH 2/2] move check to annotations Signed-off-by: Sylwester Piskozub --- app/cli/cmd/config_reset.go | 5 ++++- app/cli/cmd/config_save.go | 5 ++++- app/cli/cmd/config_view.go | 5 ++++- app/cli/cmd/root.go | 28 ++++++---------------------- 4 files changed, 18 insertions(+), 25 deletions(-) diff --git a/app/cli/cmd/config_reset.go b/app/cli/cmd/config_reset.go index 3e7cd9131..e0d39db63 100644 --- a/app/cli/cmd/config_reset.go +++ b/app/cli/cmd/config_reset.go @@ -1,5 +1,5 @@ // -// Copyright 2023 The Chainloop Authors. +// Copyright 2023-2025 The Chainloop Authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -26,6 +26,9 @@ func newConfigResetCmd() *cobra.Command { cmd := &cobra.Command{ Use: "reset", Short: "Reset the CLI configuration", + Annotations: map[string]string{ + skipActionOptsInit: trueString, + }, Run: func(cmd *cobra.Command, args []string) { configFile := viper.ConfigFileUsed() err := os.Remove(configFile) diff --git a/app/cli/cmd/config_save.go b/app/cli/cmd/config_save.go index 6bd2a2991..25851ecaf 100644 --- a/app/cli/cmd/config_save.go +++ b/app/cli/cmd/config_save.go @@ -1,5 +1,5 @@ // -// Copyright 2023 The Chainloop Authors. +// Copyright 2023-2025 The Chainloop Authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -25,6 +25,9 @@ func newConfigSaveCmd() *cobra.Command { Use: "save", Short: "Persist the current settings to the config file", Example: "chainloop config save --control-plane localhost:1234 --artifact-cas localhost:1235", + Annotations: map[string]string{ + skipActionOptsInit: trueString, + }, RunE: func(cmd *cobra.Command, args []string) error { return viper.WriteConfig() }, diff --git a/app/cli/cmd/config_view.go b/app/cli/cmd/config_view.go index 367d1e809..ee78059cc 100644 --- a/app/cli/cmd/config_view.go +++ b/app/cli/cmd/config_view.go @@ -1,5 +1,5 @@ // -// Copyright 2023 The Chainloop Authors. +// Copyright 2023-2025 The Chainloop Authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -26,6 +26,9 @@ func newConfigViewCmd() *cobra.Command { cmd := &cobra.Command{ Use: "view", Short: "View the current CLI configuration", + Annotations: map[string]string{ + skipActionOptsInit: trueString, + }, Run: func(cmd *cobra.Command, args []string) { fmt.Printf("Config file: %s\n", viper.ConfigFileUsed()) diff --git a/app/cli/cmd/root.go b/app/cli/cmd/root.go index e25546bf1..b06e59375 100644 --- a/app/cli/cmd/root.go +++ b/app/cli/cmd/root.go @@ -58,7 +58,9 @@ const ( useAPIToken = "withAPITokenAuth" // Ask for confirmation when user token is used and API token is preferred confirmWhenUserToken = "confirmWhenUserToken" - appName = "chainloop" + // Skip ActionOpts initialization for commands that operate locally + skipActionOptsInit = "skipActionOptsInit" + appName = "chainloop" //nolint:gosec tokenEnvVarName = "CHAINLOOP_TOKEN" // Follow the convention stated on https://consoledonottrack.com/ @@ -102,8 +104,9 @@ func NewRootCmd(l zerolog.Logger) *cobra.Command { logger.Debug().Str("path", viper.ConfigFileUsed()).Msg("using config file") - // Config management commands don't need connection setup - if isConfigManagementCommand(cmd) { + // Commands annotated with skipActionOptsInit don't need ActionOpts initialization + // These are local-only commands that don't interact with the control plane + if cmd.Annotations[skipActionOptsInit] == trueString { return nil } @@ -491,22 +494,3 @@ func isAPITokenPreferred(cmd *cobra.Command) bool { func getConfigDir(appName string) string { return filepath.Join(xdg.ConfigHome, appName) } - -// isConfigManagementCommand checks if the command is a config management command -// that doesn't require action options initialization -func isConfigManagementCommand(cmd *cobra.Command) bool { - // Walk up the command tree to find the parent - current := cmd - for current.Parent() != nil { - if current.Parent().Use == "config" { - switch current.Use { - // These config subcommands don't need action options - case "reset", "view", "save": - return true - } - return false - } - current = current.Parent() - } - return false -}