Skip to content

feat(init): resolve projects and improve existing setups - #1374

Draft
betegon wants to merge 1 commit into
mainfrom
refactor/shared-project-create-resolver
Draft

feat(init): resolve projects and improve existing setups#1374
betegon wants to merge 1 commit into
mainfrom
refactor/shared-project-create-resolver

Conversation

@betegon

@betegon betegon commented Aug 6, 2026

Copy link
Copy Markdown
Member

Summary

  • make sentry init resolve the organization early, then resolve the project from the concrete selected application instead of the monorepo root
  • reuse an existing project only for an unambiguous canonical repository match; otherwise keep create-new as the default path
  • share project and team creation policy between sentry init and sentry project create, including complete team pagination, Team Admin choices, personal-team creation, and accurate organization-policy errors
  • surface detected installations as an explicit improve-existing flow while preserving the separate use-or-create-another-project path
  • carry detected features into the richer feature selector and keep the existing DSN expression and setup structure intact
  • improve monorepo target labels and roles using repository name, workspace manifests, framework/deployment configuration, and package structure
  • keep create-new-team visible above the team list, open the Files view at the top, and remove transient setup-analysis chrome between selections

OAuth support

Merged PR #1373 adds team:admin to the standard OAuth scope set and supports one bounded refresh for older eligible interactive grants. Unattended, JSON, dry-run, and environment-token execution do not start OAuth.

Validation

  • pnpm --filter sentry typecheck
  • 144 focused tests covering project creation, team resolution, init preflight, and the init project tool
  • 44 Ink UI tests under CI=1, including repeated transition coverage
  • scoped Biome checks and git diff --check
  • the previous rebased revision passed the complete GitHub unit, lint/typecheck, E2E, binary, package, and security workflows

Closes #1375.

Terminal-height overflow remains separate in #1376.

@betegon
betegon force-pushed the refactor/shared-project-create-resolver branch from 41c51ff to 3263729 Compare August 7, 2026 08:12
@betegon betegon changed the title fix(project): share project creation resolver fix(init): default to project creation and infer teams Aug 7, 2026
@betegon
betegon force-pushed the refactor/shared-project-create-resolver branch from 3263729 to 2458762 Compare August 7, 2026 10:36
@betegon
betegon marked this pull request as ready for review August 7, 2026 11:12
Comment thread packages/cli/src/lib/init/preflight.ts Outdated
Comment thread packages/cli/src/lib/init/preflight.ts
@betegon
betegon force-pushed the refactor/shared-project-create-resolver branch from 2458762 to 504e0cb Compare August 7, 2026 12:18
@betegon betegon changed the title fix(init): default to project creation and infer teams fix(init): default to creation and share team resolution Aug 7, 2026
@betegon
betegon marked this pull request as draft August 7, 2026 12:18
Comment thread packages/cli/src/lib/project-creation.ts Outdated
Comment thread packages/cli/src/lib/resolve-target.ts
Comment thread packages/cli/src/lib/init/preflight.ts
@betegon
betegon force-pushed the refactor/shared-project-create-resolver branch from 504e0cb to a794d55 Compare August 7, 2026 13:26
@vercel

vercel Bot commented Aug 21, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
cli Ready Ready Preview Sep 11, 2026 12:07pm UTC
1 Skipped Deployment
Project Deployment Actions Updated
sentry-local Skipped Skipped Sep 11, 2026 12:07pm UTC

Request Review

@betegon betegon changed the title fix(init): default to creation and share team resolution feat(init): resolve projects and improve existing setups Aug 21, 2026
@betegon
betegon marked this pull request as ready for review August 22, 2026 12:55
Comment thread packages/cli/src/lib/init/preflight.ts
Comment thread packages/cli/src/lib/init/preflight.ts
Comment thread packages/cli/src/lib/init/preflight.ts

@cursor cursor Bot left a comment

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.

Stale Bugbot comment from a previous run.

Comment thread packages/cli/src/lib/project-creation.ts
Comment thread packages/cli/src/lib/init/ui/ink-ui.ts
Comment thread packages/cli/src/lib/init/wizard-runner.ts

@cursor cursor Bot left a comment

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.

Stale Bugbot comment from a previous run.

(item) => item.kind === "config" && item.sdkConfig
);
const installed =
runtimeInitialization.length > 0 || hasSdkConfig || Boolean(dsn);

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.

Per-app DSN scan escapes the target

High Severity

detectSentrySetup treats the first repo-wide DSN as proof that the selected target is installed. detectAllDsnOccurrences walks to findProjectRoot and scans that tree, so a sibling app's DSN can mark this package installed and send init into the improve/reuse path for the wrong project.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 9648c5d. Configure here.

) {
return;
}
return { selectedApp: items[0] };

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.

Unattended single-target setup is rejected

Medium Severity

When --yes sees exactly one target whose sentrySetup is detected, autoSelectTarget returns nothing and handleSelect throws the multi-target “use --app” error. Unattended init then fails on a single app instead of selecting it and continuing through the existing-setup path.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 9648c5d. Configure here.

} catch (fallbackError) {
if (isMemberCreationDisabled403(fallbackError)) {
throw buildTeamAdminAuthorizationError(orgSlug, team.slug);
}

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.

Org policy error becomes scope error

Medium Severity

If an auto-selected team create fails and the org-scoped fallback returns member-project-creation disabled, that policy 403 is rewritten as a missing team:admin authorization error. Users get the wrong recovery path, including a useless OAuth refresh.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 9648c5d. Configure here.

return explicit;
}
assertImprovementSupported(setup, options);
return markExistingSetupForImprovement(explicit, setup);

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.

Explicit setup cannot fall back safely

Medium Severity

An explicit project that matches the local setup always calls assertImprovementSupported. If the setup service is old or the health check did not advertise improve-existing-setup, init throws instead of offering another project the way the implicit detected-setup path does.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 9648c5d. Configure here.

@betegon
betegon force-pushed the refactor/shared-project-create-resolver branch from 9648c5d to 0e98f09 Compare September 11, 2026 11:28

@cursor cursor Bot left a comment

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.

Stale Bugbot comment from a previous run.

opts.existingProject.projectSlug === slug
? opts.existingProject
: await tryGetExistingProjectData(opts.org, slug).catch(() => null);
const existingProject = await tryGetExistingProjectData(opts.org, slug);

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.

Project lookup errors abort init

Medium Severity

resolveExistingProjectChoice and findAvailableProjectSlug now call tryGetExistingProjectData without handling non-404 failures. A 403 or 5xx during existence checks fails the whole wizard instead of treating the lookup as “not reusable” or “name taken.”

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 0e98f09. Configure here.

@betegon
betegon force-pushed the refactor/shared-project-create-resolver branch from 0e98f09 to 8282394 Compare September 11, 2026 11:46
@vercel
vercel Bot temporarily deployed to Preview – sentry-local September 11, 2026 11:46 Inactive
@betegon
betegon marked this pull request as draft September 11, 2026 11:46
Comment on lines +229 to +235
const shown = eligibleTeams.slice(0, 10);
const remaining = eligibleTeams.length - shown.length;
throw new ContextError("Team", `${options.usageHint} --team <team-slug>`, [
`You are a Team Admin of ${eligibleTeams.length} teams in '${orgSlug}'. Choose one explicitly with --team.`,
...shown.map((team) => `Available: ${team.slug}`),
...(remaining > 0 ? [`...and ${remaining} more`] : []),
]);

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.

Bug: In non-interactive mode, resolveEligibleTeam throws an error if multiple eligible teams exist, instead of falling back to the intended new-project-creation flow.
Severity: HIGH

Suggested Fix

Modify resolveEligibleTeam to return { kind: "create" } instead of throwing an error when it encounters multiple eligible teams and no chooseTeam callback is provided. This will allow the control flow in resolveOrCreateTeam to correctly fall back to resolveNewTeam as intended in non-interactive scenarios.

Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent. Verify if this is a real issue. If it is, propose a fix; if not, explain why it's
not valid.

Location: packages/cli/src/lib/resolve-team.ts#L229-L235

Potential issue: When running a command in non-interactive mode, such as `sentry init
--yes`, the `resolveOrCreateTeam` function is called. If the user is an admin of
multiple teams, the `resolveEligibleTeam` function throws a `ContextError`, requiring
the user to specify a `--team` flag. This prevents the intended fallback behavior, which
is to proceed to `resolveNewTeam` to create a new project. The current implementation
contradicts the expected behavior of defaulting to new project creation when an
unambiguous choice cannot be made in a non-interactive session.

@cursor cursor Bot left a comment

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.

Cursor Bugbot has reviewed your changes and found 2 potential issues.

There are 7 total unresolved issues (including 5 from previous reviews).

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 8282394. Configure here.

...envResult.dsns,
...(envDsn ? [envDsn] : []),
];
}

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.

Per-app DSN scan escapes target

High Severity

detectSentrySetup treats the first repo-wide DSN as proof the selected target is already installed. detectAllDsnOccurrences walks to the git root and scans the whole tree, so a sibling package DSN can mark an uninitialized app as installed and send init into the improve-existing flow for the wrong project.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 8282394. Configure here.

throw new WizardCancelledError();
}
if (choice === "create") {
return { project: undefined };

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.

Failed health check blocks existing setups

Medium Severity

A failed or timed-out readiness check still starts the wizard but reports improveExistingSetup: false. --yes and matching explicit-project runs then hit assertImprovementSupported and abort, even though readiness itself only warned that the service might retry.

Additional Locations (2)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 8282394. Configure here.

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.

Make CLI project team optional with default

2 participants