Skip to content

feat(issue): default to recommended sort on Sentry SaaS#1123

Merged
BYK merged 4 commits into
mainfrom
byk/feat/issue-list-recommended-sort
Jun 23, 2026
Merged

feat(issue): default to recommended sort on Sentry SaaS#1123
BYK merged 4 commits into
mainfrom
byk/feat/issue-list-recommended-sort

Conversation

@BYK

@BYK BYK commented Jun 22, 2026

Copy link
Copy Markdown
Member

Summary

sentry issue list now defaults to the server-side recommended relevance sort on Sentry SaaS (sentry.io), falling back to date on self-hosted instances.

Why SaaS-only

recommended was added to the issue search API on 2026-04-06. The backend raises InvalidSearchQueryHTTP 400 (Sort key '...' not supported) for instances that lack the sort strategy (sentry/src/sentry/search/snuba/backend.py). Since the CLI supports self-hosted Sentry, an unconditional default would break issue list on older instances — so self-hosted keeps date. If a user explicitly runs --sort recommended against an instance that doesn't support it, the resulting 400 is enriched with a sort-specific hint ("this instance does not support the 'recommended' sort; use --sort date") rather than the generic query/time-range suggestions. The organizations:issue-stream-recommended-sort feature flag is UI-exposure only (api_expose=True); it does not gate the API, so every SaaS org can use it today.

Implementation

  • src/lib/sentry-urls.ts — exported the existing private isSaaS() (routing/UX helper; JSDoc points to isSaaSTrustOrigin for trust decisions).
  • src/commands/issue/list.ts
    • Added recommended to SortValue / VALID_SORT_VALUES (so parseSort accepts it) and the ListFlags union.
    • New defaultIssueSort() = isSaaS() ? "recommended" : "date".
    • Stricli flag defaults are static, so --sort is now optional and the host-dependent default is resolved at runtime — shadow-resolved at the top of func() (new ListFlagsInput type) so all downstream code keeps a concrete flags.sort.
    • getComparator gains an explicit recommended case.
    • appendIssueFlags omits --sort when it equals the active default (defaultIssueSort() instead of hardcoded "date").
    • The merged-result client re-sort is gated behind isMultiProject so single-project / org-all responses preserve the server's order (fixes the Cursor Bugbot finding where recommended was clobbered by a lastSeen fallback).
    • 400 errors for an unsupported sort get a sort-specific hint (build400Detail).
  • No API-layer change — the @sentry/api SDK IssueSort type already includes recommended.

Known limitations (documented)

  • Multi-project merges: the recommended relevance score isn't in the issue payload, so when merging results from multiple separately-fetched projects, getComparator falls back to recency (lastSeen). This is identical to the previous date default, so it's not a regression. Single-project and org-all listings (the common case) are fully server-sorted by recommended.
  • Pagination cursor reset on upgrade: the pagination context key encodes sort, so on SaaS the default key changes daterecommended after upgrading. Any previously-stored cursor stack is silently orphaned and -c next/-c prev start fresh — self-healing, not corrupting.

Tests

  • list.test.ts:
    • End-to-end default wiring (org-all, --sort omitted): asserts the API receives sort: "recommended" on SaaS and sort: "date" on self-hosted — guards the actual feature (verified to fail if the default resolution is reverted).
    • Single-project order preservation: server-ordered recommended results aren't reordered by lastSeen (verified to fail without the isMultiProject guard).
    • defaultIssueSort (SaaS/self-hosted via env), getComparator("recommended"), parseSort("recommended"), appendIssueFlags default-omission, and build400Detail sort-hint cases.
  • list.property.test.ts: explicit recommended comparator case (property generators auto-cover it via VALID_SORT_VALUES).
  • Docs fragment + regenerated skill reference updated.

Verification

  • tsc --noEmit clean
  • Issue-list unit + property tests pass (76 in the two files); full CI green on prior revs
  • Biome clean; check:fragments passes

`sentry issue list` now defaults to the server-side `recommended`
relevance sort on Sentry SaaS (sentry.io), falling back to `date` on
self-hosted instances.

`recommended` was added to the issue search API on 2026-04-06 and the
backend returns HTTP 400 (`Sort key '...' not supported`) for instances
that lack it. Self-hosted therefore keeps `date` as the default; an
explicit `--sort recommended` there surfaces the API error as-is.

Because Stricli flag defaults are static, the `--sort` flag is now
optional and the host-dependent default is resolved at runtime via
`defaultIssueSort()` (= `isSaaS() ? "recommended" : "date"`), shadow-
resolved at the top of `func()` so all downstream code keeps a concrete
`flags.sort`.

Notes:
- No API-layer change: the @sentry/api SDK type already includes
  `recommended`.
- Multi-project merges can't reproduce the server-only recommended score,
  so `getComparator` falls back to recency (lastSeen) for the client-side
  merge. Single-project listings are fully server-sorted.

@cursor cursor Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

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

Fix All in Cursor

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

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

Comment thread src/commands/issue/list.ts
BYK added 2 commits June 22, 2026 17:39
Cursor Bugbot (high severity): after fetching with sort=recommended, the
merged result list was always re-sorted client-side with
getComparator(flags.sort). For `recommended` the comparator falls back to
lastSeen (the relevance score is not in the payload), so a typical
single-project `issue list` had its server-provided recommended ordering
silently replaced by a date ordering.

Only re-sort when merging results from multiple separately-fetched
projects, where a client comparator is genuinely required to interleave
them. Single-project and org-all responses are already ordered by the
server for the requested sort, so their order is now preserved.

Adds a regression test asserting a single-project recommended response
keeps the server order even when lastSeen would reorder it.
@github-actions

github-actions Bot commented Jun 22, 2026

Copy link
Copy Markdown
Contributor
PR Preview Action v1.8.1

QR code for preview link

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

Built to branch gh-pages at 2026-06-23 10:02 UTC.
Preview will be ready when the GitHub Pages deployment is complete.

@github-actions

github-actions Bot commented Jun 22, 2026

Copy link
Copy Markdown
Contributor

Codecov Results 📊

✅ Patch coverage is 100.00%. Project has 5052 uncovered lines.
✅ Project coverage is 81.25%. Comparing base (base) to head (head).

Files with missing lines (1)
File Patch % Lines
src/commands/issue/list.ts 100.00% ⚠️ 1 partials
Coverage diff
@@            Coverage Diff             @@
##          main       #PR       +/-##
==========================================
+ Coverage    81.24%    81.25%    +0.01%
==========================================
  Files          388       388         —
  Lines        26936     26947       +11
  Branches     17493     17508       +15
==========================================
+ Hits         21884     21895       +11
- Misses        5052      5052         —
- Partials      1825      1825         —

Generated by Codecov Action

Addresses self-review (adversarial subagent) findings:

- S1: add an end-to-end guard that, when --sort is omitted, the
  host-dependent default actually reaches the API (sort=recommended on
  SaaS, sort=date on self-hosted). All prior tests passed sort explicitly,
  so a regression dropping the `?? defaultIssueSort()` resolution would
  have gone uncaught. Verified the new tests fail when the resolution is
  reverted.

- S2: when the API rejects an unsupported sort with 400 "Sort key '<x>'
  not supported" (e.g. `--sort recommended` against an older self-hosted
  instance), emit a sort-specific hint ("use --sort date") instead of the
  generic query/time-range/access suggestions. Extracted the shared
  formatting into formatDetailWithSuggestions(); hoisted the matcher regex
  to module scope. Added build400Detail unit tests.

- N2: make the "explicit sentry.io URL" default test hermetic by clearing
  SENTRY_HOST (getConfiguredSentryUrl prefers it).
@BYK BYK merged commit 1589665 into main Jun 23, 2026
29 checks passed
@BYK BYK deleted the byk/feat/issue-list-recommended-sort branch June 23, 2026 10:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant