Skip to content

feat: workflow list and trigger commands#68

Merged
dacbd merged 7 commits into
mainfrom
ctrlc-workflow-cmd
May 14, 2026
Merged

feat: workflow list and trigger commands#68
dacbd merged 7 commits into
mainfrom
ctrlc-workflow-cmd

Conversation

@adityachoudhari26
Copy link
Copy Markdown
Member

@adityachoudhari26 adityachoudhari26 commented Mar 31, 2026

Summary by CodeRabbit

  • New Features

    • List workflows: view workflows in a workspace with pagination
    • Trigger workflows: start workflow runs with custom input parameters
    • Verification tracking: richer deployment metadata and release target state monitoring
  • Bug Fixes

    • More consistent workspace lookup and clearer error handling across CLI commands

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Mar 31, 2026

Warning

Rate limit exceeded

@dacbd has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 51 minutes and 16 seconds before requesting another review.

You’ve run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: fb3475e0-8cca-41e2-a9b1-40e5c7feaa5b

📥 Commits

Reviewing files that changed from the base of the PR and between 1568711 and 24743f3.

📒 Files selected for processing (1)
  • internal/api/client.go
📝 Walkthrough

Walkthrough

Adds a new top-level workflow CLI command with list and trigger subcommands; updates the API client models to include DeploymentVersionWithDependencies; and changes GetWorkspaceID to return (uuid, error) with many call sites updated to handle the error.

Changes

Workflow CLI feature

Layer / File(s) Summary
Workflow command factory
cmd/ctrlc/root/workflow/workflow.go, cmd/ctrlc/root/root.go
Adds NewWorkflowCmd() and registers it on the root command (workflow subcommand).
List subcommand
cmd/ctrlc/root/workflow/list.go
Implements workflow list reading url, api-key, workspace from Viper, creates API client, resolves workspace ID, validates --limit/--offset, calls ListWorkflows, and delegates output to cliutil.HandleResponseOutput.
Trigger subcommand
cmd/ctrlc/root/workflow/trigger.go
Implements workflow trigger <workflow-id> reading Viper config, creating API client, resolving workspace ID, parsing repeated --input/-i key=value flags into a map, building CreateWorkflowRun request, calling API, and rendering output.

Workspace ID API change and caller updates

Layer / File(s) Summary
Client API signature and logic
internal/api/client.go
GetWorkspaceID(ctx, workspace) now returns (uuid.UUID, error); for slugs it calls GetWorkspaceBySlugWithResponse, returns wrapped errors on failures, and no longer uses uuid.Nil sentinel.
Call-site updates (commands & services)
cmd/ctrlc/root/api/..., cmd/ctrlc/root/apply/cmd.go, cmd/ctrlc/root/sync/pipe/pipe.go, cmd/ctrlc/root/ui/cmd.go, internal/api/resolver/resolver.go, internal/resources/service.go, pkg/resourceprovider/resourceprovider.go
Multiple CLI commands and internal constructors updated to destructure (workspaceID, err) from GetWorkspaceID(...) and return errors early when workspace lookup fails; removed sentinel UUID checks and adjusted imports/usages accordingly.

API client models update

Layer / File(s) Summary
Deployment version model & response payload
internal/api/client.gen.go
Adds DeploymentVersionWithDependencies struct (includes Dependencies map) and updates ListDeploymentVersionsResponse.JSON200 and the JSON parsing helper to unmarshal items into []DeploymentVersionWithDependencies.

Sequence Diagram(s)

sequenceDiagram
    actor CLI as "CLI (list)"
    participant V as "Viper"
    participant Client as "API Client"
    participant API as "Backend API"
    participant Out as "cliutil.HandleResponseOutput"

    CLI->>V: read url, api-key, workspace
    CLI->>Client: NewAPIKeyClientWithResponses(...)
    CLI->>Client: GetWorkspaceID(ctx, workspace)
    Client->>API: ListWorkflows(workspaceID, params)
    API-->>CLI: workflows response
    CLI->>Out: HandleResponseOutput(response)
Loading
sequenceDiagram
    actor CLI as "CLI (trigger)"
    participant Flags as "Flag parser"
    participant V as "Viper"
    participant Client as "API Client"
    participant API as "Backend API"
    participant Out as "cliutil.HandleResponseOutput"

    CLI->>Flags: parse --input key=value flags
    Flags-->>CLI: validated inputs map
    CLI->>V: read url, api-key, workspace
    CLI->>Client: NewAPIKeyClientWithResponses(...)
    CLI->>Client: GetWorkspaceID(ctx, workspace)
    Client->>API: CreateWorkflowRun(workspaceID, workflowID, body)
    API-->>CLI: run creation response
    CLI->>Out: HandleResponseOutput(response)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Possibly related PRs

  • ctrlplanedev/cli#69 — Similar changes to NewAPIResourceService usage of client.GetWorkspaceID returning (id, err).
  • ctrlplanedev/cli#54 — Related workflow API surface changes used by the new workflow CLI commands.
  • ctrlplanedev/cli#73 — Related edits to deployment-version/dependencies models in internal/api/client.gen.go.

Suggested reviewers

  • jsbroks

Poem

🐰 In burrows of code I nibbled away,
New workflows to list and runs to play,
Workspace IDs now speak with a voice,
Models grew branches, the CLI made its choice,
Hop, click, trigger — a rabbit’s small rejoice!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 15.79% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the primary feature additions: workflow list and trigger commands that form the main focus of this pull request.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch ctrlc-workflow-cmd

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🧹 Nitpick comments (1)
internal/api/client.gen.go (1)

295-312: Confirm the minimum server version for the workflow contract changes.

Lines 295-312 and 1317-1368 now only read/write jobAgents, and Line 14994 only treats 201 as the typed create success. If this CLI can still target pre-migration API deployments, workflow reads will silently drop jobs and create calls will fall off the typed happy path. Please either version-gate these commands or keep dual-format handling in the API/spec until the rollout is complete.

Also applies to: 1068-1073, 1317-1368, 10783-10787, 14993-14999

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

In `@internal/api/client.gen.go` around lines 295 - 312, The generated client now
only serializes/deserializes CreateWorkflow.JobAgents and treats HTTP 201 as the
sole typed create success, which will break compatibility with pre-migration
APIs that use jobs or different success codes; update the client to either check
the server version before using the new schema or implement dual-format
handling: in functions that marshal/unmarshal CreateWorkflow and
CreateWorkflowJobAgent (and any create workflow response handling that currently
assumes 201), add logic to accept both "jobs" and "jobAgents" fields when
reading workflows and to emit both formats (or choose format based on a
negotiated/minimum server version); likewise, adjust the create response parsing
to accept alternative success codes or fall back to untyped handling when the
typed 201 path fails, using the CreateWorkflow and CreateWorkflowJobAgent types
as the primary identifiers to locate relevant code paths.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@cmd/ctrlc/root/workflow/list.go`:
- Line 30: The call to client.GetWorkspaceID(cmd.Context(), workspace) can
return a zero UUID on failure; before calling client.ListWorkflows, check the
returned workspaceID for a zero/empty UUID and return an explicit error (or wrap
with fmt.Errorf) so we fail fast and don't send an invalid ID to ListWorkflows;
update the block around GetWorkspaceID and the subsequent call to ListWorkflows
to validate workspaceID and return early if it is the zero value.
- Around line 33-38: Replace the silent-ignore behavior for negative pagination
flags by validating the limit and offset variables before assigning to params:
check if limit < 0 or offset < 0 and return a CLI validation error (e.g.,
formatted error via fmt.Errorf) instead of falling through; only set
params.Limit and params.Offset when values are non-negative and valid. Update
the code paths around the existing assignments to params.Limit/params.Offset so
invalid inputs cause an early error return from the command handler (or pre-run)
and valid inputs continue to set the pointers as currently done.

In `@cmd/ctrlc/root/workflow/trigger.go`:
- Line 33: The code assigns workspaceID via client.GetWorkspaceID but doesn't
guard against a failed lookup returning a zero UUID; before making the trigger
call, check that workspaceID is not the zero value (compare against uuid.Nil or
the project's zero-UUID constant) and return a clear error (e.g., "workspace not
found" with the original workspace string) if it is zero to avoid calling the
trigger with an invalid identifier; update the function that calls
client.GetWorkspaceID and the subsequent trigger invocation to perform this
validation and short-circuit with an error.
- Around line 37-42: The parsing loop that uses strings.Cut(input, "=")
currently allows an empty key (e.g., "--input =foo"); after extracting key,
value, found in trigger.go validate that found is true and also that key != ""
(non-empty); if key is empty return a descriptive error (e.g., "invalid input
format %q, empty key, expected key=value") instead of assigning into the inputs
map so empty keys are rejected (refer to the variables key, value, found and the
inputs map where the assignment inputs[key] = value occurs).

---

Nitpick comments:
In `@internal/api/client.gen.go`:
- Around line 295-312: The generated client now only serializes/deserializes
CreateWorkflow.JobAgents and treats HTTP 201 as the sole typed create success,
which will break compatibility with pre-migration APIs that use jobs or
different success codes; update the client to either check the server version
before using the new schema or implement dual-format handling: in functions that
marshal/unmarshal CreateWorkflow and CreateWorkflowJobAgent (and any create
workflow response handling that currently assumes 201), add logic to accept both
"jobs" and "jobAgents" fields when reading workflows and to emit both formats
(or choose format based on a negotiated/minimum server version); likewise,
adjust the create response parsing to accept alternative success codes or fall
back to untyped handling when the typed 201 path fails, using the CreateWorkflow
and CreateWorkflowJobAgent types as the primary identifiers to locate relevant
code paths.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: c68df1ae-9981-47c0-8b11-71cebac9d0be

📥 Commits

Reviewing files that changed from the base of the PR and between 20021c3 and fb893b7.

📒 Files selected for processing (5)
  • cmd/ctrlc/root/root.go
  • cmd/ctrlc/root/workflow/list.go
  • cmd/ctrlc/root/workflow/trigger.go
  • cmd/ctrlc/root/workflow/workflow.go
  • internal/api/client.gen.go

Comment thread cmd/ctrlc/root/workflow/list.go Outdated
Comment thread cmd/ctrlc/root/workflow/list.go
Comment thread cmd/ctrlc/root/workflow/trigger.go Outdated
Comment thread cmd/ctrlc/root/workflow/trigger.go
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
internal/api/client.go (1)

36-38: ⚡ Quick win

Improve error message specificity for non-200 responses.

The error message "workspace %q not found" assumes a 404 response, but resp.JSON200 == nil is true for any non-200 status (e.g., 403 Forbidden, 500 Internal Server Error). Consider including the status code or checking for specific response codes to provide more accurate error messages.

💡 Proposed improvement
 if resp.JSON200 == nil {
-  return uuid.Nil, fmt.Errorf("workspace %q not found", workspace)
+  return uuid.Nil, fmt.Errorf("failed to get workspace %q: HTTP %d", workspace, resp.StatusCode())
 }
🤖 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 `@internal/api/client.go` around lines 36 - 38, The error returned when
resp.JSON200 == nil assumes a 404 but can occur for any non-200; update the
handling in the function that checks resp.JSON200 (referencing resp.JSON200 and
the workspace variable) to include the actual HTTP status code and/or more
specific messages: e.g., if the underlying response status is 404 return
"workspace %q not found", for other codes return an error that includes the
status code (and optional response body or status text) so callers see whether
it was 403, 500, etc.
🤖 Prompt for all review comments with 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.

Nitpick comments:
In `@internal/api/client.go`:
- Around line 36-38: The error returned when resp.JSON200 == nil assumes a 404
but can occur for any non-200; update the handling in the function that checks
resp.JSON200 (referencing resp.JSON200 and the workspace variable) to include
the actual HTTP status code and/or more specific messages: e.g., if the
underlying response status is 404 return "workspace %q not found", for other
codes return an error that includes the status code (and optional response body
or status text) so callers see whether it was 403, 500, etc.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: efbe164e-3cf1-427d-a184-db9f9273d2bb

📥 Commits

Reviewing files that changed from the base of the PR and between fb893b7 and 1568711.

📒 Files selected for processing (17)
  • cmd/ctrlc/root/api/get/deployment/deployment.go
  • cmd/ctrlc/root/api/get/release/release.go
  • cmd/ctrlc/root/api/get/releasetargets/releasetargets.go
  • cmd/ctrlc/root/api/get/resources/resources.go
  • cmd/ctrlc/root/api/plan/version/version.go
  • cmd/ctrlc/root/api/upsert/deploymentversion/deployment-version.go
  • cmd/ctrlc/root/apply/cmd.go
  • cmd/ctrlc/root/root.go
  • cmd/ctrlc/root/sync/pipe/pipe.go
  • cmd/ctrlc/root/ui/cmd.go
  • cmd/ctrlc/root/workflow/list.go
  • cmd/ctrlc/root/workflow/trigger.go
  • internal/api/client.gen.go
  • internal/api/client.go
  • internal/api/resolver/resolver.go
  • internal/resources/service.go
  • pkg/resourceprovider/resourceprovider.go
✅ Files skipped from review due to trivial changes (1)
  • internal/api/client.gen.go
🚧 Files skipped from review as they are similar to previous changes (3)
  • cmd/ctrlc/root/root.go
  • cmd/ctrlc/root/workflow/list.go
  • cmd/ctrlc/root/workflow/trigger.go

@dacbd dacbd merged commit aa9175a into main May 14, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants