feat: add send-event and send-envelope commands with DSN auth#921
Open
feat: add send-event and send-envelope commands with DSN auth#921
Conversation
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
Contributor
|
Contributor
Codecov Results 📊✅ 6737 passed | Total: 6737 | Pass Rate: 100% | Execution Time: 0ms 📊 Comparison with Base Branch
All tests are passing successfully. ✅ Patch coverage is 82.02%. Project has 13593 uncovered lines. Files with missing lines (4)
Coverage diff@@ Coverage Diff @@
## main #PR +/-##
==========================================
+ Coverage 76.67% 76.75% +0.08%
==========================================
Files 303 308 +5
Lines 57977 58473 +496
Branches 0 0 —
==========================================
+ Hits 44454 44880 +426
- Misses 13523 13593 +70
- Partials 0 0 —Generated by Codecov Action |
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)
- 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)
Member
Author
|
Fixed all 6 bot findings in 7e33546:
|
- 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
…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.
…atch Mirrors the file-based path's error handling — catches any internal SDK errors and re-throws as ValidationError.
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.
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'.
Contributor
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit b6f5bab. Configure here.
…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)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Summary
Implements
sentry send eventandsentry send envelopefor old sentry-cli parity. Ref #600.These are the first commands in the new CLI that authenticate via a DSN (not a Bearer token), so no
sentry auth loginis needed — provide a DSN from--dsn,SENTRY_DSNenv var, or auto-detection.Command structure
sentry send eventSend a Sentry event from CLI flags or a JSON file:
Flags match the old sentry-cli:
-m/--message,-l/--level,-r/--release,-E/--env,-t/--tag(variadic),-e/--extra(variadic),-u/--user(variadic, routes id/email/username/ip_address to known User fields, rest touser.data),-f/--fingerprint(variadic),--dist,--platform,--timestamp,--no-environ,--raw,--dsn.sentry send envelopeSend a pre-built Sentry envelope file:
Architecture
src/commands/send/index.ts— route groupsrc/lib/envelope/transport.ts— shared DSN-based sender using@sentry/core(makeDsn,getEnvelopeEndpointWithUrlEncodedAuth,serializeEnvelope) — no new dependenciessrc/lib/envelope/event-builder.ts— builds a SentryEventfrom CLI flagsauth: "dsn"onbuildCommand— new option that skips Bearer token guard and.sentryclircURL trust check, distinct fromauth: falseTests
48 new tests across 4 files, written TDD-first before implementation.