Skip to content

feat: add send-event and send-envelope commands with DSN auth#921

Open
BYK wants to merge 16 commits intomainfrom
feat/send-event-envelope
Open

feat: add send-event and send-envelope commands with DSN auth#921
BYK wants to merge 16 commits intomainfrom
feat/send-event-envelope

Conversation

@BYK
Copy link
Copy Markdown
Member

@BYK BYK commented May 5, 2026

Summary

Implements sentry event send for old sentry-cli parity. Ref #600.

This is the first command in the new CLI that authenticates via a DSN (not a Bearer token), so no sentry auth login is needed — provide a DSN from --dsn, SENTRY_DSN env var, or auto-detection.

Command structure

sentry event send       ← canonical (under the event group)

sentry send-event       ← hidden backward-compat alias
sentry send-envelope    ← hidden deprecation shim → suggests event send --raw

sentry event send

Send a Sentry event from CLI flags or a JSON file:

# From flags
sentry event send -m "Something went wrong" -l error --tag env:prod

# From JSON file
sentry event send ./event.json

# Raw mode (send bytes as-is — also supports pre-built envelopes)
sentry event send --raw ./captured.envelope

Supports all flags from old sentry-cli send-event: --message, --level, --release, --env, --tag, --extra, --user, --fingerprint, --timestamp, --dist, --platform, --no-environ.

Design decisions

  • event send under the event group — follows the mutation pattern (project create, issue resolve, release create). Discoverable via sentry event --help.
  • send-envelope deprecated — envelopes are a low-level concept; the --raw flag on event send covers the use case. Running sentry send-envelope now throws with a clear message suggesting sentry event send --raw <file>.
  • DSN authauth: "dsn" on buildCommand skips the token guard entirely. DSN is resolved from --dsn flag or SENTRY_DSN env var.

Shared infrastructure

  • src/lib/envelope/transport.tsrequireDsn(), buildEnvelopeUrl(), sendEnvelopeRequest(), readFileBytes()
  • src/lib/envelope/event-builder.tsbuildEventFromFlags() constructs a Sentry Event from CLI flags
  • Uses @sentry/core for envelope creation/serialization and DSN parsing

Implements sentry send-event and sentry send-envelope — the first
commands that authenticate via a DSN (not a Bearer token), matching
the old sentry-cli behaviour.

Architecture:
- src/lib/envelope/transport.ts: shared DSN-based envelope sender
  using @sentry/core (makeDsn, getEnvelopeEndpointWithUrlEncodedAuth,
  serializeEnvelope) — no new dependencies
- src/lib/envelope/event-builder.ts: builds a Sentry Event from CLI
  flags (message, level, tags, extras, user, fingerprint, etc.)
- auth: 'dsn' in buildCommand: skips Bearer token guard and RC URL
  check for DSN-only commands

send-event flags (matching old CLI):
  --dsn, -m/--message, -l/--level, -r/--release, -E/--env,
  -t/--tag (variadic), -e/--extra (variadic), -u/--user (variadic),
  -f/--fingerprint (variadic), --dist, --platform, --timestamp,
  --no-environ, --raw

send-envelope flags:
  --dsn, --raw (send bytes without parsing)

Tests: 48 new tests across 4 files (TDD — tests written first)
  - transport: URL construction, auth params, error handling
  - event-builder: parseKeyValue, parseUserFields, buildEventFromFlags
  - send-event command: inline, file, JSON output, missing DSN
  - send-envelope command: valid file, raw mode, invalid envelope,
    multiple files, missing DSN
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 5, 2026

PR Preview Action v1.8.1

QR code for preview link

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

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

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 5, 2026

Codecov Results 📊

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

📊 Comparison with Base Branch

Metric Change
Total Tests 📈 +51
Passed Tests 📈 +51
Failed Tests
Skipped Tests

All tests are passing successfully.

✅ Patch coverage is 82.00%. Project has 13592 uncovered lines.
✅ Project coverage is 76.74%. Comparing base (base) to head (head).

Files with missing lines (4)
File Patch % Lines
src/commands/event/send.ts 78.19% ⚠️ 53 Missing
src/lib/envelope/event-builder.ts 78.48% ⚠️ 17 Missing
src/lib/envelope/transport.ts 85.14% ⚠️ 11 Missing
src/commands/send-envelope.ts 96.00% ⚠️ 2 Missing
Coverage diff
@@            Coverage Diff             @@
##          main       #PR       +/-##
==========================================
+ Coverage    76.67%    76.74%    +0.07%
==========================================
  Files          303       308        +5
  Lines        57997     58431      +434
  Branches         0         0         —
==========================================
+ Hits         44463     44839      +376
- Misses       13534     13592       +58
- Partials         0         0         —

Generated by Codecov Action

Comment thread src/lib/envelope/event-builder.ts
Comment thread src/commands/send-event.ts Outdated
Comment thread src/commands/send-envelope.ts Outdated
sentry send event  -- canonical new interface
sentry send envelope

sentry send-event    -- hidden bw-compat alias (old sentry-cli)
sentry send-envelope -- hidden bw-compat alias (old sentry-cli)
Comment thread src/lib/envelope/event-builder.ts
Comment thread src/commands/send-event.ts Outdated
Comment thread src/lib/envelope/event-builder.ts
Comment thread src/commands/send-envelope.ts Outdated
Comment thread src/commands/send-event.ts Outdated
- parseTimestamp now throws ValidationError on invalid input instead of
  silently falling back to Date.now() (Seer/Cursor)
- Environ spread order fixed: process.env goes first so user --extra
  environ:val correctly overrides it (Cursor)
- Raw mode no longer reads file twice: decode bytes in-memory instead
  of re-reading (Cursor)
- Fixed --raw help text: sends raw bytes directly, not 'inside an envelope'
  (Sentry)
- send-envelope now errors when no files provided (Sentry)
- send-event --raw in inline mode now throws ValidationError (Sentry)
@BYK
Copy link
Copy Markdown
Member Author

BYK commented May 5, 2026

Fixed all 6 bot findings in 7e33546:

  • Invalid --timestamp now throws ValidationError (Cursor/Seer)
  • environ spread order fixed so user --extra environ:val is not overwritten (Cursor)
  • Raw mode decodes bytes in-memory instead of re-reading file (Cursor)
  • --raw help text corrected (Sentry)
  • send-envelope now errors when no files provided (Sentry)
  • send-event --raw in inline mode now throws ValidationError (Sentry)

Comment thread src/commands/send-event.ts Outdated
Comment thread src/lib/envelope/event-builder.ts
BYK added 2 commits May 5, 2026 17:30
- Remove undocumented DSN auto-detection claim from send-event.ts
  module comment and requireDsn error message (only --dsn and
  SENTRY_DSN are actually supported)
- Use Number.isFinite instead of !Number.isNaN to reject Infinity
  and -Infinity as timestamp values
- parseTimestamp: remove && num > 0 guard — epoch-0 and negative
  timestamps are valid; the old guard silently corrupted them to
  year 2000 / year 3600 via Date.parse fallthrough
- resolveDsn: trim whitespace from --dsn flag and SENTRY_DSN env var
  (leading space / trailing newline from shell caused confusing error)
- transport test: use .toThrow(ValidationError) not bare .toThrow()
- send.md: remove false claim that DSN auto-detects from project files
- buildFilePayload + send-envelope: wrap Bun.file reads in try/catch,
  surface ENOENT and parse errors as ValidationError not raw stacks
- Document that --message is ignored when file args are provided
- Add tests: ENOENT → ValidationError, --raw without file → error,
  no files for send-envelope → ValidationError, DSN whitespace trim,
  whitespace trim for SENTRY_DSN env var
Comment thread src/commands/send-event.ts Outdated
Comment thread src/commands/send-event.ts Outdated
Comment thread src/commands/send-envelope.ts Outdated
…eation in try/catch

- Centralise ENOENT/IO error handling into shared readFileBytes() in transport.ts
- Removes duplicated file-reading error block from both send-event.ts and send-envelope.ts
- Wrap makeDsn() call in try/catch to guard against future SDK internal throws
- Wrap createEventEnvelope()+serializeEnvelope() in try/catch with descriptive ValidationError

Addresses Sentry Seer findings (medium) and Cursor Bugbot finding (low) on PR #921.
Comment thread src/commands/send-event.ts Outdated
…atch

Mirrors the file-based path's error handling — catches any internal
SDK errors and re-throws as ValidationError.
Comment thread src/commands/send-envelope.ts Outdated
Calling buildEnvelopeUrl(dsn) before the file read loop ensures
invalid DSNs are caught upfront rather than after unnecessary I/O,
consistent with send-event's behavior.
Comment thread src/lib/envelope/transport.ts
getEnvelopeEndpointWithUrlEncodedAuth appends /<version> internally,
so passing 'sentry-cli/dev' produced the malformed identifier
sentry_client=sentry-cli/dev/dev on every envelope request.

Now passes bare name 'sentry-cli' and lets the SDK append '/dev'.
Comment thread src/lib/envelope/transport.ts Outdated
Comment thread src/lib/envelope/transport.ts Outdated
BYK added 2 commits May 5, 2026 19:15
…r message

- makeDsn may throw SentryError internally; wrap in try/catch for safety
- requireDsn error message now uses canonical 'sentry send event' instead
  of hardcoded 'sentry send-event' (wrong for send-envelope callers)
- Canonical command is now 'sentry event send' under the event route
- send-envelope is now a deprecation shim suggesting 'sentry event send --raw'
- send-event remains as a hidden backward-compat alias
- Removed the 'send' route group entirely
- Updated docs, tests, and all references
Comment thread src/commands/event/send.ts
Comment thread src/lib/envelope/transport.ts
Comment thread src/lib/envelope/transport.ts
Comment thread src/lib/envelope/transport.ts
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 9f45678. Configure here.

Comment thread test/lib/command-suggestions.test.ts Outdated
Comment thread src/commands/send-envelope.ts
Prevents HostScopeError from masking the deprecation message when a
.sentryclirc file is present.
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