Skip to content

fix: restore Sentry release tag from spawned telemetry worker#3801

Open
eablack wants to merge 3 commits into
mainfrom
eb/sentry-release-tag-in-worker
Open

fix: restore Sentry release tag from spawned telemetry worker#3801
eablack wants to merge 3 commits into
mainfrom
eb/sentry-release-tag-in-worker

Conversation

@eablack

@eablack eablack commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Summary

Since the background-worker refactor in v11.2.0 (c13074da5), every Sentry event captured by the CLI is tagged release: unknown. The version cached via setVersion in telemetry-utils.ts lives in module-level state in the main process; the telemetry worker runs in a separate spawned Node process, so getVersion() returns 'unknown' when SentryClient.ensureInitialized calls Sentry.init({ release }).

Confirmed in the heroku-mk/cli Sentry project — no release tag exists for any 11.1.x → 11.8.0 build; unknown (4.27M events) is the only bucket still receiving events.

The fix wraps every worker payload in a WorkerEnvelope ({ cliVersion, payload }) — the sole contract between serializeTelemetryData and the worker entrypoint. The worker's readWorkerEnvelope helper restores the version via setVersion before any client initialization runs. No optional fields, no runtime shape checks.

Type of Change

Patch Updates (patch semver update)

  • fix: Bug fix

Testing

Notes:
The OTEL/Honeycomb path is unchanged. The only behavioral effect on OTEL is that the tracer version string (tracer('heroku-cli', getVersion())) will now be the actual CLI version instead of 'unknown' — a correction rather than a break.

Steps:

  1. Build the CLI locally (npm run build).
  2. Run any command that raises a non-user error (e.g. a command that triggers an uncaught exception).
  3. Confirm the resulting event in Sentry carries the current CLI version in its release tag instead of unknown.
  4. Passing CI (unit tests include round-trip coverage for the envelope).

Screenshots (if applicable)

Related Issues

GitHub issue: #N/A
GUS work item: W-23296430

The CLI version is stored in a module-level variable in the main
process and read back by SentryClient.ensureInitialized when the
worker calls Sentry.init. Since the worker runs in a separate Node
process spawned via spawnTelemetryWorker, that module state does
not carry across — getVersion() returns 'unknown' and every event
from CLI >= 11.2.0 has release=unknown in Sentry.

Wrap every worker payload in a WorkerEnvelope so the version rides
across the process boundary, and re-hydrate it before any client
initialization.

W-23296430
@eablack eablack requested a review from a team as a code owner July 2, 2026 21:36
@eablack eablack temporarily deployed to AcceptanceTests July 2, 2026 21:36 — with GitHub Actions Inactive
@eablack eablack temporarily deployed to AcceptanceTests July 2, 2026 21:36 — with GitHub Actions Inactive
@eablack eablack temporarily deployed to AcceptanceTests July 2, 2026 21:36 — with GitHub Actions Inactive
@eablack eablack temporarily deployed to AcceptanceTests July 2, 2026 21:36 — with GitHub Actions Inactive
@eablack eablack temporarily deployed to AcceptanceTests July 2, 2026 21:37 — with GitHub Actions Inactive
@eablack eablack temporarily deployed to AcceptanceTests July 2, 2026 21:37 — with GitHub Actions Inactive
@eablack eablack temporarily deployed to AcceptanceTests July 2, 2026 21:37 — with GitHub Actions Inactive
@eablack eablack temporarily deployed to AcceptanceTests July 2, 2026 21:37 — with GitHub Actions Inactive
- Make parseWorkerEnvelope pure. It now returns {cliVersion, payload}
  and the worker calls setVersion explicitly at the top of the stdin
  handler, so the ordering "hydrate before any client init" is visible
  at the call site instead of hidden inside a read-shaped helper.

- Discriminate non-Error variants of WorkerData exhaustively in
  serializeTelemetryData. Adding a new variant now produces a compile
  error at the serializer instead of falling through the else branch.

- Narrow RecordOpts.Command from oclif's Command.Class to
  HerokulyticsData['Command']. The producer in the prerun hook and the
  worker both build exactly this shape; the wider type was hiding the
  divergence risk that made the double-cast in the worker necessary.
  Cast removed.

W-23296430
@eablack eablack temporarily deployed to AcceptanceTests July 2, 2026 22:33 — with GitHub Actions Inactive
@eablack eablack temporarily deployed to AcceptanceTests July 2, 2026 22:33 — with GitHub Actions Inactive
@eablack eablack temporarily deployed to AcceptanceTests July 2, 2026 22:33 — with GitHub Actions Inactive
@eablack eablack temporarily deployed to AcceptanceTests July 2, 2026 22:33 — with GitHub Actions Inactive
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