Skip to content
Merged
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
44 changes: 44 additions & 0 deletions cmd/ctrlc/root/api/get/deployment/deployment.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package deployment

import (
"fmt"

"github.com/ctrlplanedev/cli/internal/api"
"github.com/ctrlplanedev/cli/internal/cliutil"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)

func NewDeploymentCmd() *cobra.Command {
var name string
cmd := &cobra.Command{
Use: "deployment",
Short: "Get a deployment",
Long: "Get a deployment by name",
RunE: func(cmd *cobra.Command, args []string) error {
apiURL := viper.GetString("url")
apiKey := viper.GetString("api-key")
workspace := viper.GetString("workspace")

client, err := api.NewAPIKeyClientWithResponses(apiURL, apiKey)
if err != nil {
return fmt.Errorf("failed to create API client: %w", err)
}

workspaceID := client.GetWorkspaceID(cmd.Context(), workspace)
resp, err := client.GetDeploymentByName(cmd.Context(), workspaceID.String(), name)
if err != nil {
return fmt.Errorf("failed to get deployment: %w", err)
}

return cliutil.HandleResponseOutput(cmd, resp)
},
}

cmd.Flags().StringVarP(&name, "name", "n", "", "Deployment name")
cmd.MarkFlagRequired("name")

cmd.MarkFlagRequired("workspace")
Comment on lines +39 to +41
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify how `workspace` is declared and whether this command can mark it required.
# Expected:
# - If workspace is only persistent on a parent command, MarkFlagRequired here won't enforce it.
# - Identify other command patterns used in this repo for inherited required flags.

rg -n -C3 'StringVarP?\([^)]*"workspace"' --type=go
rg -n -C3 'PersistentFlags\(\)\.StringVarP?\([^)]*"workspace"' --type=go
rg -n -C3 'MarkFlagRequired\("workspace"\)|MarkPersistentFlagRequired\("workspace"\)' --type=go

Repository: ctrlplanedev/cli

Length of output: 4973


🏁 Script executed:

cat -n cmd/ctrlc/root/api/get/deployment/deployment.go

Repository: ctrlplanedev/cli

Length of output: 1498


🏁 Script executed:

# Check parent commands to see if workspace is a persistent flag
rg -n "PersistentFlags" cmd/ctrlc/root/api/get/deployment/ --type=go -A5
rg -n "PersistentFlags" cmd/ctrlc/root/api/ --type=go -A5 | head -50

Repository: ctrlplanedev/cli

Length of output: 626


🏁 Script executed:

# Check the root/api command structure
cat -n cmd/ctrlc/root/api/api.go | head -100

Repository: ctrlplanedev/cli

Length of output: 2047


🏁 Script executed:

# Check root command for persistent flags
cat -n cmd/ctrlc/root/root.go | head -150

Repository: ctrlplanedev/cli

Length of output: 2494


🏁 Script executed:

# Check how other get commands handle workspace
cat -n cmd/ctrlc/root/api/get/release/release.go

Repository: ctrlplanedev/cli

Length of output: 1475


🏁 Script executed:

# Check get/resources
cat -n cmd/ctrlc/root/api/get/resources/resources.go

Repository: ctrlplanedev/cli

Length of output: 2003


🏁 Script executed:

# Check how many commands have this workspace MarkFlagRequired pattern
rg -l 'MarkFlagRequired\("workspace"\)' cmd/ctrlc/root/ --type=go

Repository: ctrlplanedev/cli

Length of output: 228


🏁 Script executed:

# For each file with this pattern, check if workspace is declared as a local flag
for file in $(rg -l 'MarkFlagRequired\("workspace"\)' cmd/ctrlc/root/ --type=go); do
  echo "=== $file ==="
  if grep -q 'StringVarP.*"workspace"' "$file"; then
    echo "✓ workspace IS declared as local flag"
  else
    echo "✗ workspace NOT declared as local flag"
  fi
done

Repository: ctrlplanedev/cli

Length of output: 415


Required-flag enforcement for workspace is not working and affects 3 commands.

Line 41 calls MarkFlagRequired("workspace") on a flag that is not declared in this command. Cobra silently ignores this call, so no validation occurs. The workspace value comes only from viper.GetString() at runtime (line 21); if empty, it will be passed to client.GetWorkspaceID() and likely cause runtime errors.

This same issue affects cmd/ctrlc/root/api/get/release/release.go and cmd/ctrlc/root/api/get/resources/resources.go — both call MarkFlagRequired("workspace") without declaring the flag locally. Only cmd/ctrlc/root/agent/run/run.go correctly declares the flag before marking it required.

Add runtime validation for workspace in the RunE function to ensure early failure with a clear error message:

Suggested fix
 		RunE: func(cmd *cobra.Command, args []string) error {
 			apiURL := viper.GetString("url")
 			apiKey := viper.GetString("api-key")
 			workspace := viper.GetString("workspace")
+			if workspace == "" {
+				return fmt.Errorf("workspace is required")
+			}

Remove the ineffective MarkFlagRequired() calls on line 39 and 41, or declare workspace as an actual flag if it should be user-provided.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@cmd/ctrlc/root/api/get/deployment/deployment.go` around lines 39 - 41, The
command calls cmd.MarkFlagRequired("workspace") for a flag that isn't declared,
so add explicit runtime validation inside the command's RunE handler (the RunE
function for this get deployment command) to fetch the workspace via
viper.GetString("workspace") and return an error like "workspace is required" if
it's empty; alternatively, if workspace should be a user flag, declare it on the
command (e.g., cmd.Flags().String("workspace", "", "...")) before calling
cmd.MarkFlagRequired("workspace"). Also remove any ineffective
MarkFlagRequired("workspace") calls if you choose the runtime validation route.


return cmd
}
2 changes: 2 additions & 0 deletions cmd/ctrlc/root/api/get/get.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package get

import (
"github.com/ctrlplanedev/cli/cmd/ctrlc/root/api/get/deployment"
"github.com/ctrlplanedev/cli/cmd/ctrlc/root/api/get/release"
"github.com/ctrlplanedev/cli/cmd/ctrlc/root/api/get/releasetargets"
"github.com/ctrlplanedev/cli/cmd/ctrlc/root/api/get/resources"
Expand All @@ -20,6 +21,7 @@ func NewGetCmd() *cobra.Command {
cmd.AddCommand(resources.NewResourcesCmd())
cmd.AddCommand(release.NewReleaseCmd())
cmd.AddCommand(releasetargets.NewReleaseTargetsCmd())
cmd.AddCommand(deployment.NewDeploymentCmd())

return cmd
}
Loading
Loading