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
23 changes: 22 additions & 1 deletion internal/cmd/variable/create/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ type Options struct {
name string
environmentID string
keys map[string]string
rawKeys []string
skipConfirm bool
inputDone bool
}
Expand All @@ -36,7 +37,7 @@ func NewCmdCreateVariable(f *cmdutil.Factory) *cobra.Command {
util.AddServiceParam(cmd, &opts.id, &opts.name)
util.AddEnvOfServiceParam(cmd, &opts.environmentID)
cmd.Flags().BoolVarP(&opts.skipConfirm, "yes", "y", false, "Skip confirmation")
cmd.Flags().StringToStringVarP(&opts.keys, "key", "k", nil, "Key value pair of the variable")
cmd.Flags().StringArrayVarP(&opts.rawKeys, "key", "k", nil, "Key value pair of the variable (KEY=VALUE)")
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

--key should bypass prompts in interactive sessions, but currently doesn’t.

Line 40 captures raw --key values, yet Line 102-109 parses them only in the non-interactive path. With f.Interactive=true, users are still forced into prompts even when flags are supplied.

Suggested fix
func runCreateVariable(f *cmdutil.Factory, opts *Options) error {
+	// If --key is provided, execute flag-driven flow directly.
+	if len(opts.rawKeys) > 0 {
+		return runCreateVariableNonInteractive(f, opts)
+	}
 	if f.Interactive {
 		return runCreateVariableInteractive(f, opts)
 	} else {
 		return runCreateVariableNonInteractive(f, opts)
 	}
}

As per coding guidelines: "Commands should support both interactive and non-interactive modes; if a flag is provided, skip the interactive prompt".

Also applies to: 102-109

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/cmd/variable/create/create.go` at line 40, The interactive prompt
path currently ignores the supplied --key/-k flags (opts.rawKeys) causing
prompts even when flags exist; change the logic in the create command so that
before invoking interactive prompts (check f.Interactive), you parse
opts.rawKeys into the expected map/list (the same parsing done in the
non-interactive branch around the current parsing block that uses opts.rawKeys
-> opts.Pairs or similar) and, if any keys were provided, bypass the prompt and
use the parsed values; ensure you reference and reuse the existing parsing
routine or replicate its behavior so opts.rawKeys is honored and prompts are
skipped when non-empty.


return cmd
}
Expand Down Expand Up @@ -85,7 +86,27 @@ func runCreateVariableInteractive(f *cmdutil.Factory, opts *Options) error {
return runCreateVariableNonInteractive(f, opts)
}

func parseRawKeys(rawKeys []string) (map[string]string, error) {
result := make(map[string]string, len(rawKeys))
for _, raw := range rawKeys {
parts := strings.SplitN(raw, "=", 2)
if len(parts) != 2 || parts[0] == "" {
return nil, fmt.Errorf("invalid --key format %q: expected KEY=VALUE", raw)
}
result[parts[0]] = parts[1]
}
return result, nil
}

func runCreateVariableNonInteractive(f *cmdutil.Factory, opts *Options) error {
// Parse rawKeys from StringArrayVar into the keys map (non-interactive mode)
if opts.keys == nil && len(opts.rawKeys) > 0 {
parsed, err := parseRawKeys(opts.rawKeys)
if err != nil {
return err
}
opts.keys = parsed
}
if opts.id == "" && opts.name != "" {
service, err := util.GetServiceByName(f.Config, f.ApiClient, opts.name)
if err != nil {
Expand Down
24 changes: 23 additions & 1 deletion internal/cmd/variable/update/update.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package update
import (
"context"
"fmt"
"strings"

"github.com/briandowns/spinner"
"github.com/spf13/cobra"
Expand All @@ -16,6 +17,7 @@ type Options struct {
name string
environmentID string
keys map[string]string
rawKeys []string
skipConfirm bool
inputDone bool
}
Expand All @@ -35,7 +37,7 @@ func NewCmdUpdateVariable(f *cmdutil.Factory) *cobra.Command {
util.AddServiceParam(cmd, &opts.id, &opts.name)
util.AddEnvOfServiceParam(cmd, &opts.environmentID)
cmd.Flags().BoolVarP(&opts.skipConfirm, "yes", "y", false, "Skip confirmation")
cmd.Flags().StringToStringVarP(&opts.keys, "key", "k", nil, "Key value pair of the variable")
cmd.Flags().StringArrayVarP(&opts.rawKeys, "key", "k", nil, "Key value pair of the variable (KEY=VALUE)")
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

--key input is ignored when running interactively.

Line 40 accepts --key, but Line 122-129 only parses it in the non-interactive path. In an interactive terminal, runUpdateVariable still prompts instead of honoring provided flags, which breaks expected flag-driven execution.

Suggested fix
func runUpdateVariable(f *cmdutil.Factory, opts *Options) error {
+	// If --key is provided, honor flags and skip interactive prompts.
+	if len(opts.rawKeys) > 0 {
+		return runUpdateVariableNonInteractive(f, opts)
+	}
 	if f.Interactive {
 		opts.keys = make(map[string]string)
 		return runUpdateVariableInteractive(f, opts)
 	}
 	return runUpdateVariableNonInteractive(f, opts)
}

As per coding guidelines: "Commands should support both interactive and non-interactive modes; if a flag is provided, skip the interactive prompt".

Also applies to: 122-129

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/cmd/variable/update/update.go` at line 40, runUpdateVariable
currently ignores opts.rawKeys in the interactive path; update runUpdateVariable
to check opts.rawKeys (the flag bound via cmd.Flags().StringArrayVarP) and, when
non-empty, skip the interactive prompt and call the existing parseKeyPairs (or
equivalent) to populate the variable values instead of prompting. Ensure you
reference opts.rawKeys, runUpdateVariable, and parseKeyPairs (or the function
used at 122-129 in the non-interactive path) so the non-interactive parsing
logic is reused for both modes.


return cmd
}
Expand Down Expand Up @@ -104,7 +106,27 @@ func runUpdateVariableInteractive(f *cmdutil.Factory, opts *Options) error {
return runUpdateVariableNonInteractive(f, opts)
}

func parseRawKeys(rawKeys []string) (map[string]string, error) {
result := make(map[string]string, len(rawKeys))
for _, raw := range rawKeys {
parts := strings.SplitN(raw, "=", 2)
if len(parts) != 2 || parts[0] == "" {
return nil, fmt.Errorf("invalid --key format %q: expected KEY=VALUE", raw)
}
result[parts[0]] = parts[1]
}
return result, nil
}

func runUpdateVariableNonInteractive(f *cmdutil.Factory, opts *Options) error {
// Parse rawKeys from StringArrayVar into the keys map (non-interactive mode)
if opts.keys == nil && len(opts.rawKeys) > 0 {
parsed, err := parseRawKeys(opts.rawKeys)
if err != nil {
return err
}
opts.keys = parsed
}
if opts.id == "" && opts.name != "" {
service, err := util.GetServiceByName(f.Config, f.ApiClient, opts.name)
if err != nil {
Expand Down