Skip to content

feat(gradle-plugin): default release mode to event - #739

Draft
ablaszkiewicz wants to merge 1 commit into
mainfrom
feat/event-release-mode-default
Draft

feat(gradle-plugin): default release mode to event#739
ablaszkiewicz wants to merge 1 commit into
mainfrom
feat/event-release-mode-default

Conversation

@ablaszkiewicz

@ablaszkiewicz ablaszkiewicz commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

Related PRs

Event mode is live today. Each build must ask for it. These PRs make it the default. The modes themselves do not change.

Problem

  • Two Android releases that ship the same proguard mapping report their exceptions on one release.
  • The release that uploads the mapping first takes them.

Changes

  • posthog.releaseMode defaults to event.
  • The build uploads the proguard mapping without a release.
  • Each event resolves its own release from the $app_namespace, $app_version and $app_build the SDK sends.
  • posthog.releaseMode=symbol-set keeps the old behavior. POSTHOG_RELEASE_MODE=symbol-set does the same.
  • PostHogUploadProguardMappingsTask.register takes the same default.

How did you test this code?

  • ./gradlew :posthog-android-gradle-plugin:test and ./gradlew spotlessCheck detekt.
  • PostHogReleaseModeTest is new. resolvePostHogReleaseMode had no tests.
  • Not run: the functional tests. This change does not touch them.

🤖 Agent context

Autonomy: Human-driven (agent-assisted)

Written with Claude Code (Opus 5).

The test helper builds its Project without apply {}. Project has its own apply(), so the scope function resolves to Gradle's method.

The proguard mapping uploads release-independent by default, and each event
resolves its own release. Set posthog.releaseMode=symbol-set to keep
stamping the release onto the mapping.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jg6r6rFUBnowrXssZyU7yR
@ablaszkiewicz ablaszkiewicz self-assigned this Aug 31, 2026
@posthog

posthog Bot commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

🦔 PostHog Review reviewed this pull request

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

Published 2 findings (view the review).

@posthog

posthog Bot commented Aug 31, 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 must fix, 1 should fix.

'posthog-android-gradle-plugin': minor
---

Default `posthog.releaseMode` to `event`. The proguard mapping is now uploaded release-independent, and each event resolves its own release from the `$app_namespace` / `$app_version` / `$app_build` the SDK already sends, so two releases that ship the same mapping no longer both report whichever release uploaded it first. Set `posthog.releaseMode=symbol-set`, or `POSTHOG_RELEASE_MODE=symbol-set`, to keep stamping the release onto the uploaded mapping. Event mode needs posthog-cli >= 0.12.0, and the release coordinates the build sends have to match the app's applicationId, versionName and versionCode.

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.

The documented minimum CLI version rejects event mode

must_fix compatibility

Why we think it's a valid issue
  • Checked: the posthog-cli release history on npm, the CLI's own CHANGELOG.md for 0.11.0 through 0.13.0, and the real x86_64-unknown-linux-gnu release binaries for both 0.12.0 and 0.13.0.
  • Found: the CLI changelog assigns --release-mode on proguard upload to 0.13.0, not 0.12.0: "Add --release-mode to proguard upload, matching sourcemap upload." Version 0.12.0 adds release resolve only, which is unrelated. Version 0.11.0 adds --release-mode to the sourcemap commands (inject/upload/process), which is the likely source of the off-by-one.
  • Found: I ran the exact argument list the task builds against both binaries. Version 0.12.0 answers error: unexpected argument '--release-mode' found and exits with code 2; its exp proguard upload --help has no --release-mode entry. Version 0.13.0 lists --release-mode <RELEASE_MODE> in help and accepts it.
  • Found: this PR puts the flag on the default path. Utils.kt:160 now returns PostHogReleaseMode.EVENT when nothing is configured, PostHogUploadProguardMappingsTask.kt:126 defaults register to EVENT, and getArguments at PostHogUploadProguardMappingsTask.kt:111-114 adds --release-mode for every mode except symbol-set. A build that configures nothing therefore passes the flag.
  • Found: the failure stops the build. PostHogCliExecTask extends Gradle's Exec and never sets isIgnoreExitValue, so the default false applies and exit code 2 fails the task. The plugin also runs no version check at all — resolvePostHogCliExecutable in Utils.kt:170-239 takes whichever posthog-cli sits on PATH or in a known install location. The documented minimum version is the only compatibility guard there is.
  • Impact: a user who reads the changeset, installs posthog-cli 0.12.0, and changes no Gradle property gets a failed uploadPostHogProguardMappings task with the misleading message unexpected argument '--release-mode'. Before this PR the wrong number only affected people who opted into event mode; the new default applies it to every build.
  • Impact: the same wrong number already sits in the shipped posthog-android-gradle-plugin/CHANGELOG.md:19, so the correction belongs in both places.
  • Priority: I keep must_fix. The version window is narrow, because 0.13.0 shipped the same day as 0.12.0, so few users sit exactly on 0.12.0. The statement is still false, the documentation is the only compatibility guard, and the fix is one number. Only the version correction is required; the suggested test that runs the arguments against a downloaded CLI binary is heavier than this needs and is optional.
Issue description

The changeset states that event mode needs posthog-cli 0.12.0. However, version 0.12.0 rejects --release-mode as an unexpected argument. Version 0.13.0 accepts this flag. Users who follow this requirement will still get a failed upload task.

Suggested fix

Change the minimum version to 0.13.0. Add a compatibility test that runs the generated arguments against the stated minimum CLI version.

Prompt to fix with AI (copy-paste)
## Context
@.changeset/gradle-plugin-event-release-mode-default.md#L5

<issue_description>
The changeset states that event mode needs posthog-cli 0.12.0. However, version 0.12.0 rejects `--release-mode` as an unexpected argument. Version 0.13.0 accepts this flag. Users who follow this requirement will still get a failed upload task.
</issue_description>

<issue_validation>
- **Checked:** the posthog-cli release history on npm, the CLI's own `CHANGELOG.md` for 0.11.0 through 0.13.0, and the real `x86_64-unknown-linux-gnu` release binaries for both 0.12.0 and 0.13.0.
- **Found:** the CLI changelog assigns `--release-mode` on `proguard upload` to **0.13.0**, not 0.12.0: "Add `--release-mode` to `proguard upload`, matching `sourcemap upload`." Version 0.12.0 adds `release resolve` only, which is unrelated. Version 0.11.0 adds `--release-mode` to the *sourcemap* commands (`inject`/`upload`/`process`), which is the likely source of the off-by-one.
- **Found:** I ran the exact argument list the task builds against both binaries. Version 0.12.0 answers `error: unexpected argument '--release-mode' found` and exits with code **2**; its `exp proguard upload --help` has no `--release-mode` entry. Version 0.13.0 lists `--release-mode <RELEASE_MODE>` in help and accepts it.
- **Found:** this PR puts the flag on the default path. `Utils.kt:160` now returns `PostHogReleaseMode.EVENT` when nothing is configured, `PostHogUploadProguardMappingsTask.kt:126` defaults `register` to `EVENT`, and `getArguments` at `PostHogUploadProguardMappingsTask.kt:111-114` adds `--release-mode` for every mode except symbol-set. A build that configures nothing therefore passes the flag.
- **Found:** the failure stops the build. `PostHogCliExecTask` extends Gradle's `Exec` and never sets `isIgnoreExitValue`, so the default `false` applies and exit code 2 fails the task. The plugin also runs no version check at all — `resolvePostHogCliExecutable` in `Utils.kt:170-239` takes whichever `posthog-cli` sits on PATH or in a known install location. The documented minimum version is the only compatibility guard there is.
- **Impact:** a user who reads the changeset, installs posthog-cli 0.12.0, and changes no Gradle property gets a failed `uploadPostHogProguardMappings` task with the misleading message `unexpected argument '--release-mode'`. Before this PR the wrong number only affected people who opted into event mode; the new default applies it to every build.
- **Impact:** the same wrong number already sits in the shipped `posthog-android-gradle-plugin/CHANGELOG.md:19`, so the correction belongs in both places.
- **Priority:** I keep `must_fix`. The version window is narrow, because 0.13.0 shipped the same day as 0.12.0, so few users sit exactly on 0.12.0. The statement is still false, the documentation is the only compatibility guard, and the fix is one number. Only the version correction is required; the suggested test that runs the arguments against a downloaded CLI binary is heavier than this needs and is optional.
</issue_validation>

## Task
Investigate the issue and solve it

<potential_solution>
Change the minimum version to 0.13.0. Add a compatibility test that runs the generated arguments against the stated minimum CLI version.
</potential_solution>

project.findProperty(POSTHOG_RELEASE_MODE_PROPERTY)?.toString()?.trim()?.takeIf { it.isNotEmpty() }
?: environment[POSTHOG_RELEASE_MODE_ENV]?.trim()?.takeIf { it.isNotEmpty() }
?: return PostHogReleaseMode.SYMBOL_SET
?: return PostHogReleaseMode.EVENT

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.

Event mode does not validate required release coordinates

should_fix bug

Why we think it's a valid issue
  • Checked: the argument builder in PostHogUploadProguardMappingsTask.getArguments, the values the caller supplies, the SDK's runtime context builder, and the posthog-cli 0.13.0 exp proguard upload --help text from the real release binary.
  • Found: the CLI's own help confirms the git-derivation claim. --release-version reads: "The version of the project ... Required to have the uploaded chunks associated with a specific release. We will try to auto-derive this from git information if not provided". --release-name carries the same sentence. So omitting the flag does not skip release creation — it creates a release under git-derived coordinates, typically a commit hash.
  • Found: the same help text states the matching requirement for the mode this PR now defaults to: --release-mode event "leaves the mapping release-independent, and each event resolves its own release from the app version and namespace the SDK already sends, so the release coordinates have to match the app's".
  • Found: the blank path is real and unguarded. PostHogAndroidGradlePlugin.kt:202 passes primaryOutput?.versionName?.map { it.orEmpty() }, which turns a null versionName into "". PostHogUploadProguardMappingsTask.kt:100-103 then drops the flag, because takeIf { it.isNotEmpty() } fails on the empty string. Nothing in resolvePostHogReleaseMode (Utils.kt:157-165) or the task checks the coordinates against the selected mode.
  • Found: the runtime side omits the property rather than sending a blank. PostHogAndroidContext.kt:41-43 guards with it.versionName?.let { name -> staticContext["\$app_version"] = name }, so a null versionName leaves $app_version absent from the event entirely. That explicit null check is also evidence the team treats a missing versionName as reachable, not as a case the types rule out.
  • Impact: for an app with no versionName, the upload creates a release keyed to a git commit hash while events carry no $app_version at all. The two can never match, so in event mode the release is orphaned and errors resolve no release. The build prints no warning, so the failure is silent — the changeset states the coordinates "have to match the app's applicationId, versionName and versionCode", but nothing enforces it.
  • Impact: scope is narrower than the wording suggests, and the author should know both limits. Symbolication is unaffected: the symbol set is keyed by the per-variant map id that InjectPostHogMetaPropertiesIntoAssetsTask bakes into the assets and PostHogMetaPropertiesApplier.kt:47-51 loads as releaseIdentifier, so stack frames still resolve. What is lost is release attribution. Reachability is also limited, because this path only runs when variant.isMinifyEnabled (PostHogAndroidGradlePlugin.kt:60) and most shipped minified builds do set a versionName.
  • Impact: it still clears the bar. The mechanism is confirmed at every link, the change makes event mode the default for unconfigured builds, the degradation is silent, and the suggested guard — fail or warn when the coordinates are blank in event mode — is small and proportionate.
Issue description

Event mode now applies to every unconfigured build, but the upload task permits a blank releaseVersion and omits --release-version. Android permits a null or blank versionName. Runtime events then omit $app_version or send an empty value. The CLI can derive a different version from Git, so the event cannot resolve the uploaded release.

Suggested fix

In event mode, fail the upload when releaseName or releaseVersion is blank. Explain that the app must set applicationId and versionName. Alternatively, use one deterministic fallback in both the CLI upload and SDK events.

Prompt to fix with AI (copy-paste)
## Context
@posthog-android-gradle-plugin/src/main/kotlin/com/posthog/android/Utils.kt#L160

<issue_description>
Event mode now applies to every unconfigured build, but the upload task permits a blank releaseVersion and omits `--release-version`. Android permits a null or blank versionName. Runtime events then omit `$app_version` or send an empty value. The CLI can derive a different version from Git, so the event cannot resolve the uploaded release.
</issue_description>

<issue_validation>
- **Checked:** the argument builder in `PostHogUploadProguardMappingsTask.getArguments`, the values the caller supplies, the SDK's runtime context builder, and the posthog-cli 0.13.0 `exp proguard upload --help` text from the real release binary.
- **Found:** the CLI's own help confirms the git-derivation claim. `--release-version` reads: "The version of the project ... Required to have the uploaded chunks associated with a specific release. **We will try to auto-derive this from git information if not provided**". `--release-name` carries the same sentence. So omitting the flag does not skip release creation — it creates a release under git-derived coordinates, typically a commit hash.
- **Found:** the same help text states the matching requirement for the mode this PR now defaults to: `--release-mode event` "leaves the mapping release-independent, and each event resolves its own release from the app version and namespace the SDK already sends, **so the release coordinates have to match the app's**".
- **Found:** the blank path is real and unguarded. `PostHogAndroidGradlePlugin.kt:202` passes `primaryOutput?.versionName?.map { it.orEmpty() }`, which turns a null `versionName` into `""`. `PostHogUploadProguardMappingsTask.kt:100-103` then drops the flag, because `takeIf { it.isNotEmpty() }` fails on the empty string. Nothing in `resolvePostHogReleaseMode` (`Utils.kt:157-165`) or the task checks the coordinates against the selected mode.
- **Found:** the runtime side omits the property rather than sending a blank. `PostHogAndroidContext.kt:41-43` guards with `it.versionName?.let { name -> staticContext["\$app_version"] = name }`, so a null `versionName` leaves `$app_version` absent from the event entirely. That explicit null check is also evidence the team treats a missing `versionName` as reachable, not as a case the types rule out.
- **Impact:** for an app with no `versionName`, the upload creates a release keyed to a git commit hash while events carry no `$app_version` at all. The two can never match, so in event mode the release is orphaned and errors resolve no release. The build prints no warning, so the failure is silent — the changeset states the coordinates "have to match the app's applicationId, versionName and versionCode", but nothing enforces it.
- **Impact:** scope is narrower than the wording suggests, and the author should know both limits. Symbolication is unaffected: the symbol set is keyed by the per-variant map id that `InjectPostHogMetaPropertiesIntoAssetsTask` bakes into the assets and `PostHogMetaPropertiesApplier.kt:47-51` loads as `releaseIdentifier`, so stack frames still resolve. What is lost is release attribution. Reachability is also limited, because this path only runs when `variant.isMinifyEnabled` (`PostHogAndroidGradlePlugin.kt:60`) and most shipped minified builds do set a `versionName`.
- **Impact:** it still clears the bar. The mechanism is confirmed at every link, the change makes event mode the default for unconfigured builds, the degradation is silent, and the suggested guard — fail or warn when the coordinates are blank in event mode — is small and proportionate.
</issue_validation>

## Task
Investigate the issue and solve it

<potential_solution>
In event mode, fail the upload when releaseName or releaseVersion is blank. Explain that the app must set applicationId and versionName. Alternatively, use one deterministic fallback in both the CLI upload and SDK events.
</potential_solution>

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