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
5 changes: 4 additions & 1 deletion cmd/ctrlc/root/api/get/deployment/deployment.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,10 @@ func NewDeploymentCmd() *cobra.Command {
return fmt.Errorf("failed to create API client: %w", err)
}

workspaceID := client.GetWorkspaceID(cmd.Context(), workspace)
workspaceID, err := client.GetWorkspaceID(cmd.Context(), workspace)
if err != nil {
return err
}
resp, err := client.GetDeploymentByName(cmd.Context(), workspaceID.String(), name)
if err != nil {
return fmt.Errorf("failed to get deployment: %w", err)
Expand Down
5 changes: 4 additions & 1 deletion cmd/ctrlc/root/api/get/release/release.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,10 @@ func NewReleaseCmd() *cobra.Command {
return fmt.Errorf("failed to create API client: %w", err)
}

workspaceID := client.GetWorkspaceID(cmd.Context(), workspace)
workspaceID, err := client.GetWorkspaceID(cmd.Context(), workspace)
if err != nil {
return err
}
resp, err := client.GetRelease(cmd.Context(), workspaceID.String(), releaseID)
if err != nil {
return fmt.Errorf("failed to get release: %w", err)
Expand Down
5 changes: 4 additions & 1 deletion cmd/ctrlc/root/api/get/releasetargets/releasetargets.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,10 @@ func NewReleaseTargetsCmd() *cobra.Command {
return fmt.Errorf("failed to create API client: %w", err)
}

workspaceID := client.GetWorkspaceID(cmd.Context(), workspace)
workspaceID, err := client.GetWorkspaceID(cmd.Context(), workspace)
if err != nil {
return err
}

params := &api.PreviewReleaseTargetsForResourceParams{}
if limit > 0 {
Expand Down
5 changes: 4 additions & 1 deletion cmd/ctrlc/root/api/get/resources/resources.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,10 @@ func NewResourcesCmd() *cobra.Command {
return fmt.Errorf("failed to create API client: %w", err)
}

workspaceID := client.GetWorkspaceID(cmd.Context(), workspace)
workspaceID, err := client.GetWorkspaceID(cmd.Context(), workspace)
if err != nil {
return err
}

params := &api.GetAllResourcesParams{}
if limit > 0 {
Expand Down
5 changes: 4 additions & 1 deletion cmd/ctrlc/root/api/plan/version/version.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,10 @@ func NewPlanVersionCmd() *cobra.Command {
metadata["ctrlplane/links"] = string(linksJSON)
}

workspaceID := client.GetWorkspaceID(cmd.Context(), workspace)
workspaceID, err := client.GetWorkspaceID(cmd.Context(), workspace)
if err != nil {
return err
}

config := cliutil.ConvertConfigArrayToNestedMap(configArray)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,10 @@ func NewUpsertDeploymentVersionCmd() *cobra.Command {
stat = &s
}

workspaceID := client.GetWorkspaceID(cmd.Context(), workspace)
workspaceID, err := client.GetWorkspaceID(cmd.Context(), workspace)
if err != nil {
return err
}

config := cliutil.ConvertConfigArrayToNestedMap(configArray)

Expand Down
7 changes: 3 additions & 4 deletions cmd/ctrlc/root/apply/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import (
"github.com/ctrlplanedev/cli/internal/api/providers"
"github.com/ctrlplanedev/cli/internal/api/resolver"
"github.com/fatih/color"
"github.com/google/uuid"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)
Expand Down Expand Up @@ -76,9 +75,9 @@ func runApply(ctx context.Context, filePatterns []string, selectorRaw string) er
return fmt.Errorf("failed to create API client: %w", err)
}

workspaceID := client.GetWorkspaceID(ctx, workspace)
if workspaceID == uuid.Nil {
return fmt.Errorf("workspace not found: %s", workspace)
workspaceID, err := client.GetWorkspaceID(ctx, workspace)
if err != nil {
return err
}

resolver := resolver.NewAPIResolver(client, workspaceID)
Expand Down
2 changes: 2 additions & 0 deletions cmd/ctrlc/root/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
"github.com/ctrlplanedev/cli/cmd/ctrlc/root/sync"
"github.com/ctrlplanedev/cli/cmd/ctrlc/root/ui"
"github.com/ctrlplanedev/cli/cmd/ctrlc/root/version"
"github.com/ctrlplanedev/cli/cmd/ctrlc/root/workflow"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)
Expand Down Expand Up @@ -63,6 +64,7 @@ func NewRootCmd() *cobra.Command {
cmd.AddCommand(run.NewRunCmd())
cmd.AddCommand(ui.NewUICmd())
cmd.AddCommand(version.NewVersionCmd())
cmd.AddCommand(workflow.NewWorkflowCmd())

return cmd
}
6 changes: 5 additions & 1 deletion cmd/ctrlc/root/sync/pipe/pipe.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,11 @@ func NewSyncPipeCmd() *cobra.Command {
return fmt.Errorf("failed to upsert resources: %w", err)
}

workspaceID := ctrlplaneClient.GetWorkspaceID(ctx, workspace).String()
workspaceUUID, err := ctrlplaneClient.GetWorkspaceID(ctx, workspace)
if err != nil {
return err
}
workspaceID := workspaceUUID.String()
if err := syncResourceVariables(ctx, ctrlplaneClient, workspaceID, resourceInputs); err != nil {
return err
}
Expand Down
6 changes: 3 additions & 3 deletions cmd/ctrlc/root/ui/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,9 @@ func NewUICmd() *cobra.Command {
}

// Resolve workspace slug to UUID
workspaceID := client.GetWorkspaceID(cmd.Context(), workspace)
if workspaceID.String() == "00000000-0000-0000-0000-000000000000" {
return fmt.Errorf("failed to resolve workspace: %s", workspace)
workspaceID, err := client.GetWorkspaceID(cmd.Context(), workspace)
if err != nil {
return err
}

// Load last-viewed resource type (default: resources)
Expand Down
63 changes: 63 additions & 0 deletions cmd/ctrlc/root/workflow/list.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package workflow

import (
"fmt"

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

func NewListCmd() *cobra.Command {
var limit int
var offset int

cmd := &cobra.Command{
Use: "list",
Short: "List workflows",
Long: `List all workflows in the workspace.`,
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, err := client.GetWorkspaceID(cmd.Context(), workspace)
if err != nil {
return err
}

if limit < 0 {
return fmt.Errorf("invalid --limit %d, must be non-negative", limit)
}
if offset < 0 {
return fmt.Errorf("invalid --offset %d, must be non-negative", offset)
}

params := &api.ListWorkflowsParams{}
if limit > 0 {
params.Limit = &limit
}
if offset > 0 {
params.Offset = &offset
}
Comment thread
coderabbitai[bot] marked this conversation as resolved.

resp, err := client.ListWorkflows(cmd.Context(), workspaceID.String(), params)
if err != nil {
return fmt.Errorf("failed to list workflows: %w", err)
}

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

cmd.Flags().IntVarP(&limit, "limit", "l", 50, "Limit the number of results")
cmd.Flags().IntVarP(&offset, "offset", "o", 0, "Offset the results")

return cmd
}
66 changes: 66 additions & 0 deletions cmd/ctrlc/root/workflow/trigger.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package workflow

import (
"fmt"
"strings"

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

func NewTriggerCmd() *cobra.Command {
var inputFlags []string

cmd := &cobra.Command{
Use: "trigger <workflow-id>",
Short: "Trigger a workflow run",
Long: `Trigger a workflow run with the given inputs.`,
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
workflowID := args[0]

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, err := client.GetWorkspaceID(cmd.Context(), workspace)
if err != nil {
return err
}

inputs := make(map[string]interface{})
for _, input := range inputFlags {
key, value, found := strings.Cut(input, "=")
if !found {
return fmt.Errorf("invalid input format %q, expected key=value", input)
}
if key == "" {
return fmt.Errorf("invalid input format %q, empty key, expected key=value", input)
}
inputs[key] = value
}
Comment thread
coderabbitai[bot] marked this conversation as resolved.

body := api.CreateWorkflowRunJSONRequestBody{
Inputs: inputs,
}

resp, err := client.CreateWorkflowRun(cmd.Context(), workspaceID.String(), workflowID, body)
if err != nil {
return fmt.Errorf("failed to trigger workflow: %w", err)
}

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

cmd.Flags().StringArrayVarP(&inputFlags, "input", "i", nil, "Input key=value pair (can be specified multiple times)")

return cmd
}
21 changes: 21 additions & 0 deletions cmd/ctrlc/root/workflow/workflow.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package workflow

import (
"github.com/spf13/cobra"
)

func NewWorkflowCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "workflow <subcommand>",
Short: "Manage workflows",
Long: `Commands for listing and triggering workflows.`,
RunE: func(cmd *cobra.Command, args []string) error {
return cmd.Help()
},
}

cmd.AddCommand(NewListCmd())
cmd.AddCommand(NewTriggerCmd())

return cmd
}
23 changes: 21 additions & 2 deletions internal/api/client.gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 9 additions & 7 deletions internal/api/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,20 +23,22 @@ func NewAPIKeyClientWithResponses(server string, apiKey string) (*ClientWithResp
)
}

func (c *ClientWithResponses) GetWorkspaceID(ctx context.Context, workspace string) uuid.UUID {
id, err := uuid.Parse(workspace)
if err == nil {
return id
func (c *ClientWithResponses) GetWorkspaceID(ctx context.Context, workspace string) (uuid.UUID, error) {
if id, err := uuid.Parse(workspace); err == nil {
return id, nil
}

resp, err := c.GetWorkspaceBySlugWithResponse(ctx, workspace)
if err != nil {
return uuid.Nil
return uuid.Nil, fmt.Errorf("failed to look up workspace %q: %w", workspace, err)
}

if resp.JSON200 == nil {
return uuid.Nil
if resp.StatusCode() == http.StatusNotFound {
return uuid.Nil, fmt.Errorf("workspace %q not found", workspace)
}
return uuid.Nil, fmt.Errorf("failed to look up workspace %q: %s: %s", workspace, resp.Status(), strings.TrimSpace(string(resp.Body)))
}

return resp.JSON200.Id
return resp.JSON200.Id, nil
}
6 changes: 3 additions & 3 deletions internal/api/resolver/resolver.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@ func NewAPIResolver(client *api.ClientWithResponses, workspaceID uuid.UUID) *API
}

func NewAPIResolverFromWorkspace(ctx context.Context, client *api.ClientWithResponses, workspace string) (*APIResolver, error) {
workspaceID := client.GetWorkspaceID(ctx, workspace)
if workspaceID == uuid.Nil {
return nil, fmt.Errorf("workspace not found: %s", workspace)
workspaceID, err := client.GetWorkspaceID(ctx, workspace)
if err != nil {
return nil, err
}
return NewAPIResolver(client, workspaceID), nil
}
Expand Down
5 changes: 4 additions & 1 deletion internal/resources/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,10 @@ func NewAPIResourceService(ctx context.Context, apiURL, apiKey, workspace string
return nil, fmt.Errorf("failed to create API client: %w", err)
}

workspaceID := client.GetWorkspaceID(ctx, workspace)
workspaceID, err := client.GetWorkspaceID(ctx, workspace)
if err != nil {
return nil, err
}
log.Debug("resolved workspace", "input", workspace, "workspaceID", workspaceID.String())

return &APIResourceService{
Expand Down
6 changes: 5 additions & 1 deletion pkg/resourceprovider/resourceprovider.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,11 @@ import (

func New(client *api.ClientWithResponses, workspace string, name string) (*ResourceProvider, error) {
ctx := context.Background()
workspaceId := client.GetWorkspaceID(ctx, workspace).String()
workspaceUUID, err := client.GetWorkspaceID(ctx, workspace)
if err != nil {
return nil, err
}
workspaceId := workspaceUUID.String()

log.Debug("Upserting resource provider", "workspaceId", workspaceId, "name", name)

Expand Down
Loading