From fa4d86c654be2deb277d0c5965dea471ed58ed6f Mon Sep 17 00:00:00 2001 From: Arunesh Dwivedi Date: Mon, 20 Jul 2026 06:47:02 +0000 Subject: [PATCH] fix: allow completion command without storage config The generated completion command (and its subcommands) ran through PersistentPreRunE, which requires a configured storage type and password, so 'scrt completion bash' failed with 'missing storage type'. Short-circuit the completion command and its children so generating shell completion does not require a store. Added a regression test. Signed-off-by: Arunesh Dwivedi --- cmd/root.go | 9 +++++++++ cmd/root_test.go | 42 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+) diff --git a/cmd/root.go b/cmd/root.go index b1d4cfab..54f0ed3b 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -54,6 +54,15 @@ var RootCmd = &cobra.Command{ return nil } + // Short circuit for the generated completion command and its + // subcommands (bash, zsh, fish, powershell). Generating shell + // completion must not require a configured storage or password. + for c := cmd; c != nil; c = c.Parent() { + if c.Name() == "completion" { + return nil + } + } + err := readConfig(cmd) if err != nil { return err diff --git a/cmd/root_test.go b/cmd/root_test.go index 95337633..a4df0544 100644 --- a/cmd/root_test.go +++ b/cmd/root_test.go @@ -19,6 +19,7 @@ import ( "github.com/golang/mock/gomock" "github.com/spf13/afero" + "github.com/spf13/cobra" "github.com/spf13/viper" "github.com/loderunner/scrt/backend" @@ -53,3 +54,44 @@ func TestRootCmd(t *testing.T) { t.Fatal(err) } } + +func TestCompletionDoesNotRequireStorage(t *testing.T) { + viper.Reset() + + // Ensure the generated completion command is attached to RootCmd. + RootCmd.InitDefaultCompletionCmd() + + // Find the generated completion command and one of its subcommands + // (e.g. bash). Generating shell completion must not require a configured + // storage backend or password. + var completionCmd *cobra.Command + for _, c := range RootCmd.Commands() { + if c.Name() == "completion" { + completionCmd = c + break + } + } + if completionCmd == nil { + t.Fatal("completion command not found") + } + + // The completion command itself + if err := RootCmd.PersistentPreRunE(completionCmd, []string{}); err != nil { + t.Fatalf("completion command should short-circuit: %v", err) + } + + // A completion subcommand (bash) must also short-circuit via its parent. + var bashCmd *cobra.Command + for _, c := range completionCmd.Commands() { + if c.Name() == "bash" { + bashCmd = c + break + } + } + if bashCmd == nil { + t.Fatal("completion bash subcommand not found") + } + if err := RootCmd.PersistentPreRunE(bashCmd, []string{}); err != nil { + t.Fatalf("completion bash subcommand should short-circuit: %v", err) + } +}