From 7bbb133e60f209c7ac86baed2395775eeee9e59d Mon Sep 17 00:00:00 2001 From: betegon Date: Mon, 5 Oct 2026 21:34:34 +0200 Subject: [PATCH 1/4] fix(cli): honor configured organizations for short IDs Resolve full short IDs in the configured organization and refresh incomplete cached organization inventories once on a miss. Co-Authored-By: GPT-6 --- apps/cli-docs/src/fragments/commands/issue.md | 13 + apps/cli-docs/src/fragments/configuration.md | 5 + .../sentry-cli/skills/sentry-cli/SKILL.md | 2 +- .../references/agent-conversation.md | 2 +- .../skills/sentry-cli/references/alert.md | 2 +- .../skills/sentry-cli/references/api.md | 2 +- .../skills/sentry-cli/references/auth.md | 2 +- .../skills/sentry-cli/references/build.md | 2 +- .../skills/sentry-cli/references/cli.md | 2 +- .../sentry-cli/references/code-mappings.md | 2 +- .../sentry-cli/references/dart-symbol-map.md | 2 +- .../skills/sentry-cli/references/dashboard.md | 2 +- .../sentry-cli/references/debug-files.md | 2 +- .../skills/sentry-cli/references/docs.md | 2 +- .../skills/sentry-cli/references/dsn.md | 2 +- .../skills/sentry-cli/references/event.md | 2 +- .../skills/sentry-cli/references/explore.md | 2 +- .../skills/sentry-cli/references/feedback.md | 2 +- .../skills/sentry-cli/references/info.md | 2 +- .../skills/sentry-cli/references/init.md | 2 +- .../skills/sentry-cli/references/issue.md | 4 +- .../skills/sentry-cli/references/local.md | 2 +- .../skills/sentry-cli/references/log.md | 2 +- .../skills/sentry-cli/references/monitor.md | 2 +- .../skills/sentry-cli/references/org.md | 2 +- .../skills/sentry-cli/references/platform.md | 2 +- .../skills/sentry-cli/references/proguard.md | 2 +- .../skills/sentry-cli/references/project.md | 2 +- .../sentry-cli/references/react-native.md | 2 +- .../skills/sentry-cli/references/release.md | 2 +- .../skills/sentry-cli/references/replay.md | 2 +- .../skills/sentry-cli/references/repo.md | 2 +- .../skills/sentry-cli/references/schema.md | 2 +- .../skills/sentry-cli/references/snapshots.md | 2 +- .../skills/sentry-cli/references/sourcemap.md | 2 +- .../skills/sentry-cli/references/span.md | 2 +- .../skills/sentry-cli/references/status.md | 2 +- .../skills/sentry-cli/references/team.md | 2 +- .../skills/sentry-cli/references/trace.md | 2 +- .../skills/sentry-cli/references/trial.md | 2 +- .../sentry-cli/references/wasm-split.md | 2 +- packages/cli/src/commands/feedback/view.ts | 4 +- packages/cli/src/commands/issue/explain.ts | 4 +- packages/cli/src/commands/issue/plan.ts | 4 +- packages/cli/src/commands/issue/utils.ts | 119 ++++++--- packages/cli/src/commands/issue/view.ts | 4 +- packages/cli/src/lib/api/organizations.ts | 12 +- packages/cli/src/lib/resolve-target.ts | 33 +-- packages/cli/src/lib/sentry-client.ts | 18 +- .../issue/short-id-resolution.test.ts | 244 ++++++++++++++++++ .../cli/test/lib/api/organizations.test.ts | 60 ++++- 51 files changed, 488 insertions(+), 112 deletions(-) create mode 100644 packages/cli/test/commands/issue/short-id-resolution.test.ts diff --git a/apps/cli-docs/src/fragments/commands/issue.md b/apps/cli-docs/src/fragments/commands/issue.md index 9cff62d1c..3b27c6f10 100644 --- a/apps/cli-docs/src/fragments/commands/issue.md +++ b/apps/cli-docs/src/fragments/commands/issue.md @@ -108,6 +108,19 @@ sentry issue view FRONT-ABC sentry issue view FRONT-ABC BACK-2 ``` +Full short IDs such as `FRONT-ABC` use your configured organization: `SENTRY_ORG`, +then `.sentryclirc`, then the default set with `sentry cli defaults org`. The lookup +stays within that organization. To select another organization, include it explicitly: + +```bash +sentry issue view my-org/FRONT-ABC +``` + +Project aliases such as `f-abc` keep the organization associated with the alias. +Without a configured organization, the CLI uses a matching detected project or +searches your accessible organizations. If the short ID matches in multiple +organizations, specify the organization explicitly. + ``` Issue: TypeError: Cannot read property 'foo' of undefined Short ID: FRONT-ABC diff --git a/apps/cli-docs/src/fragments/configuration.md b/apps/cli-docs/src/fragments/configuration.md index b9673a933..4a4c51840 100644 --- a/apps/cli-docs/src/fragments/configuration.md +++ b/apps/cli-docs/src/fragments/configuration.md @@ -55,6 +55,11 @@ When the CLI needs to determine your org and project, it checks these sources in The first source that provides both org and project wins. For org-only commands, only the org is needed. +Full issue short IDs, such as `sentry issue view FRONT-ABC`, only need the org: +`SENTRY_ORG`, `.sentryclirc`, and persistent defaults scope the lookup in that order. +Use `sentry issue view other-org/FRONT-ABC` to override the configured organization. +Project aliases retain their associated organization. See [View an issue](./commands/issue/#view-an-issue). + ### Backward Compatibility If you previously used the legacy `sentry-cli` and have a `~/.sentryclirc` file, the new CLI reads it automatically. The `[defaults]` and `[auth]` sections are fully compatible. The `[auth] token` value is mapped to the `SENTRY_AUTH_TOKEN` environment variable internally (only if the env var is not already set). diff --git a/packages/cli/plugins/sentry-cli/skills/sentry-cli/SKILL.md b/packages/cli/plugins/sentry-cli/skills/sentry-cli/SKILL.md index 771c666c2..7a3a17757 100644 --- a/packages/cli/plugins/sentry-cli/skills/sentry-cli/SKILL.md +++ b/packages/cli/plugins/sentry-cli/skills/sentry-cli/SKILL.md @@ -1,6 +1,6 @@ --- name: sentry-cli -version: 0.47.0-dev.0 +version: 0.48.0-dev.0 description: Guide for using the Sentry CLI to interact with Sentry from the command line. Use when the user asks about viewing issues, events, projects, organizations, making API calls, or authenticating with Sentry via CLI. requires: bins: ["sentry"] diff --git a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/agent-conversation.md b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/agent-conversation.md index ca7e7bb2a..0ba3bdab8 100644 --- a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/agent-conversation.md +++ b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/agent-conversation.md @@ -1,6 +1,6 @@ --- name: sentry-cli-agent-conversation -version: 0.47.0-dev.0 +version: 0.48.0-dev.0 description: List and view agent conversations requires: bins: ["sentry"] diff --git a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/alert.md b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/alert.md index 7ce0e7ef7..e742f6276 100644 --- a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/alert.md +++ b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/alert.md @@ -1,6 +1,6 @@ --- name: sentry-cli-alert -version: 0.47.0-dev.0 +version: 0.48.0-dev.0 description: Manage Sentry alert rules requires: bins: ["sentry"] diff --git a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/api.md b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/api.md index 9cee33e99..6fe3ff6e3 100644 --- a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/api.md +++ b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/api.md @@ -1,6 +1,6 @@ --- name: sentry-cli-api -version: 0.47.0-dev.0 +version: 0.48.0-dev.0 description: Make an authenticated API request requires: bins: ["sentry"] diff --git a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/auth.md b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/auth.md index 4d930876f..43fbe9eee 100644 --- a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/auth.md +++ b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/auth.md @@ -1,6 +1,6 @@ --- name: sentry-cli-auth -version: 0.47.0-dev.0 +version: 0.48.0-dev.0 description: Authenticate with Sentry requires: bins: ["sentry"] diff --git a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/build.md b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/build.md index 7ad9177be..4064f1e2a 100644 --- a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/build.md +++ b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/build.md @@ -1,6 +1,6 @@ --- name: sentry-cli-build -version: 0.47.0-dev.0 +version: 0.48.0-dev.0 description: Manage mobile build artifacts requires: bins: ["sentry"] diff --git a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/cli.md b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/cli.md index 0f67cf10f..8798683ce 100644 --- a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/cli.md +++ b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/cli.md @@ -1,6 +1,6 @@ --- name: sentry-cli-cli -version: 0.47.0-dev.0 +version: 0.48.0-dev.0 description: CLI-related commands requires: bins: ["sentry"] diff --git a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/code-mappings.md b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/code-mappings.md index 220d58afe..dd8b92ed6 100644 --- a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/code-mappings.md +++ b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/code-mappings.md @@ -1,6 +1,6 @@ --- name: sentry-cli-code-mappings -version: 0.47.0-dev.0 +version: 0.48.0-dev.0 description: Manage code mappings for stack trace linking requires: bins: ["sentry"] diff --git a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/dart-symbol-map.md b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/dart-symbol-map.md index 12e3a2025..5179747fa 100644 --- a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/dart-symbol-map.md +++ b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/dart-symbol-map.md @@ -1,6 +1,6 @@ --- name: sentry-cli-dart-symbol-map -version: 0.47.0-dev.0 +version: 0.48.0-dev.0 description: Work with Dart/Flutter symbol maps requires: bins: ["sentry"] diff --git a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/dashboard.md b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/dashboard.md index a750cc782..64660543a 100644 --- a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/dashboard.md +++ b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/dashboard.md @@ -1,6 +1,6 @@ --- name: sentry-cli-dashboard -version: 0.47.0-dev.0 +version: 0.48.0-dev.0 description: Manage Sentry dashboards requires: bins: ["sentry"] diff --git a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/debug-files.md b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/debug-files.md index 7fa5f931f..06ad6b1dd 100644 --- a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/debug-files.md +++ b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/debug-files.md @@ -1,6 +1,6 @@ --- name: sentry-cli-debug-files -version: 0.47.0-dev.0 +version: 0.48.0-dev.0 description: Work with debug information files requires: bins: ["sentry"] diff --git a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/docs.md b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/docs.md index 28ef7d857..0c523242d 100644 --- a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/docs.md +++ b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/docs.md @@ -1,6 +1,6 @@ --- name: sentry-cli-docs -version: 0.47.0-dev.0 +version: 0.48.0-dev.0 description: Search and query current Sentry documentation requires: bins: ["sentry"] diff --git a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/dsn.md b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/dsn.md index 840f93395..042f65e72 100644 --- a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/dsn.md +++ b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/dsn.md @@ -1,6 +1,6 @@ --- name: sentry-cli-dsn -version: 0.47.0-dev.0 +version: 0.48.0-dev.0 description: Find Sentry DSNs requires: bins: ["sentry"] diff --git a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/event.md b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/event.md index 9150610c0..0c5da357d 100644 --- a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/event.md +++ b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/event.md @@ -1,6 +1,6 @@ --- name: sentry-cli-event -version: 0.47.0-dev.0 +version: 0.48.0-dev.0 description: View, list, and send Sentry events requires: bins: ["sentry"] diff --git a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/explore.md b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/explore.md index 4644b453b..745ab082f 100644 --- a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/explore.md +++ b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/explore.md @@ -1,6 +1,6 @@ --- name: sentry-cli-explore -version: 0.47.0-dev.0 +version: 0.48.0-dev.0 description: Query aggregate event data (Explore) requires: bins: ["sentry"] diff --git a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/feedback.md b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/feedback.md index 4b5715ed1..f6822c432 100644 --- a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/feedback.md +++ b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/feedback.md @@ -1,6 +1,6 @@ --- name: sentry-cli-feedback -version: 0.47.0-dev.0 +version: 0.48.0-dev.0 description: Manage User Feedback requires: bins: ["sentry"] diff --git a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/info.md b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/info.md index 62a6f7771..3d81d9d71 100644 --- a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/info.md +++ b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/info.md @@ -1,6 +1,6 @@ --- name: sentry-cli-info -version: 0.47.0-dev.0 +version: 0.48.0-dev.0 description: Print configuration and verify authentication requires: bins: ["sentry"] diff --git a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/init.md b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/init.md index c2e487800..491f3c1c3 100644 --- a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/init.md +++ b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/init.md @@ -1,6 +1,6 @@ --- name: sentry-cli-init -version: 0.47.0-dev.0 +version: 0.48.0-dev.0 description: Initialize Sentry in your project (experimental) requires: bins: ["sentry"] diff --git a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/issue.md b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/issue.md index ccda75288..89c58b651 100644 --- a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/issue.md +++ b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/issue.md @@ -1,6 +1,6 @@ --- name: sentry-cli-issue -version: 0.47.0-dev.0 +version: 0.48.0-dev.0 description: Manage Sentry issues requires: bins: ["sentry"] @@ -232,6 +232,8 @@ sentry issue view FRONT-ABC # Multiple issues in one invocation (space-separated, not commas) sentry issue view FRONT-ABC BACK-2 +sentry issue view my-org/FRONT-ABC + # Open one or more issues in the browser (up to 5 tabs by default) sentry issue view FRONT-ABC BACK-2 -w diff --git a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/local.md b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/local.md index 9e173e55c..df92efaab 100644 --- a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/local.md +++ b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/local.md @@ -1,6 +1,6 @@ --- name: sentry-cli-local -version: 0.47.0-dev.0 +version: 0.48.0-dev.0 description: Sentry for local development requires: bins: ["sentry"] diff --git a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/log.md b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/log.md index aeb34e043..c49af07c6 100644 --- a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/log.md +++ b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/log.md @@ -1,6 +1,6 @@ --- name: sentry-cli-log -version: 0.47.0-dev.0 +version: 0.48.0-dev.0 description: View Sentry logs requires: bins: ["sentry"] diff --git a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/monitor.md b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/monitor.md index 4b13cbcc1..5288bd644 100644 --- a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/monitor.md +++ b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/monitor.md @@ -1,6 +1,6 @@ --- name: sentry-cli-monitor -version: 0.47.0-dev.0 +version: 0.48.0-dev.0 description: Work with Sentry cron monitors requires: bins: ["sentry"] diff --git a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/org.md b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/org.md index c6f52b78c..285a19849 100644 --- a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/org.md +++ b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/org.md @@ -1,6 +1,6 @@ --- name: sentry-cli-org -version: 0.47.0-dev.0 +version: 0.48.0-dev.0 description: Work with Sentry organizations requires: bins: ["sentry"] diff --git a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/platform.md b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/platform.md index 461689158..c684a5a08 100644 --- a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/platform.md +++ b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/platform.md @@ -1,6 +1,6 @@ --- name: sentry-cli-platform -version: 0.47.0-dev.0 +version: 0.48.0-dev.0 description: List valid Sentry platform identifiers requires: bins: ["sentry"] diff --git a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/proguard.md b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/proguard.md index 8e8e08a0b..98d82f876 100644 --- a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/proguard.md +++ b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/proguard.md @@ -1,6 +1,6 @@ --- name: sentry-cli-proguard -version: 0.47.0-dev.0 +version: 0.48.0-dev.0 description: Work with ProGuard/R8 mapping files requires: bins: ["sentry"] diff --git a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/project.md b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/project.md index d0d83dc54..4609b61ec 100644 --- a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/project.md +++ b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/project.md @@ -1,6 +1,6 @@ --- name: sentry-cli-project -version: 0.47.0-dev.0 +version: 0.48.0-dev.0 description: Work with Sentry projects requires: bins: ["sentry"] diff --git a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/react-native.md b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/react-native.md index e3d808e24..3ab79f766 100644 --- a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/react-native.md +++ b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/react-native.md @@ -1,6 +1,6 @@ --- name: sentry-cli-react-native -version: 0.47.0-dev.0 +version: 0.48.0-dev.0 description: Upload React Native sourcemaps from build steps requires: bins: ["sentry"] diff --git a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/release.md b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/release.md index 244b27a20..51b33b3d3 100644 --- a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/release.md +++ b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/release.md @@ -1,6 +1,6 @@ --- name: sentry-cli-release -version: 0.47.0-dev.0 +version: 0.48.0-dev.0 description: Work with Sentry releases requires: bins: ["sentry"] diff --git a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/replay.md b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/replay.md index 39bf76aa7..ebb72a753 100644 --- a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/replay.md +++ b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/replay.md @@ -1,6 +1,6 @@ --- name: sentry-cli-replay -version: 0.47.0-dev.0 +version: 0.48.0-dev.0 description: Search and inspect Session Replays requires: bins: ["sentry"] diff --git a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/repo.md b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/repo.md index 6621aaeba..03ff3b504 100644 --- a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/repo.md +++ b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/repo.md @@ -1,6 +1,6 @@ --- name: sentry-cli-repo -version: 0.47.0-dev.0 +version: 0.48.0-dev.0 description: Work with Sentry repositories requires: bins: ["sentry"] diff --git a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/schema.md b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/schema.md index c56b69d73..4d4f4abb8 100644 --- a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/schema.md +++ b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/schema.md @@ -1,6 +1,6 @@ --- name: sentry-cli-schema -version: 0.47.0-dev.0 +version: 0.48.0-dev.0 description: Browse the Sentry API schema requires: bins: ["sentry"] diff --git a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/snapshots.md b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/snapshots.md index 43f584ec1..332f5b68a 100644 --- a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/snapshots.md +++ b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/snapshots.md @@ -1,6 +1,6 @@ --- name: sentry-cli-snapshots -version: 0.47.0-dev.0 +version: 0.48.0-dev.0 description: Manage and compare snapshots requires: bins: ["sentry"] diff --git a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/sourcemap.md b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/sourcemap.md index 749e45d3d..0998bdd9a 100644 --- a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/sourcemap.md +++ b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/sourcemap.md @@ -1,6 +1,6 @@ --- name: sentry-cli-sourcemap -version: 0.47.0-dev.0 +version: 0.48.0-dev.0 description: Manage sourcemaps requires: bins: ["sentry"] diff --git a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/span.md b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/span.md index b204a11c1..3e9b03334 100644 --- a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/span.md +++ b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/span.md @@ -1,6 +1,6 @@ --- name: sentry-cli-span -version: 0.47.0-dev.0 +version: 0.48.0-dev.0 description: List and view spans in projects or traces requires: bins: ["sentry"] diff --git a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/status.md b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/status.md index 452742129..86ce11bcd 100644 --- a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/status.md +++ b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/status.md @@ -1,6 +1,6 @@ --- name: sentry-cli-status -version: 0.47.0-dev.0 +version: 0.48.0-dev.0 description: Check Sentry service status requires: bins: ["sentry"] diff --git a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/team.md b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/team.md index dac91fe16..a074f709b 100644 --- a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/team.md +++ b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/team.md @@ -1,6 +1,6 @@ --- name: sentry-cli-team -version: 0.47.0-dev.0 +version: 0.48.0-dev.0 description: Work with Sentry teams requires: bins: ["sentry"] diff --git a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/trace.md b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/trace.md index 65d392b5d..67112896a 100644 --- a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/trace.md +++ b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/trace.md @@ -1,6 +1,6 @@ --- name: sentry-cli-trace -version: 0.47.0-dev.0 +version: 0.48.0-dev.0 description: View distributed traces requires: bins: ["sentry"] diff --git a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/trial.md b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/trial.md index 333cafd7c..3b857dddc 100644 --- a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/trial.md +++ b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/trial.md @@ -1,6 +1,6 @@ --- name: sentry-cli-trial -version: 0.47.0-dev.0 +version: 0.48.0-dev.0 description: Manage product trials requires: bins: ["sentry"] diff --git a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/wasm-split.md b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/wasm-split.md index 3ed78dca8..33179e2cb 100644 --- a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/wasm-split.md +++ b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/wasm-split.md @@ -1,6 +1,6 @@ --- name: sentry-cli-wasm-split -version: 0.47.0-dev.0 +version: 0.48.0-dev.0 description: Add build ids to WebAssembly modules and split out debug data requires: bins: ["sentry"] diff --git a/packages/cli/src/commands/feedback/view.ts b/packages/cli/src/commands/feedback/view.ts index 6d9b74b4c..bb8823f5c 100644 --- a/packages/cli/src/commands/feedback/view.ts +++ b/packages/cli/src/commands/feedback/view.ts @@ -101,10 +101,12 @@ export const viewCommand = buildCommand({ "Feedback formats:\n" + " @latest Most recent unresolved Feedback\n" + " /@latest Most recent unresolved Feedback in an organization\n" + - " Search accessible organizations\n" + + " Use configured org or discover the organization\n" + " Resolve by numeric issue ID\n" + " / Explicit organization\n" + " // Explicit organization and project\n\n" + + "Full short IDs use SENTRY_ORG, .sentryclirc, or 'sentry cli defaults' for the org.\n" + + "Without a configured org, the CLI uses a matching DSN or searches accessible orgs.\n\n" + "The resolved issue must have issue.category:feedback. Use 'sentry issue view' for other issue categories.", }, output: { diff --git a/packages/cli/src/commands/issue/explain.ts b/packages/cli/src/commands/issue/explain.ts index a8f2467d3..4591510d4 100644 --- a/packages/cli/src/commands/issue/explain.ts +++ b/packages/cli/src/commands/issue/explain.ts @@ -95,9 +95,11 @@ export const explainCommand = buildCommand({ " /ID - Explicit org: sentry/EXTENSION-7, sentry/cli-G\n" + " /@selector - Selector with org: my-org/@latest\n" + " -suffix - Project + suffix: cli-G, spotlight-electron-4Y\n" + - " ID - Short ID: CLI-G (searches across orgs)\n" + + " ID - Short ID: CLI-G (uses configured org when set)\n" + " suffix - Suffix only: G (requires DSN context)\n" + " numeric - Numeric ID: 123456789\n\n" + + "Full short IDs use SENTRY_ORG, .sentryclirc, or 'sentry cli defaults' for the org.\n" + + "Without a configured org, the CLI uses a matching DSN or searches accessible orgs.\n\n" + "Multiple issue IDs can be passed as separate arguments or newline-separated\n" + "within a single argument.\n\n" + "Examples:\n" + diff --git a/packages/cli/src/commands/issue/plan.ts b/packages/cli/src/commands/issue/plan.ts index 4a6db7ede..a5e12ec40 100644 --- a/packages/cli/src/commands/issue/plan.ts +++ b/packages/cli/src/commands/issue/plan.ts @@ -211,9 +211,11 @@ export const planCommand = buildCommand({ " /ID - Explicit org: sentry/EXTENSION-7, sentry/cli-G\n" + " /@selector - Selector with org: my-org/@latest\n" + " -suffix - Project + suffix: cli-G, spotlight-electron-4Y\n" + - " ID - Short ID: CLI-G (searches across orgs)\n" + + " ID - Short ID: CLI-G (uses configured org when set)\n" + " suffix - Suffix only: G (requires DSN context)\n" + " numeric - Numeric ID: 123456789\n\n" + + "Full short IDs use SENTRY_ORG, .sentryclirc, or 'sentry cli defaults' for the org.\n" + + "Without a configured org, the CLI uses a matching DSN or searches accessible orgs.\n\n" + "Prerequisites:\n" + " - GitHub integration configured for your organization\n" + " - Code mappings set up for your project\n\n" + diff --git a/packages/cli/src/commands/issue/utils.ts b/packages/cli/src/commands/issue/utils.ts index 00e43771c..c3c9aed26 100644 --- a/packages/cli/src/commands/issue/utils.ts +++ b/packages/cli/src/commands/issue/utils.ts @@ -16,6 +16,7 @@ import { type IssueSort, listIssuesPaginated, listOrganizations, + listOrganizationsUncached, ORG_FANOUT_CONCURRENCY, triggerRootCauseAnalysis, tryGetIssueByShortId, @@ -32,6 +33,7 @@ import { setCachedIssueOrg, } from "../../lib/db/issue-org-cache.js"; import { getProjectByAlias } from "../../lib/db/project-aliases.js"; +import { getCachedOrganizations } from "../../lib/db/regions.js"; import { detectAllDsns } from "../../lib/dsn/index.js"; import { ApiError, @@ -46,6 +48,7 @@ import { logger } from "../../lib/logger.js"; import { poll } from "../../lib/polling.js"; import { resolveEffectiveOrg } from "../../lib/region.js"; import { + resolveConfiguredOrg, resolveFromDsn, resolveOrg, resolveOrgAndProject, @@ -331,14 +334,60 @@ async function resolveProjectSearchFallback( ); } +/** Search the supplied orgs and preserve failures when none could be queried. */ +async function findIssuesByShortId( + orgSlugs: readonly string[], + fullShortId: string +): Promise { + const limit = pLimit(ORG_FANOUT_CONCURRENCY); + const results = await Promise.all( + orgSlugs.map((org) => + limit(() => + withAuthGuard(() => + tryGetIssueByShortId(org, fullShortId, { + collapse: ISSUE_DETAIL_COLLAPSE, + }) + ) + ) + ) + ); + + const successes: StrictResolvedIssue[] = []; + for (let i = 0; i < results.length; i++) { + const result = results[i]; + const org = orgSlugs[i]; + if (result && org && result.ok && result.value) { + successes.push({ org, issue: result.value }); + } + } + + // If every org failed with a real error (403, 5xx, network timeout), + // surface it instead of falling through to a misleading "not found". + // Only throw when ALL results are errors — if some orgs returned clean + // 404s ({ok: true, value: null}), fall through to the fallback for a + // precise error message. + const realErrors = results.filter( + (r): r is AuthGuardFailure => r !== undefined && !r.ok + ); + if (realErrors.length === results.length && realErrors.length > 0) { + const firstError = realErrors[0]?.error; + if (firstError instanceof Error) { + throw firstError; + } + } + + return successes; +} + /** * Resolve project-search type: search for project across orgs, then fetch issue. * * Resolution order: * 1. Try alias cache (fast, local) - * 2. Check DSN detection cache - * 3. Try shortid endpoint directly across all orgs (fast path) - * 4. Fall back to findProjectsBySlug for precise error messages + * 2. Use the configured organization, if any + * 3. Check DSN detection cache for the matching project + * 4. Search accessible orgs, refreshing a cached list once on a miss + * 5. Fall back to findProjectsBySlug for precise error messages * * @param projectSlug - Project slug to search for * @param suffix - Issue suffix (uppercase) @@ -362,7 +411,17 @@ async function resolveProjectSearch( return aliasResult; } - // 2. Check if DSN detection already resolved this project. + const fullShortId = expandToFullShortId(suffix, projectSlug); + const configured = await resolveConfiguredOrg({ cwd }); + if (configured) { + const org = await resolveEffectiveOrg(configured.org); + const issue = await getIssueByShortId(org, fullShortId, { + collapse: ISSUE_DETAIL_COLLAPSE, + }); + return { org, issue }; + } + + // Check if DSN detection already resolved this project. // resolveFromDsn() reads from the DSN cache (populated by detectAllDsns // in tryResolveFromAlias above) + project cache. This avoids the expensive // listOrganizations() fan-out when the DSN matches the target project. @@ -378,40 +437,33 @@ async function resolveProjectSearch( dsnTarget && dsnTarget.project.toLowerCase() === projectSlug.toLowerCase() ) { - const fullShortId = expandToFullShortId(suffix, dsnTarget.project); const issue = await getIssueByShortId(dsnTarget.org, fullShortId, { collapse: ISSUE_DETAIL_COLLAPSE, }); return { org: dsnTarget.org, issue }; } - // 3. Fast path: try resolving the short ID directly across all orgs. + // Try resolving the short ID directly across all orgs. // The shortid endpoint validates both project existence and issue existence // in a single call, eliminating the separate getProject() round-trip. // Concurrency-limited to avoid overwhelming the API for enterprise users. - const fullShortId = expandToFullShortId(suffix, projectSlug); + const hadCachedOrganizations = getCachedOrganizations().length > 0; const orgs = await listOrganizations(); - const limit = pLimit(ORG_FANOUT_CONCURRENCY); - const results = await Promise.all( - orgs.map((org) => - limit(() => - withAuthGuard(() => - tryGetIssueByShortId(org.slug, fullShortId, { - collapse: ISSUE_DETAIL_COLLAPSE, - }) - ) - ) - ) + let successes = await findIssuesByShortId( + orgs.map((org) => org.slug), + fullShortId ); - const successes: StrictResolvedIssue[] = []; - for (let i = 0; i < results.length; i++) { - const result = results[i]; - const org = orgs[i]; - if (result && org && result.ok && result.value) { - successes.push({ org: org.slug, issue: result.value }); - } + // A nonempty cache need not include every accessible org. Refresh once on + // a miss, and only search orgs not already queried in this invocation. + if (successes.length === 0 && hadCachedOrganizations) { + const searchedOrgs = new Set(orgs.map((org) => org.slug)); + const freshOrgs = await listOrganizationsUncached(); + const newOrgSlugs = freshOrgs + .map((org) => org.slug) + .filter((org) => !searchedOrgs.has(org)); + successes = await findIssuesByShortId(newOrgSlugs, fullShortId); } if (successes.length === 1 && successes[0]) { @@ -431,22 +483,7 @@ async function resolveProjectSearch( ); } - // If every org failed with a real error (403, 5xx, network timeout), - // surface it instead of falling through to a misleading "not found". - // Only throw when ALL results are errors — if some orgs returned clean - // 404s ({ok: true, value: null}), fall through to the fallback for a - // precise error message. - const realErrors = results.filter( - (r): r is AuthGuardFailure => r !== undefined && !r.ok - ); - if (realErrors.length === results.length && realErrors.length > 0) { - const firstError = realErrors[0]?.error; - if (firstError instanceof Error) { - throw firstError; - } - } - - // 4. Fall back to findProjectsBySlug for precise error messages + // Fall back to findProjectsBySlug for precise error messages // and retry the issue lookup (handles transient failures). return resolveProjectSearchFallback(projectSlug, suffix, commandContext); } diff --git a/packages/cli/src/commands/issue/view.ts b/packages/cli/src/commands/issue/view.ts index 53051ab7f..9e8f7ac83 100644 --- a/packages/cli/src/commands/issue/view.ts +++ b/packages/cli/src/commands/issue/view.ts @@ -243,10 +243,12 @@ export const viewCommand = buildCommand({ " /ID - Explicit org: sentry/EXTENSION-7, sentry/cli-G\n" + " /@selector - Selector with org: my-org/@latest\n" + " -suffix - Project + suffix: cli-G, spotlight-electron-4Y\n" + - " ID - Short ID: CLI-G (searches across orgs)\n" + + " ID - Short ID: CLI-G (uses configured org when set)\n" + " suffix - Suffix only: G (requires DSN context)\n" + " numeric - Numeric ID: 123456789\n" + " org/project#ID - GitHub-style: my-org/my-project#PROJ-123\n\n" + + "Full short IDs use SENTRY_ORG, .sentryclirc, or 'sentry cli defaults' for the org.\n" + + "Without a configured org, the CLI uses a matching DSN or searches accessible orgs.\n\n" + "Multiple issue IDs can be passed as separate arguments or newline-separated\n" + "within a single argument (handy when piping from other commands).\n" + `With --web, up to ${MAX_WEB_ISSUES} issues open by default; pass --force to open all.\n\n` + diff --git a/packages/cli/src/lib/api/organizations.ts b/packages/cli/src/lib/api/organizations.ts index 616ff00f4..a463c7616 100644 --- a/packages/cli/src/lib/api/organizations.ts +++ b/packages/cli/src/lib/api/organizations.ts @@ -63,14 +63,19 @@ export async function getUserRegions(): Promise { */ export async function listOrganizationsPage( baseUrl: string, - options: { cursor?: string; perPage?: number } = {} + options: { cursor?: string; perPage?: number; cache?: "reload" } = {} ): Promise> { const config = getSdkConfig(baseUrl); - const result = await sdkListOrganizations({ + // Node's RequestInit types omit cache, although the SDK forwards it to Request. + const requestOptions = { ...config, + cache: options.cache, query: { cursor: options.cursor, per_page: options.perPage }, - }); + } satisfies Parameters[0] & { + cache?: "reload"; + }; + const result = await sdkListOrganizations(requestOptions); // 403 enrichment (CLI-89, 24 users) is now handled centrally by // throwApiError() in infrastructure.ts — no per-endpoint catch needed. @@ -148,6 +153,7 @@ export async function listOrganizationsUncached(): Promise< listOrganizationsPage(controlSiloUrl, { cursor, perPage: API_MAX_PER_PAGE, + cache: "reload", }), MAX_PAGINATION_PAGES * API_MAX_PER_PAGE ); diff --git a/packages/cli/src/lib/resolve-target.ts b/packages/cli/src/lib/resolve-target.ts index 219e43c86..811672e99 100644 --- a/packages/cli/src/lib/resolve-target.ts +++ b/packages/cli/src/lib/resolve-target.ts @@ -1841,20 +1841,8 @@ export async function resolveOrgProjectOrGuide( return resolved ?? (await guideOrgProjectFailure(options)); } -/** - * Resolve organization only from multiple sources. - * - * Resolution priority: - * 1. Positional argument - * 2. SENTRY_ORG / SENTRY_PROJECT env vars - * 3. `.sentryclirc` config file - * 4. Config defaults - * 5. DSN auto-detection - * - * @param options - Resolution options with flag and cwd - * @returns Resolved org, or null if resolution failed - */ -export async function resolveOrg( +/** Resolve an explicitly configured org, without inferring one from a DSN. */ +export async function resolveConfiguredOrg( options: ResolveOrgOptions ): Promise { const { org, cwd } = options; @@ -1889,10 +1877,25 @@ export async function resolveOrg( return { org: defaultOrg }; } + return null; +} + +/** + * Resolve an org from arguments, environment, .sentryclirc, defaults, then DSN. + * Configured context takes precedence over automatic detection. + */ +export async function resolveOrg( + options: ResolveOrgOptions +): Promise { + const configured = await resolveConfiguredOrg(options); + if (configured) { + return configured; + } + // 5. DSN auto-detection // biome-ignore lint/plugin: grandfathered silent catch — see #1531; drain by adding log.debug()/log.warn() or re-throwing. try { - const result = await resolveOrgFromDsn(cwd); + const result = await resolveOrgFromDsn(options.cwd); if (result) { // resolveOrgFromDsn may return a bare numeric org ID when the project // cache is cold. Normalize to a slug so API endpoints that reject diff --git a/packages/cli/src/lib/sentry-client.ts b/packages/cli/src/lib/sentry-client.ts index 893b459d8..a14ce6e6f 100644 --- a/packages/cli/src/lib/sentry-client.ts +++ b/packages/cli/src/lib/sentry-client.ts @@ -574,6 +574,9 @@ async function fetchWithRetry( throw new Error("Exhausted all retry attempts"); } +// Node's RequestInit types omit cache; Request exposes the supported values. +type CacheRequestInit = RequestInit & { cache?: Request["cache"] }; + /** * Create a fetch function with authentication, timeout, retry, caching, and 401 refresh. * @@ -595,11 +598,11 @@ async function fetchWithRetry( */ function createAuthenticatedFetch(): ( input: Request | string | URL, - init?: RequestInit + init?: CacheRequestInit ) => Promise { return function authenticatedFetch( input: Request | string | URL, - init?: RequestInit + init?: CacheRequestInit ): Promise { // Reset cache-hit age so it reflects only this request's outcome. // Commands read it after their primary API call to show cache-age hints. @@ -614,6 +617,9 @@ function createAuthenticatedFetch(): ( const method = init?.method ?? (input instanceof Request ? input.method : "GET"); + const reload = + (init?.cache ?? (input instanceof Request ? input.cache : undefined)) === + "reload"; const urlPath = extractUrlPath(input); return withTracingSpan( @@ -625,11 +631,9 @@ function createAuthenticatedFetch(): ( // Check cache before auth/retry for GET requests. // Uses current token (no refresh) so lookups are fast but Vary-correct. - const cached = await tryCacheHit( - method, - fullUrl, - authHeaders(getAuthToken()) - ); + const cached = reload + ? undefined + : await tryCacheHit(method, fullUrl, authHeaders(getAuthToken())); if (cached) { span.setAttribute("http.response.status_code", cached.status); log.debug( diff --git a/packages/cli/test/commands/issue/short-id-resolution.test.ts b/packages/cli/test/commands/issue/short-id-resolution.test.ts new file mode 100644 index 000000000..31756bf41 --- /dev/null +++ b/packages/cli/test/commands/issue/short-id-resolution.test.ts @@ -0,0 +1,244 @@ +import { writeFileSync } from "node:fs"; +import { join } from "node:path"; +import { afterEach, beforeEach, describe, expect, test } from "vitest"; +import { resolveIssue } from "../../../src/commands/issue/utils.js"; +import { setAuthToken } from "../../../src/lib/db/auth.js"; +import { setDefaultOrganization } from "../../../src/lib/db/defaults.js"; +import { setProjectAliases } from "../../../src/lib/db/project-aliases.js"; +import { setCachedProject } from "../../../src/lib/db/project-cache.js"; +import { setOrgRegion, setOrgRegions } from "../../../src/lib/db/regions.js"; +import { ApiError, ResolutionError } from "../../../src/lib/errors.js"; +import issueFixture from "../../fixtures/issue.json"; +import organizationFixture from "../../fixtures/organization.json"; +import { mockFetch, useEnvSandbox, useTestConfigDir } from "../../helpers.js"; + +const SHORT_ID = "CUSTOM-5BS"; +const REGION_URL = "https://de.sentry.io"; + +function organization(slug: string, id: string) { + return { + ...organizationFixture, + slug, + id, + links: { regionUrl: REGION_URL }, + }; +} + +const cachedOrg = organization("cached-org", "1"); +const targetOrg = organization("target-org", "2"); +const secondOrg = organization("second-org", "3"); + +const getConfigDir = useTestConfigDir("test-short-id-resolution-", { + isolateProjectRoot: true, +}); +useEnvSandbox(["SENTRY_ORG", "SENTRY_PROJECT", "SENTRY_DSN"]); + +let originalFetch: typeof fetch; +let listedOrgs: ReturnType[]; +let listingStatus: number; +let requests: URL[]; +let issues: Map; + +function addIssue(org: string, shortId = SHORT_ID): void { + issues.set(`${org}/${shortId}`, { + ...issueFixture, + shortId, + // Sentry's short-ID prefix need not equal the current project slug. + project: { ...issueFixture.project, slug: "renamed-project" }, + }); +} + +function resolve(issueArg = SHORT_ID) { + return resolveIssue({ issueArg, cwd: getConfigDir(), command: "view" }); +} + +function listingRequests() { + return requests.filter((url) => url.pathname === "/api/0/organizations/"); +} + +function shortIdRequests() { + return requests.filter((url) => url.pathname.includes("/shortids/")); +} + +beforeEach(async () => { + originalFetch = globalThis.fetch; + requests = []; + listedOrgs = [cachedOrg]; + listingStatus = 200; + issues = new Map(); + await setAuthToken("test-token"); + setOrgRegions([ + { + slug: cachedOrg.slug, + regionUrl: REGION_URL, + orgId: cachedOrg.id, + orgName: cachedOrg.name, + }, + ]); + // Routing information alone does not make these orgs listing candidates. + setOrgRegion(targetOrg.slug, REGION_URL); + setOrgRegion(secondOrg.slug, REGION_URL); + + globalThis.fetch = mockFetch(async (input, init) => { + const url = new URL(new Request(input, init).url); + requests.push(url); + if (url.pathname === "/api/0/organizations/") { + return Response.json( + listingStatus === 200 ? listedOrgs : { detail: "Forbidden" }, + { status: listingStatus } + ); + } + for (const [key, issue] of issues) { + const [org, shortId] = key.split("/"); + if (url.pathname === `/api/0/organizations/${org}/shortids/${shortId}/`) { + return Response.json({ group: issue }); + } + } + return Response.json({ detail: "Not found" }, { status: 404 }); + }); +}); + +afterEach(() => { + globalThis.fetch = originalFetch; +}); + +describe("short IDs with configured organization context", () => { + test("uses a default org missing from the cached and API organization lists", async () => { + setDefaultOrganization(targetOrg.slug); + addIssue(targetOrg.slug); + + const result = await resolve(); + + expect(result.org).toBe(targetOrg.slug); + expect(result.issue.shortId).toBe(SHORT_ID); + expect(listingRequests()).toHaveLength(0); + expect(shortIdRequests().map((url) => url.href)).toEqual([ + expect.stringContaining(`${REGION_URL}/api/0/organizations/target-org/`), + ]); + }); + + test.each([ + { envOrg: secondOrg.slug, expectedOrg: secondOrg.slug }, + { envOrg: undefined, expectedOrg: targetOrg.slug }, + ])("honors env and .sentryclirc precedence: $expectedOrg", async ({ + envOrg, + expectedOrg, + }) => { + setDefaultOrganization(cachedOrg.slug); + writeFileSync( + join(getConfigDir(), ".sentryclirc"), + `[defaults]\norg = ${targetOrg.slug}\n` + ); + if (envOrg) { + process.env.SENTRY_ORG = envOrg; + } + for (const org of [cachedOrg, targetOrg, secondOrg]) { + addIssue(org.slug); + } + + expect((await resolve()).org).toBe(expectedOrg); + expect(listingRequests()).toHaveLength(0); + expect(shortIdRequests()).toHaveLength(1); + }); + + test("does not fall through to another org when the configured org returns 404", async () => { + setDefaultOrganization(targetOrg.slug); + addIssue(cachedOrg.slug); + + await expect(resolve()).rejects.toMatchObject({ status: 404 }); + + expect(listingRequests()).toHaveLength(0); + expect(shortIdRequests().map((url) => url.pathname)).toEqual([ + `/api/0/organizations/target-org/shortids/${SHORT_ID}/`, + ]); + }); + + test("preserves an alias's org even when a different default is configured", async () => { + setDefaultOrganization(targetOrg.slug); + setProjectAliases( + { f: { orgSlug: cachedOrg.slug, projectSlug: "frontend" } }, + "" + ); + addIssue(cachedOrg.slug, "FRONTEND-5BS"); + + expect((await resolve("f-5BS")).org).toBe(cachedOrg.slug); + expect(listingRequests()).toHaveLength(0); + }); +}); + +describe("short IDs missing from cached organizations", () => { + test("refreshes once and resolves a new EU org even when the project slug differs from the prefix", async () => { + listedOrgs = [cachedOrg, targetOrg]; + addIssue(targetOrg.slug); + + const result = await resolve(); + + expect(result.org).toBe(targetOrg.slug); + expect(result.issue.project?.slug).toBe("renamed-project"); + expect(listingRequests()).toHaveLength(1); + expect(shortIdRequests().map((url) => url.pathname)).toEqual([ + `/api/0/organizations/cached-org/shortids/${SHORT_ID}/`, + `/api/0/organizations/target-org/shortids/${SHORT_ID}/`, + ]); + expect(shortIdRequests().every((url) => url.origin === REGION_URL)).toBe( + true + ); + }); + + test.each([ + { label: "unchanged", inventory: [cachedOrg] }, + { label: "new organization", inventory: [cachedOrg, targetOrg] }, + ])("keeps a still-missing lookup bounded after refresh: $label", async ({ + inventory, + }) => { + listedOrgs = inventory; + + await expect(resolve()).rejects.toBeInstanceOf(ResolutionError); + + expect(listingRequests()).toHaveLength(1); + expect(shortIdRequests()).toHaveLength(inventory.length); + expect(new Set(shortIdRequests().map((url) => url.pathname)).size).toBe( + inventory.length + ); + }); + + test("reports ambiguity when the refresh discovers two matching orgs", async () => { + listedOrgs = [cachedOrg, targetOrg, secondOrg]; + addIssue(targetOrg.slug); + addIssue(secondOrg.slug); + + await expect(resolve()).rejects.toThrow("is ambiguous"); + + expect(listingRequests()).toHaveLength(1); + expect(shortIdRequests()).toHaveLength(3); + }); + + test("propagates refresh failures instead of reporting an absent issue", async () => { + listingStatus = 403; + + const error = await resolve().catch((caught: unknown) => caught); + + expect(error).toBeInstanceOf(ApiError); + expect(error).toMatchObject({ status: 403 }); + expect(listingRequests()).toHaveLength(1); + }); + + test("does not scope the search to a DSN for a different project", async () => { + writeFileSync( + join(getConfigDir(), ".env"), + "SENTRY_DSN=https://abc@o123.ingest.de.sentry.io/456" + ); + setCachedProject("123", "456", { + orgSlug: cachedOrg.slug, + orgName: cachedOrg.name, + projectSlug: "unrelated-project", + projectName: "Unrelated Project", + projectId: "456", + }); + listedOrgs = [cachedOrg, targetOrg]; + addIssue(targetOrg.slug); + + expect((await resolve()).org).toBe(targetOrg.slug); + expect(listingRequests()).toHaveLength(1); + }); +}); diff --git a/packages/cli/test/lib/api/organizations.test.ts b/packages/cli/test/lib/api/organizations.test.ts index 98d5b5a2b..aa30c260e 100644 --- a/packages/cli/test/lib/api/organizations.test.ts +++ b/packages/cli/test/lib/api/organizations.test.ts @@ -1,17 +1,32 @@ /** - * Tests for listOrganizationsPage — guards against non-array SDK responses. + * Organization API response validation and fresh-list cache behavior. * * CLI-1CQ: self-hosted instances can return non-array data from * GET /api/0/organizations/ when a reverse proxy or WAF interferes. */ import { afterEach, beforeEach, describe, expect, test } from "vitest"; -import { listOrganizationsPage } from "../../../src/lib/api/organizations.js"; +import { + listOrganizations, + listOrganizationsPage, + listOrganizationsUncached, +} from "../../../src/lib/api/organizations.js"; import { setAuthToken } from "../../../src/lib/db/auth.js"; import { ApiError } from "../../../src/lib/errors.js"; -import { mockFetch, useTestConfigDir } from "../../helpers.js"; +import { + getCachedResponse, + storeCachedResponse, +} from "../../../src/lib/response-cache.js"; +import { mockFetch, useEnvSandbox, useTestConfigDir } from "../../helpers.js"; useTestConfigDir("org-api-test-"); +useEnvSandbox([ + "SENTRY_AUTH_TOKEN", + "SENTRY_TOKEN", + "SENTRY_HOST", + "SENTRY_URL", + "SENTRY_NO_CACHE", +]); let originalFetch: typeof globalThis.fetch; @@ -22,6 +37,45 @@ beforeEach(async () => { }); }); +test("uncached organization refresh replaces an incomplete HTTP response cache", async () => { + const baseUrl = "https://sentry.example.com"; + process.env.SENTRY_URL = baseUrl; + const url = `${baseUrl}/api/0/organizations/?per_page=100`; + const headers = { authorization: "Bearer fake-token-for-test" }; + const cachedOrgs = [{ id: "1", slug: "first-org", name: "First Org" }]; + const currentOrgs = [ + ...cachedOrgs, + { id: "2", slug: "new-org", name: "New Org" }, + ]; + await storeCachedResponse( + "GET", + url, + headers, + Response.json(cachedOrgs, { + headers: { "Cache-Control": "private, max-age=300" }, + }) + ); + + const requests: Request[] = []; + globalThis.fetch = mockFetch(async (input, init) => { + requests.push(new Request(input, init)); + return Response.json(currentOrgs); + }); + + const cachedPage = await listOrganizationsPage(baseUrl, { perPage: 100 }); + expect(cachedPage.data).toEqual(cachedOrgs); + expect(requests).toHaveLength(0); + + expect(await listOrganizationsUncached()).toEqual(currentOrgs); + expect(requests).toHaveLength(1); + expect(requests[0]?.url).toBe(url); + expect(requests[0]?.headers.get("Authorization")).toBe(headers.authorization); + expect(await listOrganizations()).toEqual(currentOrgs); + await expect + .poll(async () => (await getCachedResponse("GET", url, headers))?.json()) + .toEqual(currentOrgs); +}); + afterEach(() => { globalThis.fetch = originalFetch; }); From 61f2ace93a19e8ff15e8825a4ff0cb16b7692dcb Mon Sep 17 00:00:00 2001 From: betegon Date: Mon, 5 Oct 2026 21:46:06 +0200 Subject: [PATCH 2/4] chore(cli): exclude unrelated generated version updates Leave skill version regeneration to the dedicated PR while keeping the issue-specific documentation example. Co-Authored-By: GPT-6 --- packages/cli/plugins/sentry-cli/skills/sentry-cli/SKILL.md | 2 +- .../skills/sentry-cli/references/agent-conversation.md | 2 +- .../plugins/sentry-cli/skills/sentry-cli/references/alert.md | 2 +- .../cli/plugins/sentry-cli/skills/sentry-cli/references/api.md | 2 +- .../cli/plugins/sentry-cli/skills/sentry-cli/references/auth.md | 2 +- .../plugins/sentry-cli/skills/sentry-cli/references/build.md | 2 +- .../cli/plugins/sentry-cli/skills/sentry-cli/references/cli.md | 2 +- .../sentry-cli/skills/sentry-cli/references/code-mappings.md | 2 +- .../sentry-cli/skills/sentry-cli/references/dart-symbol-map.md | 2 +- .../sentry-cli/skills/sentry-cli/references/dashboard.md | 2 +- .../sentry-cli/skills/sentry-cli/references/debug-files.md | 2 +- .../cli/plugins/sentry-cli/skills/sentry-cli/references/docs.md | 2 +- .../cli/plugins/sentry-cli/skills/sentry-cli/references/dsn.md | 2 +- .../plugins/sentry-cli/skills/sentry-cli/references/event.md | 2 +- .../plugins/sentry-cli/skills/sentry-cli/references/explore.md | 2 +- .../plugins/sentry-cli/skills/sentry-cli/references/feedback.md | 2 +- .../cli/plugins/sentry-cli/skills/sentry-cli/references/info.md | 2 +- .../cli/plugins/sentry-cli/skills/sentry-cli/references/init.md | 2 +- .../plugins/sentry-cli/skills/sentry-cli/references/issue.md | 2 +- .../plugins/sentry-cli/skills/sentry-cli/references/local.md | 2 +- .../cli/plugins/sentry-cli/skills/sentry-cli/references/log.md | 2 +- .../plugins/sentry-cli/skills/sentry-cli/references/monitor.md | 2 +- .../cli/plugins/sentry-cli/skills/sentry-cli/references/org.md | 2 +- .../plugins/sentry-cli/skills/sentry-cli/references/platform.md | 2 +- .../plugins/sentry-cli/skills/sentry-cli/references/proguard.md | 2 +- .../plugins/sentry-cli/skills/sentry-cli/references/project.md | 2 +- .../sentry-cli/skills/sentry-cli/references/react-native.md | 2 +- .../plugins/sentry-cli/skills/sentry-cli/references/release.md | 2 +- .../plugins/sentry-cli/skills/sentry-cli/references/replay.md | 2 +- .../cli/plugins/sentry-cli/skills/sentry-cli/references/repo.md | 2 +- .../plugins/sentry-cli/skills/sentry-cli/references/schema.md | 2 +- .../sentry-cli/skills/sentry-cli/references/snapshots.md | 2 +- .../sentry-cli/skills/sentry-cli/references/sourcemap.md | 2 +- .../cli/plugins/sentry-cli/skills/sentry-cli/references/span.md | 2 +- .../plugins/sentry-cli/skills/sentry-cli/references/status.md | 2 +- .../cli/plugins/sentry-cli/skills/sentry-cli/references/team.md | 2 +- .../plugins/sentry-cli/skills/sentry-cli/references/trace.md | 2 +- .../plugins/sentry-cli/skills/sentry-cli/references/trial.md | 2 +- .../sentry-cli/skills/sentry-cli/references/wasm-split.md | 2 +- 39 files changed, 39 insertions(+), 39 deletions(-) diff --git a/packages/cli/plugins/sentry-cli/skills/sentry-cli/SKILL.md b/packages/cli/plugins/sentry-cli/skills/sentry-cli/SKILL.md index 7a3a17757..771c666c2 100644 --- a/packages/cli/plugins/sentry-cli/skills/sentry-cli/SKILL.md +++ b/packages/cli/plugins/sentry-cli/skills/sentry-cli/SKILL.md @@ -1,6 +1,6 @@ --- name: sentry-cli -version: 0.48.0-dev.0 +version: 0.47.0-dev.0 description: Guide for using the Sentry CLI to interact with Sentry from the command line. Use when the user asks about viewing issues, events, projects, organizations, making API calls, or authenticating with Sentry via CLI. requires: bins: ["sentry"] diff --git a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/agent-conversation.md b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/agent-conversation.md index 0ba3bdab8..ca7e7bb2a 100644 --- a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/agent-conversation.md +++ b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/agent-conversation.md @@ -1,6 +1,6 @@ --- name: sentry-cli-agent-conversation -version: 0.48.0-dev.0 +version: 0.47.0-dev.0 description: List and view agent conversations requires: bins: ["sentry"] diff --git a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/alert.md b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/alert.md index e742f6276..7ce0e7ef7 100644 --- a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/alert.md +++ b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/alert.md @@ -1,6 +1,6 @@ --- name: sentry-cli-alert -version: 0.48.0-dev.0 +version: 0.47.0-dev.0 description: Manage Sentry alert rules requires: bins: ["sentry"] diff --git a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/api.md b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/api.md index 6fe3ff6e3..9cee33e99 100644 --- a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/api.md +++ b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/api.md @@ -1,6 +1,6 @@ --- name: sentry-cli-api -version: 0.48.0-dev.0 +version: 0.47.0-dev.0 description: Make an authenticated API request requires: bins: ["sentry"] diff --git a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/auth.md b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/auth.md index 43fbe9eee..4d930876f 100644 --- a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/auth.md +++ b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/auth.md @@ -1,6 +1,6 @@ --- name: sentry-cli-auth -version: 0.48.0-dev.0 +version: 0.47.0-dev.0 description: Authenticate with Sentry requires: bins: ["sentry"] diff --git a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/build.md b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/build.md index 4064f1e2a..7ad9177be 100644 --- a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/build.md +++ b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/build.md @@ -1,6 +1,6 @@ --- name: sentry-cli-build -version: 0.48.0-dev.0 +version: 0.47.0-dev.0 description: Manage mobile build artifacts requires: bins: ["sentry"] diff --git a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/cli.md b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/cli.md index 8798683ce..0f67cf10f 100644 --- a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/cli.md +++ b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/cli.md @@ -1,6 +1,6 @@ --- name: sentry-cli-cli -version: 0.48.0-dev.0 +version: 0.47.0-dev.0 description: CLI-related commands requires: bins: ["sentry"] diff --git a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/code-mappings.md b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/code-mappings.md index dd8b92ed6..220d58afe 100644 --- a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/code-mappings.md +++ b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/code-mappings.md @@ -1,6 +1,6 @@ --- name: sentry-cli-code-mappings -version: 0.48.0-dev.0 +version: 0.47.0-dev.0 description: Manage code mappings for stack trace linking requires: bins: ["sentry"] diff --git a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/dart-symbol-map.md b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/dart-symbol-map.md index 5179747fa..12e3a2025 100644 --- a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/dart-symbol-map.md +++ b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/dart-symbol-map.md @@ -1,6 +1,6 @@ --- name: sentry-cli-dart-symbol-map -version: 0.48.0-dev.0 +version: 0.47.0-dev.0 description: Work with Dart/Flutter symbol maps requires: bins: ["sentry"] diff --git a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/dashboard.md b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/dashboard.md index 64660543a..a750cc782 100644 --- a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/dashboard.md +++ b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/dashboard.md @@ -1,6 +1,6 @@ --- name: sentry-cli-dashboard -version: 0.48.0-dev.0 +version: 0.47.0-dev.0 description: Manage Sentry dashboards requires: bins: ["sentry"] diff --git a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/debug-files.md b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/debug-files.md index 06ad6b1dd..7fa5f931f 100644 --- a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/debug-files.md +++ b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/debug-files.md @@ -1,6 +1,6 @@ --- name: sentry-cli-debug-files -version: 0.48.0-dev.0 +version: 0.47.0-dev.0 description: Work with debug information files requires: bins: ["sentry"] diff --git a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/docs.md b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/docs.md index 0c523242d..28ef7d857 100644 --- a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/docs.md +++ b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/docs.md @@ -1,6 +1,6 @@ --- name: sentry-cli-docs -version: 0.48.0-dev.0 +version: 0.47.0-dev.0 description: Search and query current Sentry documentation requires: bins: ["sentry"] diff --git a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/dsn.md b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/dsn.md index 042f65e72..840f93395 100644 --- a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/dsn.md +++ b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/dsn.md @@ -1,6 +1,6 @@ --- name: sentry-cli-dsn -version: 0.48.0-dev.0 +version: 0.47.0-dev.0 description: Find Sentry DSNs requires: bins: ["sentry"] diff --git a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/event.md b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/event.md index 0c5da357d..9150610c0 100644 --- a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/event.md +++ b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/event.md @@ -1,6 +1,6 @@ --- name: sentry-cli-event -version: 0.48.0-dev.0 +version: 0.47.0-dev.0 description: View, list, and send Sentry events requires: bins: ["sentry"] diff --git a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/explore.md b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/explore.md index 745ab082f..4644b453b 100644 --- a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/explore.md +++ b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/explore.md @@ -1,6 +1,6 @@ --- name: sentry-cli-explore -version: 0.48.0-dev.0 +version: 0.47.0-dev.0 description: Query aggregate event data (Explore) requires: bins: ["sentry"] diff --git a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/feedback.md b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/feedback.md index f6822c432..4b5715ed1 100644 --- a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/feedback.md +++ b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/feedback.md @@ -1,6 +1,6 @@ --- name: sentry-cli-feedback -version: 0.48.0-dev.0 +version: 0.47.0-dev.0 description: Manage User Feedback requires: bins: ["sentry"] diff --git a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/info.md b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/info.md index 3d81d9d71..62a6f7771 100644 --- a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/info.md +++ b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/info.md @@ -1,6 +1,6 @@ --- name: sentry-cli-info -version: 0.48.0-dev.0 +version: 0.47.0-dev.0 description: Print configuration and verify authentication requires: bins: ["sentry"] diff --git a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/init.md b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/init.md index 491f3c1c3..c2e487800 100644 --- a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/init.md +++ b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/init.md @@ -1,6 +1,6 @@ --- name: sentry-cli-init -version: 0.48.0-dev.0 +version: 0.47.0-dev.0 description: Initialize Sentry in your project (experimental) requires: bins: ["sentry"] diff --git a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/issue.md b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/issue.md index 89c58b651..9b006dd60 100644 --- a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/issue.md +++ b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/issue.md @@ -1,6 +1,6 @@ --- name: sentry-cli-issue -version: 0.48.0-dev.0 +version: 0.47.0-dev.0 description: Manage Sentry issues requires: bins: ["sentry"] diff --git a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/local.md b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/local.md index df92efaab..9e173e55c 100644 --- a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/local.md +++ b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/local.md @@ -1,6 +1,6 @@ --- name: sentry-cli-local -version: 0.48.0-dev.0 +version: 0.47.0-dev.0 description: Sentry for local development requires: bins: ["sentry"] diff --git a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/log.md b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/log.md index c49af07c6..aeb34e043 100644 --- a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/log.md +++ b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/log.md @@ -1,6 +1,6 @@ --- name: sentry-cli-log -version: 0.48.0-dev.0 +version: 0.47.0-dev.0 description: View Sentry logs requires: bins: ["sentry"] diff --git a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/monitor.md b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/monitor.md index 5288bd644..4b13cbcc1 100644 --- a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/monitor.md +++ b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/monitor.md @@ -1,6 +1,6 @@ --- name: sentry-cli-monitor -version: 0.48.0-dev.0 +version: 0.47.0-dev.0 description: Work with Sentry cron monitors requires: bins: ["sentry"] diff --git a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/org.md b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/org.md index 285a19849..c6f52b78c 100644 --- a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/org.md +++ b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/org.md @@ -1,6 +1,6 @@ --- name: sentry-cli-org -version: 0.48.0-dev.0 +version: 0.47.0-dev.0 description: Work with Sentry organizations requires: bins: ["sentry"] diff --git a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/platform.md b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/platform.md index c684a5a08..461689158 100644 --- a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/platform.md +++ b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/platform.md @@ -1,6 +1,6 @@ --- name: sentry-cli-platform -version: 0.48.0-dev.0 +version: 0.47.0-dev.0 description: List valid Sentry platform identifiers requires: bins: ["sentry"] diff --git a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/proguard.md b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/proguard.md index 98d82f876..8e8e08a0b 100644 --- a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/proguard.md +++ b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/proguard.md @@ -1,6 +1,6 @@ --- name: sentry-cli-proguard -version: 0.48.0-dev.0 +version: 0.47.0-dev.0 description: Work with ProGuard/R8 mapping files requires: bins: ["sentry"] diff --git a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/project.md b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/project.md index 4609b61ec..d0d83dc54 100644 --- a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/project.md +++ b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/project.md @@ -1,6 +1,6 @@ --- name: sentry-cli-project -version: 0.48.0-dev.0 +version: 0.47.0-dev.0 description: Work with Sentry projects requires: bins: ["sentry"] diff --git a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/react-native.md b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/react-native.md index 3ab79f766..e3d808e24 100644 --- a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/react-native.md +++ b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/react-native.md @@ -1,6 +1,6 @@ --- name: sentry-cli-react-native -version: 0.48.0-dev.0 +version: 0.47.0-dev.0 description: Upload React Native sourcemaps from build steps requires: bins: ["sentry"] diff --git a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/release.md b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/release.md index 51b33b3d3..244b27a20 100644 --- a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/release.md +++ b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/release.md @@ -1,6 +1,6 @@ --- name: sentry-cli-release -version: 0.48.0-dev.0 +version: 0.47.0-dev.0 description: Work with Sentry releases requires: bins: ["sentry"] diff --git a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/replay.md b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/replay.md index ebb72a753..39bf76aa7 100644 --- a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/replay.md +++ b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/replay.md @@ -1,6 +1,6 @@ --- name: sentry-cli-replay -version: 0.48.0-dev.0 +version: 0.47.0-dev.0 description: Search and inspect Session Replays requires: bins: ["sentry"] diff --git a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/repo.md b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/repo.md index 03ff3b504..6621aaeba 100644 --- a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/repo.md +++ b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/repo.md @@ -1,6 +1,6 @@ --- name: sentry-cli-repo -version: 0.48.0-dev.0 +version: 0.47.0-dev.0 description: Work with Sentry repositories requires: bins: ["sentry"] diff --git a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/schema.md b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/schema.md index 4d4f4abb8..c56b69d73 100644 --- a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/schema.md +++ b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/schema.md @@ -1,6 +1,6 @@ --- name: sentry-cli-schema -version: 0.48.0-dev.0 +version: 0.47.0-dev.0 description: Browse the Sentry API schema requires: bins: ["sentry"] diff --git a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/snapshots.md b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/snapshots.md index 332f5b68a..43f584ec1 100644 --- a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/snapshots.md +++ b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/snapshots.md @@ -1,6 +1,6 @@ --- name: sentry-cli-snapshots -version: 0.48.0-dev.0 +version: 0.47.0-dev.0 description: Manage and compare snapshots requires: bins: ["sentry"] diff --git a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/sourcemap.md b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/sourcemap.md index 0998bdd9a..749e45d3d 100644 --- a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/sourcemap.md +++ b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/sourcemap.md @@ -1,6 +1,6 @@ --- name: sentry-cli-sourcemap -version: 0.48.0-dev.0 +version: 0.47.0-dev.0 description: Manage sourcemaps requires: bins: ["sentry"] diff --git a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/span.md b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/span.md index 3e9b03334..b204a11c1 100644 --- a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/span.md +++ b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/span.md @@ -1,6 +1,6 @@ --- name: sentry-cli-span -version: 0.48.0-dev.0 +version: 0.47.0-dev.0 description: List and view spans in projects or traces requires: bins: ["sentry"] diff --git a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/status.md b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/status.md index 86ce11bcd..452742129 100644 --- a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/status.md +++ b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/status.md @@ -1,6 +1,6 @@ --- name: sentry-cli-status -version: 0.48.0-dev.0 +version: 0.47.0-dev.0 description: Check Sentry service status requires: bins: ["sentry"] diff --git a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/team.md b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/team.md index a074f709b..dac91fe16 100644 --- a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/team.md +++ b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/team.md @@ -1,6 +1,6 @@ --- name: sentry-cli-team -version: 0.48.0-dev.0 +version: 0.47.0-dev.0 description: Work with Sentry teams requires: bins: ["sentry"] diff --git a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/trace.md b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/trace.md index 67112896a..65d392b5d 100644 --- a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/trace.md +++ b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/trace.md @@ -1,6 +1,6 @@ --- name: sentry-cli-trace -version: 0.48.0-dev.0 +version: 0.47.0-dev.0 description: View distributed traces requires: bins: ["sentry"] diff --git a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/trial.md b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/trial.md index 3b857dddc..333cafd7c 100644 --- a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/trial.md +++ b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/trial.md @@ -1,6 +1,6 @@ --- name: sentry-cli-trial -version: 0.48.0-dev.0 +version: 0.47.0-dev.0 description: Manage product trials requires: bins: ["sentry"] diff --git a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/wasm-split.md b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/wasm-split.md index 33179e2cb..3ed78dca8 100644 --- a/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/wasm-split.md +++ b/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/wasm-split.md @@ -1,6 +1,6 @@ --- name: sentry-cli-wasm-split -version: 0.48.0-dev.0 +version: 0.47.0-dev.0 description: Add build ids to WebAssembly modules and split out debug data requires: bins: ["sentry"] From cb10efb7d0cf569d2ccdc1c75b207d1f27085a3e Mon Sep 17 00:00:00 2001 From: betegon Date: Mon, 5 Oct 2026 22:06:00 +0200 Subject: [PATCH 3/4] refactor(cli): keep short ID results paired with their org Return the organization with each lookup result so collection no longer depends on parallel array indices. Co-Authored-By: GPT-6 --- packages/cli/src/commands/issue/utils.ts | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/packages/cli/src/commands/issue/utils.ts b/packages/cli/src/commands/issue/utils.ts index c3c9aed26..d7ff09930 100644 --- a/packages/cli/src/commands/issue/utils.ts +++ b/packages/cli/src/commands/issue/utils.ts @@ -343,24 +343,16 @@ async function findIssuesByShortId( const results = await Promise.all( orgSlugs.map((org) => limit(() => - withAuthGuard(() => - tryGetIssueByShortId(org, fullShortId, { + withAuthGuard(async () => { + const issue = await tryGetIssueByShortId(org, fullShortId, { collapse: ISSUE_DETAIL_COLLAPSE, - }) - ) + }); + return issue ? { org, issue } : null; + }) ) ) ); - const successes: StrictResolvedIssue[] = []; - for (let i = 0; i < results.length; i++) { - const result = results[i]; - const org = orgSlugs[i]; - if (result && org && result.ok && result.value) { - successes.push({ org, issue: result.value }); - } - } - // If every org failed with a real error (403, 5xx, network timeout), // surface it instead of falling through to a misleading "not found". // Only throw when ALL results are errors — if some orgs returned clean @@ -376,7 +368,9 @@ async function findIssuesByShortId( } } - return successes; + return results.flatMap((result) => + result.ok && result.value ? [result.value] : [] + ); } /** From ff7c8e6896cc44e3b4b803810ba7373281c41d9b Mon Sep 17 00:00:00 2001 From: betegon Date: Tue, 6 Oct 2026 10:30:59 +0200 Subject: [PATCH 4/4] chore: drop unrelated merge-hook formatting Restore the MCP client test exactly to main. Skip the formatting hook for this restoration so it does not reintroduce changes outside the CLI fix. --- packages/mcp-core/src/api-client/client.test.ts | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/packages/mcp-core/src/api-client/client.test.ts b/packages/mcp-core/src/api-client/client.test.ts index 973d82fa2..3587bc0d2 100644 --- a/packages/mcp-core/src/api-client/client.test.ts +++ b/packages/mcp-core/src/api-client/client.test.ts @@ -44,9 +44,7 @@ describe("API bearer token validation", () => { accessToken: "valid\nsecret", }); - const error = await api - .listOrganizations() - .catch((cause: unknown) => cause); + const error = await api.listOrganizations().catch((cause: unknown) => cause); expect(error).toBeInstanceOf(ConfigurationError); expect(String(error)).toContain("Malformed authentication token"); expect(String(error)).not.toContain("valid\nsecret"); @@ -56,9 +54,7 @@ describe("API bearer token validation", () => { host: "sentry.example.com", accessToken: "", }); - await expect(emptyTokenApi.listOrganizations()).rejects.toThrow( - ConfigurationError, - ); + await expect(emptyTokenApi.listOrganizations()).rejects.toThrow(ConfigurationError); expect(requests).toBe(0); }); });