Skip to content

fix(init): add --app flag and actionable errors for non-interactive monorepo runs#977

Merged
betegon merged 7 commits into
mainfrom
fix/init-monorepo-app-selection
May 19, 2026
Merged

fix(init): add --app flag and actionable errors for non-interactive monorepo runs#977
betegon merged 7 commits into
mainfrom
fix/init-monorepo-app-selection

Conversation

@betegon
Copy link
Copy Markdown
Member

@betegon betegon commented May 18, 2026

Running sentry init --yes --features errors against a monorepo would hit the select-target-app step, fail to resolve an app non-interactively, and send { cancelled: true } as resume data to the server. The server validated it against a schema requiring selectedApp and returned HTTP 500. Users saw:

WizardError: HTTP error! status: 500 - {"error":"Invalid resume data: \n- selectedApp: Required"}

Three root causes fixed here:

1. No non-interactive escape hatch. Added --app <name> flag so CI/agent runs can specify which monorepo app to initialize. Case-insensitive match against the server-provided app list.

2. handleSelect returned instead of throwing. When --yes was set with multiple apps, it returned { cancelled: true } which got forwarded to the server as resume data. It now throws with a formatted app list and the exact re-run command:

This monorepo has 3 apps. Use --app to specify which one to initialize:

  sentry init --yes --features <features> --app web

Available apps:
  web    (Next.js)   /repo/apps/web
  api    (Express)   /repo/apps/api
  admin  (React)     /repo/packages/admin

Or run without --yes to pick interactively:
  sentry init

3. Safety net. Added a guard in handleSuspendedStep that throws before any { cancelled: true } result can reach resumeWithRetry, so a future regression fails on the CLI side rather than producing an opaque server error.

Also fixed the default branch in handleInteractive (same { cancelled: true } bug for unknown prompt kinds) and rewrote formatAppList to iterate over items rather than apps so the list stays correct if payload.options and payload.apps ever arrive at different lengths.

Closes CLI-17A (77 events, all is_tty: False + flag.yes: True).

betegon and others added 2 commits May 18, 2026 22:33
…onorepo runs

When running `sentry init --yes --features errors` against a monorepo,
the wizard suspended for app selection, received `{ cancelled: true }` as
resume data, and the server returned a bare HTTP 500 because `selectedApp`
was required. The root causes:

- No flag existed to pre-select an app in non-interactive mode
- handleSelect returned { cancelled: true } instead of throwing, so
  malformed resume data reached the server
- The one-liner error didn't name the available apps or show a fix

This adds --app to allow non-interactive app selection and rewrites
handleSelect to throw with a formatted list of apps and the exact
re-run command. The default branch in handleInteractive also now throws
instead of returning the sentinel. A guard in handleSuspendedStep
catches any future { cancelled: true } return before it reaches the
server.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
@betegon betegon marked this pull request as ready for review May 18, 2026 20:34
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 18, 2026

PR Preview Action v1.8.1

QR code for preview link

🚀 View preview at
https://cli.sentry.dev/_preview/pr-977/

Built to branch gh-pages at 2026-05-19 09:39 UTC.
Preview will be ready when the GitHub Pages deployment is complete.

Three tests expected { cancelled: true } return values that the
refactored handlers now throw as WizardError instead.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 19, 2026

Codecov Results 📊

6986 passed | Total: 6986 | Pass Rate: 100% | Execution Time: 0ms

📊 Comparison with Base Branch

Metric Change
Total Tests 📈 +6
Passed Tests 📈 +6
Failed Tests
Skipped Tests

All tests are passing successfully.

✅ Patch coverage is 85.39%. Project has 14236 uncovered lines.
❌ Project coverage is 76.99%. Comparing base (base) to head (head).

Files with missing lines (2)
File Patch % Lines
src/lib/init/wizard-runner.ts 18.18% ⚠️ 9 Missing
src/lib/init/interactive.ts 94.20% ⚠️ 4 Missing
Coverage diff
@@            Coverage Diff             @@
##          main       #PR       +/-##
==========================================
- Coverage    77.15%    76.99%    -0.16%
==========================================
  Files          320       320         —
  Lines        61662     61873      +211
  Branches         0         0         —
==========================================
+ Hits         47572     47637       +65
- Misses       14090     14236      +146
- Partials         0         0         —

Generated by Codecov Action

Comment thread src/lib/init/interactive.ts Outdated
Three follow-ups for #977:

- Guard the --app matching branch on payload.apps being present and
  non-empty, so the flag only activates for the monorepo app-selection
  prompt and is silently ignored on any other select-kind payload
- Fix import sort order in interactive.test.ts (WizardError before
  handleInteractive) to satisfy Biome's organizeImports rule
- Add five tests covering the --app happy path, case-insensitive
  matching, not-found error content, non-monorepo passthrough, and
  multi-app error message content — brings interactive.ts to 100%
  function coverage and 99% line coverage

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Comment thread src/lib/init/interactive.ts Outdated
The if (options.yes) block that throws the "This monorepo has N apps"
error was missing the same payload.apps guard added for --app in the
previous commit. A non-monorepo select prompt with multiple options
and --yes set would hit this path and show a completely wrong error
suggesting the user is in a monorepo and needs --app.

Guard is now: options.yes && payload.apps && payload.apps.length > 0,
symmetric with the --app guard above it. Without apps present the
block is skipped and falls through to ui.select() as expected.

Updates existing test to include payload.apps so it still covers the
monorepo error path. Adds a new test confirming --yes with a plain
options-only select falls through without error.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 2445a17. Configure here.

Comment thread src/lib/init/interactive.ts
"No apps found in this monorepo." was wrong when payload.apps is
absent and the empty options list came from a non-monorepo select
prompt. Message is now context-neutral.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Comment thread src/lib/init/interactive.ts
…omment

The interactive app picker built select options with apps[i] (index-based)
while formatAppList already used apps.find(a => a.name === item) after the
alignment fix. Consistent name-based lookup throughout so framework hints
stay correct regardless of whether payload.options and payload.apps have
the same ordering or length.

Also trims the formatAppList comment to the why, dropping the redundant
"how" sentence.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
@betegon betegon merged commit 6794330 into main May 19, 2026
30 checks passed
@betegon betegon deleted the fix/init-monorepo-app-selection branch May 19, 2026 09:49
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