Skip to content

feat(cli): add sentry cli defaults command for persistent settings#721

Merged
BYK merged 1 commit intomainfrom
feat/cli-defaults
Apr 13, 2026
Merged

feat(cli): add sentry cli defaults command for persistent settings#721
BYK merged 1 commit intomainfrom
feat/cli-defaults

Conversation

@BYK
Copy link
Copy Markdown
Member

@BYK BYK commented Apr 13, 2026

Summary

Implements sentry cli defaults — a command for viewing and managing persistent CLI defaults. Closes #304.

  • Show defaults: sentry cli defaults displays all current settings
  • Set defaults: sentry cli defaults org my-org, sentry cli defaults telemetry off, etc.
  • Clear specific: sentry cli defaults org --clear
  • Clear all: sentry cli defaults --clear --yes

Supported keys: org, project, telemetry (on/off/yes/no/true/false/1/0), url (for self-hosted).

Storage consolidation

The defaults single-row table was never written by production code. This PR:

  • Migrates all defaults to the metadata KV table (keys: defaults.org, defaults.project, defaults.telemetry, defaults.url)
  • Adds schema migration 13 that copies any existing data and drops the table
  • Updates the JSON migration to write to metadata instead of defaults

Public getters (getDefaultOrganization(), getDefaultProject()) keep the same signatures — all consumers work unchanged.

Telemetry preference

Adds persistent telemetry opt-out with a 4-level priority chain:

  1. SENTRY_CLI_NO_TELEMETRY=1 env var (highest)
  2. DO_NOT_TRACK=1 env var (consoledonottrack.com)
  3. SQLite persistent preference via sentry cli defaults telemetry off
  4. Default: enabled

URL default

Adds persistent URL default for self-hosted instances, applied in preloadProjectContext() after .sentryclirc env shim using the same env.SENTRY_URL mechanism.

New utility

parseBoolValue() in src/lib/parse-bool.ts — human-friendly boolean parser adapted from Sentry JS SDK's envToBool. Handles on/off, yes/no, true/false, 1/0, t/f, y/n.

Tests

  • Property-based tests for parseBoolValue (8 properties, 50 runs each)
  • Unit tests for defaults storage layer and isTelemetryEnabled() priority chain (26 tests)
  • Updated 4 existing test files that used the removed setDefaults() function

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 13, 2026

Semver Impact of This PR

🟡 Minor (new features)

📋 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 ✨

  • (cli) Add sentry cli defaults command for persistent settings by BYK in #721

Bug Fixes 🐛

Upgrade

  • Detect npm install method from node_modules path by BYK in #723
  • Add shell option on Windows for .cmd package managers by BYK in #722

Other

  • (dashboard) Remove overly restrictive dataset-display cross-validation by BYK in #720
  • (init) Remove JSON minification that breaks edit-based codemods by betegon in #719
  • (issue) Support share issue URLs by BYK in #718

Internal Changes 🔧

  • Regenerate skill files by github-actions[bot] in ca16b2ff

🤖 This preview updates automatically when you update the PR.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 13, 2026

PR Preview Action v1.8.1

QR code for preview link

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

Built to branch gh-pages at 2026-04-13 12:25 UTC.
Preview will be ready when the GitHub Pages deployment is complete.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 13, 2026

Codecov Results 📊

134 passed | Total: 134 | 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 99.25%. Project has 1590 uncovered lines.
✅ Project coverage is 95.35%. Comparing base (base) to head (head).

Files with missing lines (1)
File Patch % Lines
src/lib/db/defaults.ts 97.40% ⚠️ 2 Missing
Coverage diff
@@            Coverage Diff             @@
##          main       #PR       +/-##
==========================================
+ Coverage    95.30%    95.35%    +0.05%
==========================================
  Files          232       234        +2
  Lines        33993     34208      +215
  Branches         0         0         —
==========================================
+ Hits         32395     32618      +223
- Misses        1598      1590        -8
- Partials         0         0         —

Generated by Codecov Action

Comment thread src/commands/cli/defaults.ts Outdated
* Used for display in show mode to help users understand when env vars
* override their stored preference.
*/
function computeTelemetryEffective(): DefaultsResult["telemetryEffective"] {
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Shouldn't this live in a generic helper library for Sentry.init() system to use? I'm also concerned about how we track auto-completions. I'm assuming they'd still honor this and drop the temp entries from the DB without sending them?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

isTelemetryEnabled() already lives in src/lib/telemetry.ts (the generic helper) which withTelemetry() calls. computeTelemetryEffective() stays in the command file because it is display-only — it computes the source string for the human formatter, not just the boolean.

Re completions: they honor this correctly. The completion fast-path sets SENTRY_CLI_NO_TELEMETRY=1 (highest priority in isTelemetryEnabled()). Deferred queue entries are only drained when enabled=true in withTelemetry(), so if the persistent preference is off, queued entries are never sent.

Comment thread src/commands/cli/defaults.ts Outdated
/**
* Read the current value of a single default for display or change tracking.
*/
function getCurrentValue(key: DefaultKey): string | boolean | null {
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I feel like a map of key to handlers would be easier to maintain compared to a big switch statement?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Done — replaced all three switch functions (getCurrentValue, setDefault, clearDefault) with a single DEFAULTS_REGISTRY: Record<DefaultKey, DefaultHandler> map. Each key maps to { get, set, clear } handlers. The command dispatch just does handler.get() / handler.set(value) / handler.clear().

Comment thread src/commands/cli/defaults.ts Outdated
type DefaultKey = "organization" | "project" | "telemetry" | "url";

/** Map user-facing key names to canonical DefaultsState keys */
function normalizeKey(key: string): DefaultKey | null {
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Should we instead have a global ALIASES const was a map org -> organization and just use key.toLowerCase() and that map instead of a switch?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Done — replaced with a KEY_ALIASES: Record<string, DefaultKey> map. normalizeKey() is now a one-liner: KEY_ALIASES[key.toLowerCase()] ?? null.

Comment thread src/commands/cli/defaults.ts Outdated
*/
function computeTelemetryEffective(): DefaultsResult["telemetryEffective"] {
const env = getEnv();
if (env.SENTRY_CLI_NO_TELEMETRY === "1") {
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

These ENV variable names should probably be in some constant?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Done — extracted TELEMETRY_ENV_VAR and DO_NOT_TRACK_ENV_VAR as exported constants in src/lib/telemetry.ts. Used in both isTelemetryEnabled() and computeTelemetryEffective(). The formatter also simplified to just check source.startsWith("env:") and slice the env var name.

Comment thread src/commands/cli/defaults.ts Outdated
/**
* Set a default value. Validates and stores the value.
*/
function setDefault(key: DefaultKey, value: string): void {
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Same as above: name -> handler pattern rather than a switch?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Done — same DEFAULTS_REGISTRY handler map covers this too. See reply on the other handler map thread.

@BYK BYK force-pushed the feat/cli-defaults branch 3 times, most recently from 9357c90 to 9993366 Compare April 13, 2026 11:52
@BYK BYK marked this pull request as ready for review April 13, 2026 12:06
Comment thread src/commands/cli/defaults.ts
@BYK BYK force-pushed the feat/cli-defaults branch from 9993366 to d934972 Compare April 13, 2026 12:16
Copy link
Copy Markdown
Contributor

@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.

Reviewed by Cursor Bugbot for commit d934972. Configure here.

Comment thread src/lib/formatters/human.ts Outdated
Implement a command to view and manage persistent CLI defaults: organization,
project, telemetry preference, and Sentry URL (for self-hosted instances).

- Consolidate storage from the unused `defaults` single-row table to the
  `metadata` KV table (migration 13 copies any data, then drops the table)
- Add `parseBoolValue()` utility for human-friendly boolean parsing (on/off,
  yes/no, true/false, 1/0) adapted from Sentry JS SDK's `envToBool`
- Add persistent telemetry opt-out with priority chain:
  SENTRY_CLI_NO_TELEMETRY > DO_NOT_TRACK > SQLite preference > default (on)
- Add persistent URL default applied in `preloadProjectContext()` after
  `.sentryclirc` env shim, using the same `env.SENTRY_URL` mechanism
- Property-based tests for parseBoolValue, unit tests for defaults storage
  and isTelemetryEnabled priority chain

Closes #304
@BYK BYK force-pushed the feat/cli-defaults branch from d934972 to 4ff6ef8 Compare April 13, 2026 12:25
@BYK BYK merged commit 1163dac into main Apr 13, 2026
26 checks passed
@BYK BYK deleted the feat/cli-defaults branch April 13, 2026 13:26
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.

feat: support setting and using a default organization

1 participant