diff --git a/.changeset/gradle-plugin-event-release-mode-default.md b/.changeset/gradle-plugin-event-release-mode-default.md new file mode 100644 index 000000000..e202b5b37 --- /dev/null +++ b/.changeset/gradle-plugin-event-release-mode-default.md @@ -0,0 +1,9 @@ +--- +'posthog-android-gradle-plugin': minor +--- + +Default `posthog.releaseMode` to `event`. The proguard mapping now uploads release-independent. Each event resolves its own release from the `$app_namespace` / `$app_version` / `$app_build` the SDK already sends. 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.13.0 or newer. That version added `--release-mode` to `proguard upload`. The release coordinates the build sends must match the app's applicationId, versionName and versionCode. diff --git a/posthog-android-gradle-plugin/src/main/kotlin/com/posthog/android/PostHogUploadProguardMappingsTask.kt b/posthog-android-gradle-plugin/src/main/kotlin/com/posthog/android/PostHogUploadProguardMappingsTask.kt index 4fd14f3c7..8f521565c 100644 --- a/posthog-android-gradle-plugin/src/main/kotlin/com/posthog/android/PostHogUploadProguardMappingsTask.kt +++ b/posthog-android-gradle-plugin/src/main/kotlin/com/posthog/android/PostHogUploadProguardMappingsTask.kt @@ -105,8 +105,9 @@ public abstract class PostHogUploadProguardMappingsTask : PostHogCliExecTask() { args.add("--build") args.add(it.toString()) } - // Passed only outside the default mode, so a symbol-set build keeps working against a - // posthog-cli predating the flag. + // Passed only outside symbol-set mode, so a symbol-set build keeps working against a + // posthog-cli predating the flag. The environment variable set above pins the mode for + // binaries that do know it. releaseMode.orNull?.takeIf { it != PostHogReleaseMode.SYMBOL_SET.cliValue }?.let { args.add("--release-mode") args.add(it) @@ -122,7 +123,7 @@ public abstract class PostHogUploadProguardMappingsTask : PostHogCliExecTask() { releaseName: Provider? = null, releaseVersion: Provider? = null, build: Provider? = null, - releaseMode: PostHogReleaseMode = PostHogReleaseMode.SYMBOL_SET, + releaseMode: PostHogReleaseMode = PostHogReleaseMode.EVENT, ): TaskProvider { val uploadPostHogProguardMappingsTask = project.tasks.register( diff --git a/posthog-android-gradle-plugin/src/main/kotlin/com/posthog/android/Utils.kt b/posthog-android-gradle-plugin/src/main/kotlin/com/posthog/android/Utils.kt index a322d8233..98e06b9a8 100644 --- a/posthog-android-gradle-plugin/src/main/kotlin/com/posthog/android/Utils.kt +++ b/posthog-android-gradle-plugin/src/main/kotlin/com/posthog/android/Utils.kt @@ -145,7 +145,7 @@ internal enum class PostHogReleaseMode(val cliValue: String) { /** * Release mode for this build: the `posthog.releaseMode` gradle property, then the * `POSTHOG_RELEASE_MODE` environment variable posthog-cli and the bundler plugins already read, - * then [PostHogReleaseMode.SYMBOL_SET]. + * then [PostHogReleaseMode.EVENT]. * * An unrecognized value fails the build rather than falling back, so a typo can't silently leave * a build binding its mapping to a release it meant to keep independent. @@ -157,7 +157,7 @@ internal fun resolvePostHogReleaseMode( val value = 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 return PostHogReleaseMode.from(value) ?: error( diff --git a/posthog-android-gradle-plugin/src/test/java/com/posthog/android/PostHogReleaseModeTest.kt b/posthog-android-gradle-plugin/src/test/java/com/posthog/android/PostHogReleaseModeTest.kt new file mode 100644 index 000000000..79c71ebf5 --- /dev/null +++ b/posthog-android-gradle-plugin/src/test/java/com/posthog/android/PostHogReleaseModeTest.kt @@ -0,0 +1,55 @@ +package com.posthog.android + +import org.gradle.api.Project +import org.gradle.testfixtures.ProjectBuilder +import org.junit.Test +import kotlin.test.assertEquals +import kotlin.test.assertFailsWith + +internal class PostHogReleaseModeTest { + // Not `apply`: Project has its own apply(), so the scope function would resolve to Gradle's. + private fun project(releaseMode: String? = null): Project { + val project = ProjectBuilder.builder().build() + releaseMode?.let { project.extensions.extraProperties.set(POSTHOG_RELEASE_MODE_PROPERTY, it) } + return project + } + + @Test + fun `a build that configures nothing uploads its mapping release-independent`() { + assertEquals(PostHogReleaseMode.EVENT, resolvePostHogReleaseMode(project(), emptyMap())) + } + + @Test + fun `the gradle property selects the mode`() { + assertEquals( + PostHogReleaseMode.SYMBOL_SET, + resolvePostHogReleaseMode(project(releaseMode = "symbol-set"), emptyMap()), + ) + } + + @Test + fun `the environment variable selects the mode`() { + assertEquals( + PostHogReleaseMode.SYMBOL_SET, + resolvePostHogReleaseMode(project(), mapOf(POSTHOG_RELEASE_MODE_ENV to "symbol-set")), + ) + } + + @Test + fun `the gradle property wins over the environment variable`() { + assertEquals( + PostHogReleaseMode.SYMBOL_SET, + resolvePostHogReleaseMode( + project(releaseMode = "symbol-set"), + mapOf(POSTHOG_RELEASE_MODE_ENV to "event"), + ), + ) + } + + @Test + fun `an unrecognized value fails the build instead of picking a mode`() { + assertFailsWith { + resolvePostHogReleaseMode(project(releaseMode = "symbolset"), emptyMap()) + } + } +}