Skip to content

feat(cli): add release-independent event mode to symbol-sets upload - #89834

Closed
ablaszkiewicz wants to merge 5 commits into
masterfrom
ab/docs/release-id-env
Closed

feat(cli): add release-independent event mode to symbol-sets upload#89834
ablaszkiewicz wants to merge 5 commits into
masterfrom
ab/docs/release-id-env

Conversation

@ablaszkiewicz

@ablaszkiewicz ablaszkiewicz commented Aug 27, 2026

Copy link
Copy Markdown
Contributor

Problem

The default symbol-sets upload always binds the symbol set to a release — from --release-name/--release-version, or from git when you omit them. That has two costs for native apps: the upload needs release coordinates, and the same binary re-binds (and can collide) on every release. There was no way to upload native symbols release-independent and carry the release on the event instead — the native equivalent of the web $release_id.

Changes

Add --release-mode to symbol-sets upload (env POSTHOG_RELEASE_MODE):

  • symbol-set (default, unchanged): resolve a release and bind it to every uploaded symbol set.
  • event: upload the symbol sets release-independent — bound to no release. One symbol set then serves every release of an unchanged binary, and the upload needs no --release-name/--release-version.

In event mode the release rides the event as $release_id. You name the release with release resolve, pass its id to the app in POSTHOG_RELEASE_ID, and the SDK reports it (PostHog/posthog-rs#239):

# symbols, release-independent — no release name/version here
posthog-cli symbol-sets upload --directory target/release --release-mode=event

# the release is named here, and its id goes to the app
export POSTHOG_RELEASE_ID=$(posthog-cli release resolve --release-name my-app --release-version 1.4.0)
./my-app

This is the same --release-mode=event as the injected variant (#89117), minus the binary patching and code signing: the release still rides the event, but the SDK reads the id from the environment rather than from bytes patched into the build. This pair (this PR + PostHog/posthog-rs#239) and the injection pair (#89117 + PostHog/posthog-rs#237) are alternatives — pick one.

How did you test this code?

Automated (cargo test): parse tests that the flag defaults to symbol-set and accepts event, plus cargo fmt --check and cargo clippy clean.

End to end against a local PostHog stack, run by the agent (Claude). The rust-release-env example is built once; its symbols upload release-independent; two different releases resolve off that one symbol set purely by the reported $release_id.

event-mode upload — release-independent, no release name/version
$ posthog-cli symbol-sets upload --directory target/release --include-source --release-mode=event
INFO  --release-mode=event: uploading symbol sets release-independent; the release is carried on each event as $release_id (POSTHOG_RELEASE_ID)
INFO  Uploading 1 debug symbol file(s)...
INFO  Upload summary: 0 chunk(s) uploaded, 1 skipped (1 already present, 0 too large)
INFO  Debug symbol upload complete

No found release …, no binding — contrast the default mode, where a bare upload resolves a git release and binds the set to it.

name the release, run the app, resolve by id — off the one release-independent symbol set
$ export POSTHOG_RELEASE_ID=$(posthog-cli release resolve --release-name rust-release-env --release-version 3.0.0)
$ ./target/release/rust-release-env
starting — release 01a04269-bf66-0000-2ffa-a6f6d33af9dd (from POSTHOG_RELEASE_ID)
stopping

# read back server-side (dev-login session):
$release_id        : 01a04269-bf66-0000-2ffa-a6f6d33af9dd
$exception_release : { project: "rust-release-env", version: "3.0.0" }

The same binary earlier resolved rust-release-env@1.0.0 off the same symbol set (debug id 8A089A84-…), so one release-independent symbol set serves both releases. Symbolication and release resolution in the UI:

Symbolicated stack trace Release resolved via the reported $release_id
stack-trace release-resolved

🤖 Agent context

Autonomy: Human-driven (agent-assisted)

Authored by Claude in Claude Code, directed by @ablaszkiewicz (DRI). This is the CLI half of a second, env-variable-based approach to native release tracking, offered alongside the marker-injection pair (#89117 + PostHog/posthog-rs#237) for comparison. It started as docs-only until the DRI pointed out that symbol-sets upload binds the symbol set by default, so event mode was needed here too. The end-to-end verification above was run by the agent against a local PostHog dev stack (ingestion + cymbal); the example data is invented (rust-release-env) and draws on no customer material.

🤖 Generated with Claude Code

…OG_RELEASE_ID

Document the runtime env-var workflow for native apps: `release resolve`
prints the release id, you export it as `POSTHOG_RELEASE_ID`, and the SDK
reports it as `$release_id` on every event. This is the deploy-time
counterpart to the web `$release_id`, and it needs no new CLI code —
`release resolve` already ships. posthog-rs reads the variable
(PostHog/posthog-rs#239).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@trunk-io

trunk-io Bot commented Aug 27, 2026

Copy link
Copy Markdown

Merging to master in this repository is managed by Trunk.

  • To merge this pull request, check the box to the left or comment /trunk merge below.

After your PR is submitted to the merge queue, this comment will be automatically updated with its status. If the PR fails, failure details will also be posted here

@github-actions

Copy link
Copy Markdown
Contributor

🤖 CI report

Trunk lane — non-backend lane

This PR is assigned to the non-backend lane. It does not run backend Python tests and may merge in parallel with PRs in other lanes.

ablaszkiewicz and others added 2 commits August 27, 2026 09:31
posthog-rs reports the release id only on `$exception` events, so match
that wording: the SDK stamps `$release_id` on each exception, not on
every event.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add `--release-mode` to `symbol-sets upload` (env `POSTHOG_RELEASE_MODE`).
The default `symbol-set` mode keeps binding the release to every uploaded
symbol set. `event` uploads the symbol sets release-independent — bound
to no release — so one symbol set serves every release of an unchanged
binary, and the upload no longer needs `--release-name`/`--release-version`.

In event mode the release rides the event as `$release_id`, which the SDK
reports from `POSTHOG_RELEASE_ID` (posthog-rs 0.26+, PostHog/posthog-rs#239);
the release is named with `posthog-cli release resolve`, whose id you pass
to the app. No binary patching and no code signing, unlike the injected
`--release-mode=event` variant.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@ablaszkiewicz ablaszkiewicz changed the title docs(cli): report the release from a native app via POSTHOG_RELEASE_ID feat(cli): add release-independent event mode to symbol-sets upload Aug 27, 2026
@posthog

posthog Bot commented Aug 27, 2026

Copy link
Copy Markdown
Contributor

🦔 PostHog Review reviewed this pull request

Found 0 must fix, 1 should fix, 1 consider.

Published 2 findings (view the review).

Resolved comments: 1 fixed, 1 left for you

@posthog

posthog Bot commented Aug 27, 2026

Copy link
Copy Markdown
Contributor

PostHog Review alpha 🦔 If you find any issues helpful - please reply "valid", "invalid", etc., for evaluation purposes 🙏

@posthog posthog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

PostHog Review

Found 1 should fix, 1 consider.

Comment thread cli/README.md Outdated
Comment thread cli/src/debug_symbols/upload.rs
The runtime release-id section claimed posthog-rs and "other native SDKs"
read POSTHOG_RELEASE_ID, with no version gate. Only posthog-rs 0.26+ reads
it (PostHog/posthog-rs#239), and no other native SDK does today. State the
version gate the CLI help text and changeset already carry, and drop the
unverified multi-SDK claim.

Generated-By: PostHog Desktop
Task-Id: 81d53914-e1ab-4ecf-9740-da990f29d7dd
@ablaszkiewicz
ablaszkiewicz marked this pull request as ready for review August 27, 2026 12:09
Copilot AI lite review requested due to automatic review settings August 27, 2026 12:09

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@pr-assigner-resolver-posthog
pr-assigner-resolver-posthog Bot requested review from a team, cat-ph and hpouillot August 27, 2026 12:10
@greptile-apps

greptile-apps Bot commented Aug 27, 2026

Copy link
Copy Markdown
Contributor
Prompt To Fix All With AI
### Issue 1
cli/src/debug_symbols/upload.rs:65
**Event mode resolves plist**

When an event-mode upload supplies a missing or malformed `--info-plist`, `resolve_info_plist()` aborts the command before the release-independent branch runs, preventing otherwise valid symbols from uploading even though this mode does not use release metadata.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Reviews (1): Last reviewed commit: "docs(cli): gate release-id env docs to p..." | Re-trigger Greptile

Comment thread cli/src/debug_symbols/upload.rs Outdated
Comment thread cli/README.md Outdated
Comment thread cli/src/debug_symbols/upload.rs
Comment thread cli/src/debug_symbols/upload.rs Outdated
…e docs

Address review feedback on the release-independent event mode:

- resolve_info_plist() ran unconditionally, so a bad --info-plist aborted an
  event-mode upload that never reads release metadata. Move it into the
  symbol-set arm.
- The runtime log and field help said "each event"; $release_id is reported
  only on exceptions. Say "each exception".
- The shared ReleaseMode / UploadConflictArgs help described the sourcemap
  (injection) event mode, which contradicts the native symbol-sets path. Make
  the shared wording mode-neutral.
- README: assign then export, so a failing `release resolve` is not masked by
  export's own exit status.
- Document that event mode only creates new symbol sets unbound and leaves an
  existing binding intact (README, help, changeset).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@ablaszkiewicz

Copy link
Copy Markdown
Contributor Author

I think new release mode makes no sense for native technologies with a single-chunk-build - https://posthog.slack.com/archives/C07AA937K9A/p1787845698964179

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

docs Improvements or additions to documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants