Skip to content

fix(deploy,api): interactive project picker + detect shell-mangled api paths#35

Merged
facundofarias merged 3 commits into
mainfrom
fix/deploy-picker-and-api-path
Jul 14, 2026
Merged

fix(deploy,api): interactive project picker + detect shell-mangled api paths#35
facundofarias merged 3 commits into
mainfrom
fix/deploy-picker-and-api-path

Conversation

@facundofarias

@facundofarias facundofarias commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

Fixes the two current CLI failure buckets from the last-30-day Mixpanel telemetry review. (The other two buckets — 422/404→internal misclassification and literal undefined error messages — turned out to be stale-client artifacts from v0.16.3 / v0.14.1, already fixed on current versions, so no code change was needed there.)

dhq deploy — "No project specified" (52 events, 47 distinct users)

The largest failure message in the dataset. resolveDeployProject already auto-selects when the account has exactly one project, but multi-project accounts hard-failed with a list even for interactive users.

  • Add a promptui picker for the multi-project case, mirroring the existing server picker in deploy.go.
  • Agents / piped output / --non-interactive keep the structured No project specified error + project list (unchanged), so automation can still retry with --project. The telemetry headline is preserved for bucket continuity.

dhq apiunsupported protocol scheme "c" (Windows / Git-Bash)

MSYS POSIX path conversion rewrites a leading /projects/... into C:/Program Files/Git/projects/... before the CLI sees it, so url.Parse reads c: as a scheme.

  • Detect a drive-letter path (never a valid API path) and return an actionable error pointing to MSYS_NO_PATHCONV=1 or omitting the leading slash.
  • Deliberately does not try to reconstruct the intended endpoint — on a raw escape hatch a wrong guess could fire a destructive call.

Tests

  • New resolveDeployProject non-interactive assertions (multi-project lists candidates; lone project auto-selects; zero projects suggests dhq launch).
  • New TestIsShellMangledPath table test (drive-letter variants flagged; relative/root-absolute paths pass).
  • Verified with the real binary: mangled path → actionable error, exit 1 (now correctly user class); legitimate relative/absolute paths pass through untouched.
  • go test ./..., go vet, golangci-lint all clean.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Bug Fixes

    • Detects API paths rewritten by Git Bash/MSYS and provides clear instructions for retrying the command.
    • Prevents requests from being sent when an API path is invalid due to shell path conversion.
  • New Features

    • Interactive deployments now prompt you to choose a project when multiple projects are available.
    • Non-interactive deployments continue to provide a project list and instructions to specify one explicitly.
    • Deployment cancellation is reported clearly.

…i paths

Two CLI failure buckets surfaced by telemetry (last 30 days):

deploy — "No project specified" (52 events, 47 users): resolveDeployProject
already auto-selects a lone project, but multi-project accounts hard-failed even
for interactive users. Add a promptui picker for the multi-project case, mirroring
the existing server picker. Agents / piped / --non-interactive callers keep the
structured error+list so automation can retry with --project.

api — "unsupported protocol scheme \"c\"" (Windows/Git-Bash): MSYS POSIX path
conversion rewrites a leading "/projects/..." into "C:/Program Files/Git/...".
Detect a drive-letter path (never a valid API path) and return an actionable
error pointing to MSYS_NO_PATHCONV=1 or dropping the leading slash — rather than
guessing the intended endpoint, which on a raw escape hatch could fire a
destructive call.

Note: the other two telemetry buckets (422/404 -> internal misclassification,
literal "undefined" error_message) are stale-client artifacts (v0.16.3 / v0.14.1)
already fixed on current versions; no code change needed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jul 14, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

You’ve reached a temporary PR review limit under our Fair Usage Limits Policy.

Your recent review volume is higher than typical usage, so adaptive limits are currently applied.

Next review available in: 1 minute

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 7610c6b5-a3bb-4d8d-abf8-271b7a8cf60b

📥 Commits

Reviewing files that changed from the base of the PR and between 5497929 and 7760453.

📒 Files selected for processing (3)
  • internal/commands/api.go
  • internal/commands/deploy.go
  • internal/commands/deploy_test.go

Walkthrough

The CLI now rejects Git Bash/MSYS-mangled API paths before making requests. Deploy commands prompt interactive users to choose among multiple projects while retaining structured errors for non-interactive callers.

Changes

CLI behavior updates

Layer / File(s) Summary
API path mangling guard
internal/commands/api.go, internal/commands/api_test.go
Detects Windows drive-letter paths converted by Git Bash/MSYS, returns rerun guidance, and tests valid and false-positive cases.
Interactive deploy project resolution
internal/commands/deploy.go, internal/commands/deploy_test.go
Prompts interactive users to select a project and preserves the project-list error for non-interactive execution.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant CLI
  participant resolveDeployProject
  participant promptui.Select
  CLI->>resolveDeployProject: resolve multiple projects
  resolveDeployProject->>promptui.Select: prompt when interactive
  promptui.Select-->>resolveDeployProject: selected project or cancellation
  resolveDeployProject-->>CLI: project identifier or UserError
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 4
✅ 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 two main changes: interactive deploy project selection and shell-mangled API path detection.
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.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/deploy-picker-and-api-path

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
internal/commands/deploy_test.go (1)

605-608: 📐 Maintainability & Code Quality | 🔵 Trivial | 🏗️ Heavy lift

Cover both sides of the project-resolution split.

This test only exercises the existing non-interactive error path. Add coverage for a non-TTY envelope with NonInteractive: false and a deterministic interactive selection, so regressions in the picker or piped-output behavior are caught.

🤖 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/commands/deploy_test.go` around lines 605 - 608, Add a complementary
test alongside the existing non-interactive multi-project case using a non-TTY
output.Envelope with NonInteractive: false, and configure deterministic picker
input to select a project. Exercise resolveDeployProject and assert the selected
project is returned, while preserving the existing structured-error assertions
for the non-interactive path.
🤖 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.

Inline comments:
In `@internal/commands/api.go`:
- Around line 53-55: Update the recovery command hints in the API error response
to make the path placeholder shell-safe: quote the placeholder or replace it
with a clearly marked concrete example such as "/projects/my-app", while
indicating that users must substitute their actual path. Preserve both recovery
command variants and their existing guidance.

---

Nitpick comments:
In `@internal/commands/deploy_test.go`:
- Around line 605-608: Add a complementary test alongside the existing
non-interactive multi-project case using a non-TTY output.Envelope with
NonInteractive: false, and configure deterministic picker input to select a
project. Exercise resolveDeployProject and assert the selected project is
returned, while preserving the existing structured-error assertions for the
non-interactive path.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 1f157b73-fb93-404d-bf82-aa1beb09aff9

📥 Commits

Reviewing files that changed from the base of the PR and between 8d7a17f and 5497929.

📒 Files selected for processing (4)
  • internal/commands/api.go
  • internal/commands/api_test.go
  • internal/commands/deploy.go
  • internal/commands/deploy_test.go

Comment thread internal/commands/api.go Outdated
facundofarias and others added 2 commits July 14, 2026 11:26
Review-council finding (Codex, verified): the project and server pickers
gated only on !env.NonInteractive, but --json on a TTY leaves NonInteractive
false. promptui writes terminal control sequences to os.Stdout
(select.go:558), so `dhq deploy --json` in a terminal would interleave
non-JSON bytes into stdout, breaking the stdout=data contract.

Gate both pickers on `!env.NonInteractive && !env.WantsJSON()` so JSON mode
takes the structured-error path (itself valid JSON). Also closes the same
pre-existing gap in the server picker.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
CodeRabbit review: the recovery hint printed literal "<path>" placeholders,
which Bash parses as input redirection (from a file named "path") if a user
copies the command. Use concrete examples ("/projects/my-app") in both
recovery lines instead.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@facundofarias
facundofarias merged commit 6ae80e2 into main Jul 14, 2026
10 checks passed
@facundofarias
facundofarias deleted the fix/deploy-picker-and-api-path branch July 14, 2026 09:33
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.

1 participant