From 36fb95b8a188d0218778a220152aad6ecccaa4af Mon Sep 17 00:00:00 2001 From: Mark Shine Date: Sun, 30 Aug 2026 03:03:05 +0200 Subject: [PATCH] Shell completions never ask for a login `brew install taelio/tap/tael` failed at the last step: the formula runs `tael completion bash|zsh|fish` to generate completions, and the CLI answered "not logged in" (exit 3). Only cobra's hidden __complete helpers were exempt from the login gate; the user-facing generator was not, and its shells are named bash/zsh/fish, so a name check on the leaf never saw it. The gate now walks up to the `completion` command directly under the root. Everything else still needs a login. Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01T6qrk4NVPAGeac6YuALp1M --- cmd/completion_test.go | 58 ++++++++++++++++++++++++++++++++++++++++++ cmd/root.go | 16 ++++++++++++ 2 files changed, 74 insertions(+) create mode 100644 cmd/completion_test.go diff --git a/cmd/completion_test.go b/cmd/completion_test.go new file mode 100644 index 0000000..4cfb242 --- /dev/null +++ b/cmd/completion_test.go @@ -0,0 +1,58 @@ +package cmd + +import ( + "context" + "io" + "path/filepath" + "testing" + + "github.com/spf13/cobra" +) + +// TestCompletionNeedsNoLogin runs the shell completion generator the way +// Homebrew does at install time: no token anywhere, no config file yet. +// Cobra binds the generator's writer on the first execution in a process, +// so the script itself is not captured here; the refusal is what matters. +func TestCompletionNeedsNoLogin(t *testing.T) { + t.Setenv("TAEL_CONFIG", filepath.Join(t.TempDir(), "tael.yaml")) + t.Setenv(envAPIToken, "") + t.Setenv(envBaseURL, "") + t.Setenv(envWorkspace, "") + resetFlags(rootCmd) + + rootCmd.SetOut(io.Discard) + rootCmd.SetErr(io.Discard) + rootCmd.SetArgs([]string{"completion", "zsh"}) + t.Cleanup(func() { + resetFlags(rootCmd) + rootCmd.SetOut(nil) + rootCmd.SetErr(nil) + rootCmd.SetArgs(nil) + }) + if _, executeError := rootCmd.ExecuteContextC(context.Background()); executeError != nil { + t.Fatalf("tael completion zsh must not need a login, got: %v", executeError) + } +} + +// TestCommandRequiresAuthExemptsOnlyTheRootCompletion pins the rule: the +// `completion` command directly under the root and its shells are exempt; +// a command that merely happens to be called completion elsewhere is not. +func TestCommandRequiresAuthExemptsOnlyTheRootCompletion(t *testing.T) { + root := &cobra.Command{Use: "tael"} + completion := &cobra.Command{Use: "completion"} + zsh := &cobra.Command{Use: "zsh"} + root.AddCommand(completion) + completion.AddCommand(zsh) + + apps := &cobra.Command{Use: "apps"} + nested := &cobra.Command{Use: "completion"} + root.AddCommand(apps) + apps.AddCommand(nested) + + if commandRequiresAuth(completion) || commandRequiresAuth(zsh) { + t.Fatal("completion and its shells must not require a login") + } + if !commandRequiresAuth(apps) || !commandRequiresAuth(nested) { + t.Fatal("every other command still requires a login") + } +} diff --git a/cmd/root.go b/cmd/root.go index a334538..04dbaa9 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -156,6 +156,9 @@ func commandRequiresAuth(command *cobra.Command) bool { case "help", cobra.ShellCompRequestCmd, cobra.ShellCompNoDescRequestCmd: return false } + if isShellCompletionCommand(command) { + return false + } for current := command; current != nil; current = current.Parent() { if current.Annotations == nil { continue @@ -166,3 +169,16 @@ func commandRequiresAuth(command *cobra.Command) bool { } return true } + +// isShellCompletionCommand reports whether the command is cobra's +// `completion ` generator or one of its shells. Cobra adds it at +// execution time, so it cannot carry the annotation; Homebrew runs it while +// installing, before anyone has logged in. +func isShellCompletionCommand(command *cobra.Command) bool { + for current := command; current != nil; current = current.Parent() { + if current.Name() == "completion" && current.HasParent() && !current.Parent().HasParent() { + return true + } + } + return false +}