Conversation
Semver Impact of This PR🟡 Minor (new features) 📋 Changelog PreviewThis is how your changes will appear in the changelog. New Features ✨
Bug Fixes 🐛
Internal Changes 🔧
🤖 This preview updates automatically when you update the PR. |
Codecov Results 📊✅ 116 passed | Total: 116 | Pass Rate: 100% | Execution Time: 0ms 📊 Comparison with Base Branch
All tests are passing successfully. ✅ Patch coverage is 92.82%. Project has 1122 uncovered lines. Files with missing lines (4)
Coverage diff@@ Coverage Diff @@
## main #PR +/-##
==========================================
- Coverage 95.25% 95.23% -0.02%
==========================================
Files 174 175 +1
Lines 23342 23537 +195
Branches 0 0 —
==========================================
+ Hits 22234 22415 +181
- Misses 1108 1122 +14
- Partials 0 0 —Generated by Codecov Action |
| const SCOPES = [ | ||
| "project:read", | ||
| "project:write", | ||
| "project:admin", |
There was a problem hiding this comment.
what would happen if someone doesn't have this permission? would it face trouble signing in?
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Autofix Details
Bugbot Autofix prepared a fix for the issue found in the latest run.
- ✅ Fixed: New OAuth scope may break login for non-admin users
- Removed project:admin from global OAuth SCOPES to prevent potentially breaking authentication for non-admin users, and updated the delete command's 403 error to direct users to contact their org admin instead.
Or push these changes by commenting:
@cursor push 3eb69e6f5d
Preview (3eb69e6f5d)
diff --git a/src/commands/project/delete.ts b/src/commands/project/delete.ts
--- a/src/commands/project/delete.ts
+++ b/src/commands/project/delete.ts
@@ -176,8 +176,8 @@
if (error instanceof ApiError && error.status === 403) {
throw new ApiError(
`Permission denied: You don't have permission to delete '${orgSlug}/${project.slug}'.\n\n` +
- "Project deletion requires the 'project:admin' scope.\n" +
- " Re-authenticate: sentry auth login",
+ "Project deletion requires the 'project:admin' permission.\n" +
+ "Contact your organization admin to grant you project admin access.",
403,
error.detail,
error.endpoint
diff --git a/src/lib/oauth.ts b/src/lib/oauth.ts
--- a/src/lib/oauth.ts
+++ b/src/lib/oauth.ts
@@ -52,7 +52,6 @@
const SCOPES = [
"project:read",
"project:write",
- "project:admin",
"org:read",
"event:read",
"event:write",
diff --git a/test/commands/project/delete.test.ts b/test/commands/project/delete.test.ts
--- a/test/commands/project/delete.test.ts
+++ b/test/commands/project/delete.test.ts
@@ -185,7 +185,7 @@
const apiErr = error as ApiError;
expect(apiErr.status).toBe(403);
expect(apiErr.message).toContain("project:admin");
- expect(apiErr.message).toContain("sentry auth login");
+ expect(apiErr.message).toContain("organization admin");
}
});This Bugbot Autofix run was free. To enable autofix for future PRs, go to the Cursor dashboard.
| Delete a project | ||
|
|
||
| **Flags:** | ||
| - `-y, --yes - Skip confirmation prompt` |
There was a problem hiding this comment.
We should also accept -f/--force flag
src/commands/project/delete.ts
Outdated
| const confirmed = await log.prompt( | ||
| `Delete project '${project.name}' (${orgSlug}/${project.slug})? This cannot be undone.`, | ||
| { type: "confirm", initial: false } | ||
| ); | ||
|
|
||
| // consola prompt returns Symbol(clack:cancel) on Ctrl+C — a truthy value. | ||
| // Strictly check for `true` to avoid deleting on cancel. | ||
| return confirmed === true; |
There was a problem hiding this comment.
Let's follow the classical safety measure and ask the user to type out org/project like deletions on GitHub UI and other places?
|
|
||
| let orgRole: string | undefined; | ||
| try { | ||
| const org = await getOrganization(orgSlug); |
There was a problem hiding this comment.
If there's a cached version of that, let's make sure to use that
src/commands/project/delete.ts
Outdated
| "Your auth token may be missing the 'project:admin' scope.\n" + | ||
| " Re-authenticate: sentry auth login", |
There was a problem hiding this comment.
How would this grant that permission? This can only be the case when they are using a custom oauth token so sentry auth login would not help here.
src/commands/project/delete.ts
Outdated
| return new ApiError( | ||
| `Permission denied: You don't have permission to delete ${label}.\n\n` + | ||
| `This requires ${rolesWithAccess} role, or a token with the 'project:admin' scope.\n` + | ||
| ` Check your role: sentry org view ${orgSlug}\n` + |
There was a problem hiding this comment.
Does this command really show the user's role in the org? If not let's make that the case
src/commands/project/delete.ts
Outdated
| `Permission denied: You don't have permission to delete ${label}.\n\n` + | ||
| `This requires ${rolesWithAccess} role, or a token with the 'project:admin' scope.\n` + | ||
| ` Check your role: sentry org view ${orgSlug}\n` + | ||
| " Re-authenticate: sentry auth login", |
There was a problem hiding this comment.
Reauth using sentry auth login will not resolve any permission issues at all. This could only help when using a custom OAuth token which then they need to regenerate or expand the scope of.
src/commands/project/delete.ts
Outdated
| " sentry project delete acme-corp/my-app --dry-run", | ||
| }, | ||
| output: { | ||
| json: true, |
Add `sentry project delete` subcommand for permanently deleting Sentry projects via the API. Safety measures: - No auto-detect mode — requires explicit org/project target - Type-out confirmation (user types `org/project` like GitHub) - --yes/-y and --force/-f flags to skip confirmation (for CI/agents) - --dry-run/-n to validate without deleting - Non-interactive TTY guard (refuses without --yes/--force) - Role-aware 403 error messages (never suggests reauth) - Verifies project exists before prompting Also adds: - `project:admin` to OAuth SCOPES (required for deletion API) - `orgRole` display in `sentry org view` output - `deleteProject()` in API layer Addresses all review comments from PR #397: 1. Accept -f/--force alongside --yes 2. Type-out org/project confirmation instead of yes/no 3. Note about cached org data (no cache exists yet) 4. Fix misleading 403 token scope messages 5. Show user role in org view 6. Remove sentry auth login suggestions from 403 errors 7. Remove obsolete json: true from output config Co-authored-by: MathurAditya724 <AditMathur16@gmail.com>
658fcd5 to
a4e5715
Compare
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Bugbot Autofix prepared a fix for the issue found in the latest run.
- ✅ Fixed: Redundant
--yesand--forceflags with identical behavior- Removed the redundant --force flag and consolidated to a single --yes flag while keeping both -y and -f as short aliases for backward compatibility.
Or push these changes by commenting:
@cursor push f335ba1cf4
Preview (f335ba1cf4)
diff --git a/plugins/sentry-cli/skills/sentry-cli/SKILL.md b/plugins/sentry-cli/skills/sentry-cli/SKILL.md
--- a/plugins/sentry-cli/skills/sentry-cli/SKILL.md
+++ b/plugins/sentry-cli/skills/sentry-cli/SKILL.md
@@ -186,7 +186,6 @@
**Flags:**
- `-y, --yes - Skip confirmation prompt`
-- `-f, --force - Force deletion without confirmation`
- `-n, --dry-run - Validate and show what would be deleted without deleting`
- `--json - Output as JSON`
- `--fields <value> - Comma-separated fields to include in JSON output (dot.notation supported)`
diff --git a/src/commands/project/delete.ts b/src/commands/project/delete.ts
--- a/src/commands/project/delete.ts
+++ b/src/commands/project/delete.ts
@@ -64,7 +64,7 @@
if (!isatty(0)) {
throw new CliError(
`Refusing to delete '${expected}' in non-interactive mode. ` +
- "Use --yes or --force to confirm."
+ "Use --yes to confirm."
);
}
@@ -154,7 +154,6 @@
type DeleteFlags = {
readonly yes: boolean;
- readonly force: boolean;
readonly "dry-run": boolean;
readonly json: boolean;
readonly fields?: string[];
@@ -170,7 +169,6 @@
" sentry project delete acme-corp/my-app\n" +
" sentry project delete my-app\n" +
" sentry project delete acme-corp/my-app --yes\n" +
- " sentry project delete acme-corp/my-app --force\n" +
" sentry project delete acme-corp/my-app --dry-run",
},
output: {
@@ -209,18 +207,13 @@
brief: "Skip confirmation prompt",
default: false,
},
- force: {
- kind: "boolean",
- brief: "Force deletion without confirmation",
- default: false,
- },
"dry-run": {
kind: "boolean",
brief: "Validate and show what would be deleted without deleting",
default: false,
},
},
- aliases: { y: "yes", f: "force", n: "dry-run" },
+ aliases: { y: "yes", f: "yes", n: "dry-run" },
},
async *func(this: SentryContext, flags: DeleteFlags, target: string) {
const { cwd } = this;
@@ -250,7 +243,7 @@
}
// Confirmation gate
- if (!(flags.yes || flags.force)) {
+ if (!flags.yes) {
const confirmed = await confirmDeletion(orgSlug, project);
if (!confirmed) {
log.info("Cancelled.");This Bugbot Autofix run was free. To enable autofix for future PRs, go to the Cursor dashboard.
| kind: "boolean", | ||
| brief: "Force deletion without confirmation", | ||
| default: false, | ||
| }, |
There was a problem hiding this comment.
Redundant --yes and --force flags with identical behavior
Low Severity
Both --yes and --force flags do exactly the same thing: skip the confirmation prompt. The confirmation gate at if (!(flags.yes || flags.force)) treats them as fully interchangeable, yet they're documented with different descriptions ("Skip confirmation prompt" vs "Force deletion without confirmation") and registered as separate flags. A PR reviewer noted one is "no longer needed (the default)". Having two flags with distinct names but identical runtime behavior adds confusion for users and maintenance overhead.



Summary
Add
sentry project deletesubcommand for permanently deleting Sentry projects via the API.Changes
src/commands/project/delete.ts— New command with safety measures:<org>/<project>or<project>target (no auto-detect)confirmed !== truecheck for Symbol(clack:cancel) gotcha)--yes/-yflag to skip confirmation for CI/agent usage--dry-run/-nflag to validate inputs and show what would be deleted without deleting--yesgetProject()before promptingApiErrorwith actionable message (preserves HTTP status for upstream handlers)src/commands/project/index.ts— Registereddeletein project route mapsrc/lib/api-client.ts— AddeddeleteProject()using@sentry/apiSDK'sdeleteAProjectsrc/lib/oauth.ts— Addedproject:adminto OAuth scopes (required for project deletion; existing users must re-runsentry auth login)test/commands/project/delete.test.ts— 10 unit tests covering happy path, error cases, dry-run, JSON output, and safety checksUsage
Notes
project:admin— users need to re-authenticate viasentry auth loginafter upgrading