Conversation
Semver Impact of This PR🟡 Minor (new features) 📋 Changelog PreviewThis is how your changes will appear in the changelog. New Features ✨
Bug Fixes 🐛
🤖 This preview updates automatically when you update the PR. |
Codecov Results 📊✅ 2111 passed | Total: 2111 | Pass Rate: 100% | Execution Time: 0ms 📊 Comparison with Base Branch
All tests are passing successfully. ✅ Patch coverage is 89.43%. Project has 3640 uncovered lines. Files with missing lines (5)
Coverage diff@@ Coverage Diff @@
## main #PR +/-##
==========================================
+ Coverage 76.47% 76.81% +0.34%
==========================================
Files 117 119 +2
Lines 15335 15698 +363
Branches 0 0 —
==========================================
+ Hits 11727 12058 +331
- Misses 3608 3640 +32
- Partials 0 0 —Generated by Codecov Action |
BYK
left a comment
There was a problem hiding this comment.
Love that you both try to infer team and org automatically while supporting org/proj --team <team> syntax too.
See my comments and decide whether you wanna merge as it is or not. My 2 major concerns are the refactor (I may merge that before you see this) and the error when we find more than 1 team.
src/lib/arg-parsing.ts
Outdated
| * parseOrgPrefixedArg("acme/my-app", "Project name", "sentry project create <org>/<name>") | ||
| * // { org: "acme", name: "my-app" } | ||
| */ | ||
| export function parseOrgPrefixedArg( |
There was a problem hiding this comment.
I'm doing a massive refactor which may make this part obsolete.
There was a problem hiding this comment.
finally looked through the current infra after merging main, parseOrgProjectArg and dispatchOrgScopedList are for list/query commands. parseOrgPrefixedArg parses a new resource name, not an existing slug, and resolveTeam handles team auto-selection for write operations.
So i don't think they have an equivalent in your changes, maybe we could consolidate later with more create commands?
| * @returns Team slug to use | ||
| * @throws {ContextError} When team cannot be resolved | ||
| */ | ||
| export async function resolveTeam( |
Add team schema/type and two new API functions needed for project
creation. Also adds TEAM_ENDPOINT_REGEX so /teams/{org}/... endpoints
route to the correct region.
Adds `sentry project create <name> <platform> [--team] [--json]`. Supports org/name syntax (like gh repo create owner/repo), auto-detects org from config/DSN, and auto-selects team when the org has exactly one. Fetches the DSN after creation so users can start sending events immediately. All error paths are actionable — wrong org lists your orgs, wrong team lists available teams, 409 links to the existing project.
When the API returns 400 for an invalid platform string, show the same helpful platform list instead of a raw JSON error body.
Replace the confusing 'Or: - Available platforms:' pattern with a cleaner 'Usage: ... Available platforms:' layout. Applies to both missing platform and invalid platform errors.
- tryGetPrimaryDsn() → api-client.ts (was duplicated in view + create) - resolveTeam() → resolve-team.ts (reusable for future team-dependent commands) - parseOrgPrefixedArg() → arg-parsing.ts (reusable org/name parsing) - writeKeyValue() for aligned key-value output in create.ts - project/view.ts now uses shared tryGetPrimaryDsn instead of local copy
The /teams/{org}/{team}/projects/ endpoint returns 404 for both a bad
org and a bad team. Previously we always blamed the team, which was
misleading when --team was explicit and the org was auto-detected wrong.
Now on 404 we call listTeams(orgSlug) to check:
- If it succeeds → team is wrong, show available teams
- If it fails → org is wrong, show user's actual organizations
Only adds an API call on the error path, never on the happy path.
The view command hint on 409 used the raw name ('My Cool App') instead
of the expected slug ('my-cool-app'), pointing to a non-existent target.
handleCreateProject404 was treating any listTeams failure as proof that the org doesn't exist. Now it checks the status code: only 404 triggers 'Organization not found'. Other failures (403, 5xx, network) get a generic message that doesn't misdiagnose the root cause.
Same class of bug as the previous fix in handleCreateProject404: resolveTeam was routing all ApiErrors from listTeams into the 'org not found' path. Now only 404 triggers that diagnosis. Other failures (403, 5xx) get a generic message that doesn't misdiagnose the cause.
- Extract shared fetchOrgListHint() in resolve-team.ts to deduplicate
org-list fetching logic (used by both resolve-team and create 404 handler)
- Use Writer type instead of inline { write } in writeKeyValue
- Simplify Awaited<ReturnType<typeof listTeams>> to SentryTeam[]
- Add fragility comment to isPlatformError (relies on API message wording)
- Fix test import to use barrel (types/index.js)
When a project slug is already taken, Sentry silently appends a random suffix (e.g., 'test1' becomes 'test1-0g'). This was confusing because the user had no indication why the slug differed from the name. Now shows: Note: Slug 'test1-0g' was assigned because 'test1' is already taken.
Previously, project create errored whenever an org had 2+ teams, requiring --team in every non-trivial org. Now filters teams by isMember and auto-selects when the user belongs to exactly one team. When multiple member teams exist, only those are shown in the error (not all org teams). Falls back to the full list when isMember data is unavailable (self-hosted, old API).
…ists handleCreateProject404 now checks if the teamSlug is actually present in the returned teams list before claiming it's not found. When the team exists (e.g., auto-selected by resolveTeam), the error correctly reports a permission issue instead of the contradictory message.
Add NFKD normalization to handle accented characters and ligatures, and preserve underscores to match Sentry's MIXED_SLUG_PATTERN.
512093d to
1c80d67
Compare
Reuse the more capable parseOrgProjectArg parser instead of the custom parseOrgPrefixedArg, which was the only consumer. This removes duplicated parsing logic and adds URL support for free.
…ions Delete the old orgScopedRequest-based implementations that were left behind after migrating to @sentry/api. These duplicates referenced undefined identifiers (orgScopedRequest, SentryTeamSchema, SentryProjectSchema) and would crash at runtime. Also add the missing TEAM_ENDPOINT_REGEX constant and clean up unused imports.
Move writeKeyValue from project/create.ts to lib/formatters/output.ts so it can be reused across commands. Adopt it in team/view.ts to replace the missing formatTeamDetails with inline human-readable output.
The error hint referenced `sentry org view <org>` for setting a default org, but no such mechanism exists yet. Remove it to avoid confusing users. Tracked in #304.
src/commands/team/view.ts
Outdated
| } | ||
|
|
||
| return null; | ||
| } |
There was a problem hiding this comment.
Duplicate org resolution skips environment variable check
Medium Severity
resolveOrgForTeam reimplements org resolution but skips the SENTRY_ORG environment variable check that the shared resolveOrg function in resolve-target.ts includes. When a user has SENTRY_ORG set (without SENTRY_PROJECT), sentry team view <team> fails to resolve the org while sentry project create works correctly since it uses resolveOrg.
DSN detection is confusing in the project create context since you typically don't have a DSN when creating a new project. Remove DSN mentions from the error hint and description while keeping DSN detection functional as a silent fallback.
The team view command imports getTeam but the function was missing from api-client, causing a runtime TypeError. Add getTeam using the same pattern as getProject, backed by the SDK's retrieveATeam.
Remove team view command and getTeam API function that were accidentally included in this branch. The code imported a non-existent buildTeamUrl, breaking typecheck. This work is preserved on feat/team-view-command. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Re-throw AuthError in handleCreateProject404 so auth errors propagate instead of being swallowed. Guard writeKeyValue against empty pairs to avoid Math.max(...[]) returning -Infinity. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Replace `await` with `return` on `handleCreateProject404` and `buildOrgFailureError` calls so the `never` control flow is explicit and subsequent code is clearly unreachable. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>


Summary
Adds
sentry project create <name> <platform>— the first write command in the CLI. Followsgh repo createconventions with org/name syntax, auto-detection of org and team, and actionable errors at every step.Changes
SentryTeamZod schema and typelistTeams()andcreateProject()API functions with region-aware routing (TEAM_ENDPOINT_REGEX)project createcommand with two required positionals,--team/-tflag, and--jsonoutputTest Plan
bun test test/commands/project/create.test.ts— 19 pass, 0 failbun run typecheck— cleanbun run lint— clean