Skip to content

fix: show human-friendly names in trial list and surface plan trials#412

Merged
BYK merged 11 commits intomainfrom
fix/trial-list-friendly-names
Mar 12, 2026
Merged

fix: show human-friendly names in trial list and surface plan trials#412
BYK merged 11 commits intomainfrom
fix/trial-list-friendly-names

Conversation

@BYK
Copy link
Copy Markdown
Member

@BYK BYK commented Mar 12, 2026

Summary

Improves the sentry trial list and sentry trial start commands with human-friendly names, plan trial visibility, deduplication, and better error messages.

Changes

Human-friendly trial names

  • Added mappings for monitorSeats → "Cron Monitors", uptime → "Uptime Monitoring"
  • Added profileDurationUI to existing profiling mapping
  • Added humanizeCategory() fallback that converts unknown camelCase categories to "Title Case"
  • Added kebabize() fallback for CLI-friendly names

Plan trial surfacing

  • New getCustomerTrialInfo() API function returns plan trial data (canTrial, isTrial, trialEnd, planDetails)
  • Plan-level trials (e.g., "Developer -> Business") now appear in trial list with status "Available" or "Active"
  • Shows hint: Tip: Use 'sentry trial start plan' to start a Business plan trial

sentry trial start plan

  • New "plan" pseudo-trial name that opens the org's billing page
  • Shows billing URL, QR code, and optional browser prompt (TTY-aware)
  • Checks eligibility via canTrial/isTrial before prompting
  • Respects --json mode

Simplified table format

  • Merged NAME + PRODUCT into single "TRIAL" column with CLI name in parentheses: Profiling (profiling)
  • Dropped CATEGORY column from human output (kept in --json)
  • Plan trial row: Developer -> Business (plan) | ○ Available | —

Deduplication

  • API returns separate entries for profileDuration and profileDurationUI, both mapping to CLI name "profiling"
  • deduplicateTrials() groups by CLI name, keeps best entry (active > available > expired, latest endDate wins)

Better error messages

  • ContextError now shows usage with placeholder: sentry trial list <org> instead of bare sentry trial list
  • Default alternatives (DSN detection, SENTRY_ORG env var) shown instead of being overridden

Test coverage

89 tests passing across 3 files (154 assertions):

  • test/lib/trials.test.ts — unit tests for name mappings, humanization, kebabization
  • test/commands/trial/list.test.ts — plan trial entries, deduplication, table formatting
  • test/commands/trial/start.test.ts — plan trial flow, eligibility checks, JSON mode

Related

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Mar 12, 2026

Semver Impact of This PR

🟢 Patch (bug fixes)

📋 Changelog Preview

This is how your changes will appear in the changelog.
Entries from this PR are highlighted with a left border (blockquote style).


New Features ✨

Init

  • Add --team flag to relay team selection to project creation by MathurAditya724 in #403
  • Enforce canonical feature display order by betegon in #388
  • Accept multiple delimiter formats for --features flag by betegon in #386
  • Add git safety checks before wizard modifies files by betegon in #379
  • Add experimental warning before wizard runs by betegon in #378
  • Add init command for guided Sentry project setup by betegon in #283

Issue List

  • Auto-compact when table exceeds terminal height by BYK in #395
  • Redesign table to match Sentry web UI by BYK in #372

Other

  • (trial) Auto-prompt for Seer trial + sentry trial list/start commands by BYK in #399
  • Support SENTRY_HOST as alias for SENTRY_URL by betegon in #409
  • Add --dry-run flag to mutating commands by BYK in #387
  • Return-based output with OutputConfig on buildCommand by BYK in #380
  • Add --fields flag for context-window-friendly JSON output by BYK in #373
  • Magic @ selectors (@latest, @most_frequent) for issue commands by BYK in #371
  • Input hardening against agent hallucinations by BYK in #370
  • Add response caching for read-only API calls by BYK in #330

Bug Fixes 🐛

Init

  • Remove implementation detail from help text by betegon in #385
  • Truncate uncommitted file list to first 5 entries by MathurAditya724 in #381

Other

  • (api) Convert --data to query params for GET requests by BYK in #383
  • (docs) Remove double borders and fix column alignment on landing page tables by betegon in #369
  • Show human-friendly names in trial list and surface plan trials by BYK in #412
  • Add trace ID validation to trace view + UUID dash-stripping by BYK in #375

Internal Changes 🔧

Init

  • Remove --force flag by betegon in #377
  • Remove dead determine-pm step label by betegon in #374

Other

  • (log/list) Convert non-follow paths to return CommandOutput by BYK in #410
  • Convert list command handlers to return data instead of writing stdout by BYK in #404
  • Split api-client.ts into focused domain modules by BYK in #405
  • Migrate non-streaming commands to CommandOutput with markdown rendering by BYK in #398
  • Convert Tier 2-3 commands to return-based output and consola by BYK in #394
  • Convert remaining Tier 1 commands to return-based output by BYK in #382
  • Converge Tier 1 commands to writeOutput helper by BYK in #376

Other

  • Minify JSON on read and pretty-print on write in init local ops by MathurAditya724 in #396

🤖 This preview updates automatically when you update the PR.

BYK added 8 commits March 12, 2026 19:55
Three issues fixed:

1. Missing category mappings: API categories like monitorSeats, uptime,
   and profileDurationUI were not in the TRIAL_NAMES map, so they showed
   raw camelCase API names in both the NAME and PRODUCT columns.
   Added mappings for monitors, uptime, and profileDurationUI → profiling.

2. Poor fallback for unknown categories: When an API returns a category
   not in the map, getTrialDisplayName now uses humanizeCategory() to
   convert camelCase to title case (e.g., 'fooBar' → 'Foo Bar') and
   getTrialFriendlyName uses kebab-case (e.g., 'fooBar' → 'foo-bar')
   instead of showing the raw API string.

3. Plan-level trials not surfaced: Organizations on free/Developer plans
   with canTrial=true (eligible for a Business plan trial) saw 'No trials
   found' because the CLI only showed product trials. Now fetches full
   customer trial info via getCustomerTrialInfo() and synthesizes a 'plan'
   entry when canTrial or isTrial is true, with a hint linking to the
   billing page.
The human table now shows one 'TRIAL' column with the display name
instead of three redundant columns (NAME, PRODUCT, CATEGORY). The
name and category fields are still available in --json output for
scripting.
Product trials now show 'Profiling (profiling)' so users know the
exact argument for 'sentry trial start <name>'. Plan trial entries
skip the parenthetical since they aren't startable via CLI.
When users run 'sentry trial start plan', the CLI:
1. Checks canTrial/isTrial eligibility via the customer API
2. Shows the billing URL and a QR code (for mobile/remote)
3. Prompts to open the browser (if interactive TTY)
4. Returns JSON with url/opened fields in --json mode

This fills the gap where plan-level trials have no API endpoint
and must be activated through the Sentry billing UI.
Multiple API categories can map to one trial name (e.g., both
profileDuration and profileDurationUI → profiling). Without
deduplication, the table showed duplicate rows.

The deduplicateTrials() function groups by CLI name and keeps the
best entry: active > available > expired, with latest end date
as tiebreaker.
- Replace → with -> in the TRIAL column to avoid multi-byte
  rendering issues where the arrow eats into column padding
- Show (plan) in parentheses like product trials so users learn
  the sentry trial start <name> argument
- Change hint from billing URL to 'sentry trial start plan'
Pass the usage example with placeholder as the command arg
(e.g., 'sentry trial list <org>') instead of the bare command.
Use default alternatives (DSN detection, SENTRY_ORG env var)
instead of overriding with just the positional syntax.

Before:
  Organization is required.
  Specify it using:
    sentry trial list
  Or:
    - sentry trial list <org>

After:
  Organization is required.
  Specify it using:
    sentry trial list <org>
  Or:
    - Run from a directory with a Sentry-configured project
    - Set SENTRY_ORG and SENTRY_PROJECT (or SENTRY_DSN) environment variables
- Fix swap detection for "plan" pseudo-trial: `sentry trial start my-org plan`
  now correctly auto-corrects to `sentry trial start plan my-org` instead of
  giving a confusing "Unknown trial name" error
- Deduplicate getProductTrials to delegate to getCustomerTrialInfo instead of
  making its own identical API call
- Add test for plan argument swap detection
@BYK BYK force-pushed the fix/trial-list-friendly-names branch from 7d1263b to 7655417 Compare March 12, 2026 19:59
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Mar 12, 2026

Codecov Results 📊

104 passed | Total: 104 | Pass Rate: 100% | Execution Time: 0ms

📊 Comparison with Base Branch

Metric Change
Total Tests
Passed Tests
Failed Tests
Skipped Tests

✨ No test changes detected

All tests are passing successfully.

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

Coverage diff
@@            Coverage Diff             @@
##          main       #PR       +/-##
==========================================
+ Coverage    96.66%    96.69%    +0.03%
==========================================
  Files          159       159         —
  Lines        20855     21011      +156
  Branches         0         0         —
==========================================
+ Hits         20158     20315      +157
- Misses         697       696        -1
- Partials         0         0         —

Generated by Codecov Action

- Use `info.canTrial === false` instead of `!info.canTrial` so undefined
  (API omitted the field) does not incorrectly block plan trial activation
- Extract daysRemainingFromDate() shared helper in trials.ts, reuse in
  both getDaysRemaining() and buildPlanTrialEntry() to eliminate duplicate
  end-of-day UTC date math
Copy link
Copy Markdown

@cursor cursor bot left a comment

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.

…cy with list.ts

Both commands now treat undefined canTrial conservatively: list.ts does
not show a plan trial row, start.ts rejects the attempt. This avoids
user confusion where "sentry trial start plan" succeeds but
"sentry trial list" shows no plan trial option.
@BYK BYK merged commit 84d2812 into main Mar 12, 2026
22 checks passed
@BYK BYK deleted the fix/trial-list-friendly-names branch March 12, 2026 21:14
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