From ba27d3a87d130e7a0a5601f339f284c0a2b9e837 Mon Sep 17 00:00:00 2001 From: ablaszkiewicz Date: Tue, 1 Sep 2026 13:41:29 +0200 Subject: [PATCH 1/4] chore(gradle-plugin): remove event release mode The plugin uploads the proguard mapping bound to the release it creates. The map id is a content hash of the mapping, so two releases collide only when they ship a byte-identical mapping. An ordinary release that changes code already gets its own symbol set. The property was experimental and undocumented. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01Jg6r6rFUBnowrXssZyU7yR --- .../remove-gradle-plugin-release-mode.md | 7 +++ .../android/PostHogAndroidGradlePlugin.kt | 8 +-- .../PostHogUploadProguardMappingsTask.kt | 19 ------- .../main/kotlin/com/posthog/android/Utils.kt | 50 ------------------- 4 files changed, 8 insertions(+), 76 deletions(-) create mode 100644 .changeset/remove-gradle-plugin-release-mode.md diff --git a/.changeset/remove-gradle-plugin-release-mode.md b/.changeset/remove-gradle-plugin-release-mode.md new file mode 100644 index 000000000..d8de363f2 --- /dev/null +++ b/.changeset/remove-gradle-plugin-release-mode.md @@ -0,0 +1,7 @@ +--- +'posthog-android-gradle-plugin': minor +--- + +Remove the `posthog.releaseMode` gradle property and the `POSTHOG_RELEASE_MODE` environment variable. The plugin uploads the proguard mapping bound to the release it creates, which is what it did before the property existed. + +Event mode only helps when two releases ship a byte-identical mapping. The map id is already a content hash, so an ordinary release that changes code gets its own symbol set and never collides with an earlier one. The property was experimental and undocumented, so it goes out directly. diff --git a/posthog-android-gradle-plugin/src/main/kotlin/com/posthog/android/PostHogAndroidGradlePlugin.kt b/posthog-android-gradle-plugin/src/main/kotlin/com/posthog/android/PostHogAndroidGradlePlugin.kt index e74d9e761..44dff8bf4 100644 --- a/posthog-android-gradle-plugin/src/main/kotlin/com/posthog/android/PostHogAndroidGradlePlugin.kt +++ b/posthog-android-gradle-plugin/src/main/kotlin/com/posthog/android/PostHogAndroidGradlePlugin.kt @@ -45,8 +45,6 @@ internal abstract class PostHogAndroidGradlePlugin ) {} buildEventsListenerRegistry.onTaskCompletion(failureTracker) - val releaseMode = resolvePostHogReleaseMode(project) - project.pluginManager.withPlugin("com.android.application") { val androidComponentsExt = project.extensions.getByType(ApplicationAndroidComponentsExtension::class.java) @@ -66,7 +64,7 @@ internal abstract class PostHogAndroidGradlePlugin // TODO: skip variants, skip autoUpload, release info, allow failure, debug mode val paths = OutputPaths(project, variant.name) - val generateMapIdTask = generateMapIdTask(project, variant, paths, failureTracker, releaseMode) + val generateMapIdTask = generateMapIdTask(project, variant, paths, failureTracker) tasksGeneratingProperties.add(generateMapIdTask) variant.apply { @@ -158,7 +156,6 @@ internal abstract class PostHogAndroidGradlePlugin variant: ApplicationVariant, paths: OutputPaths, failureTracker: Provider, - releaseMode: PostHogReleaseMode, ): TaskProvider { val generateMapIdTask = PostHogGenerateMapIdTask.register( @@ -174,7 +171,6 @@ internal abstract class PostHogAndroidGradlePlugin generateMapIdTask = generateMapIdTask, variant = variant, mappingFiles = variant.mappingFileProvider(project), - releaseMode = releaseMode, ) generateMapIdTask.hookWithMinifyTasks(project, variant.name, generateMapIdTask) @@ -189,7 +185,6 @@ internal abstract class PostHogAndroidGradlePlugin generateMapIdTask: Provider, variant: ApplicationVariant, mappingFiles: Provider, - releaseMode: PostHogReleaseMode, ): TaskProvider { val primaryOutput = variant.outputs.firstOrNull() val uploadMapIdTask = @@ -201,7 +196,6 @@ internal abstract class PostHogAndroidGradlePlugin releaseName = variant.applicationId, releaseVersion = primaryOutput?.versionName?.map { it.orEmpty() }, build = primaryOutput?.versionCode?.map { it ?: 0 }, - releaseMode = releaseMode, ) return uploadMapIdTask } 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..982710c96 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 @@ -53,21 +53,10 @@ public abstract class PostHogUploadProguardMappingsTask : PostHogCliExecTask() { @get:Optional public abstract val build: Property - /** [PostHogReleaseMode.cliValue], as the enum itself is internal to the plugin. */ - @get:Input - @get:Optional - public abstract val releaseMode: Property - override fun exec() { if (!mappingsFiles.isPresent || mappingsFiles.get().isEmpty) { error("[PostHog] Mapping files are missing!") } - // posthog-cli reads POSTHOG_RELEASE_MODE itself when --release-mode is absent, and the - // Gradle daemon's environment may carry one that contradicts the mode resolved here — - // where the gradle property is supposed to win. Pin the resolved mode in the child's - // environment so it cannot be overridden by inheritance. A posthog-cli predating the flag - // has no such argument and ignores the variable, so this stays safe for old CLIs. - releaseMode.orNull?.let { environment(POSTHOG_RELEASE_MODE_ENV, it) } super.exec() } @@ -105,12 +94,6 @@ 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. - releaseMode.orNull?.takeIf { it != PostHogReleaseMode.SYMBOL_SET.cliValue }?.let { - args.add("--release-mode") - args.add(it) - } } internal companion object { @@ -122,7 +105,6 @@ public abstract class PostHogUploadProguardMappingsTask : PostHogCliExecTask() { releaseName: Provider? = null, releaseVersion: Provider? = null, build: Provider? = null, - releaseMode: PostHogReleaseMode = PostHogReleaseMode.SYMBOL_SET, ): TaskProvider { val uploadPostHogProguardMappingsTask = project.tasks.register( @@ -136,7 +118,6 @@ public abstract class PostHogUploadProguardMappingsTask : PostHogCliExecTask() { releaseName?.let { this.releaseName.set(it) } releaseVersion?.let { this.releaseVersion.set(it) } build?.let { this.build.set(it) } - this.releaseMode.set(releaseMode.cliValue) resolvePostHogDotenvFile(project)?.let { this.postHogDotenvFile.set(it) } } return uploadPostHogProguardMappingsTask 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..e9ad0a884 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 @@ -116,56 +116,6 @@ internal fun resolvePostHogDotenvFile(project: Project): String? { return if (file.isAbsolute) file.path else File(project.rootDir, value).path } -internal const val POSTHOG_RELEASE_MODE_PROPERTY = "posthog.releaseMode" - -internal const val POSTHOG_RELEASE_MODE_ENV = "POSTHOG_RELEASE_MODE" - -/** How the release a build belongs to gets associated with the exceptions it reports. */ -internal enum class PostHogReleaseMode(val cliValue: String) { - /** - * posthog-cli stamps the release onto the uploaded mapping file, and exceptions inherit it - * from the mapping their frames resolved against. The behavior before event mode existed. - */ - SYMBOL_SET("symbol-set"), - - /** - * The mapping is uploaded release-independent, and each event resolves its own release from - * the `$app_namespace` / `$app_version` / `$app_build` the SDK already sends. Nothing is - * injected into the app. A map id is derived from the mapping's content, so two releases - * sharing a mapping would otherwise both report whichever release uploaded it first. - */ - EVENT("event"), - ; - - internal companion object { - fun from(value: String): PostHogReleaseMode? = values().firstOrNull { it.cliValue == value } - } -} - -/** - * 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]. - * - * 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. - */ -internal fun resolvePostHogReleaseMode( - project: Project, - environment: Map = System.getenv(), -): PostHogReleaseMode { - 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.from(value) - ?: error( - "$POSTHOG_RELEASE_MODE_PROPERTY must be one of " + - "${PostHogReleaseMode.values().joinToString { it.cliValue }}, was '$value'", - ) -} - /** * Locates posthog-cli for builds whose environment lacks the shell PATH — * IDE-launched Gradle daemons don't source shell profiles, so a CLI installed From 16c3f8e5708dc516c2900e1b4e439090d5686eda Mon Sep 17 00:00:00 2001 From: ablaszkiewicz Date: Tue, 1 Sep 2026 15:43:33 +0200 Subject: [PATCH 2/4] fix(gradle-plugin): pin the release mode for the mapping upload An Exec task inherits the daemon environment, and posthog-cli reads POSTHOG_RELEASE_MODE for proguard upload. A value set for another tool would leave the mapping release-independent, which is what this PR removes. A posthog-cli without the flag ignores the variable. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01Jg6r6rFUBnowrXssZyU7yR --- .../com/posthog/android/PostHogUploadProguardMappingsTask.kt | 5 +++++ 1 file changed, 5 insertions(+) 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 982710c96..4f4551b66 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 @@ -57,6 +57,11 @@ public abstract class PostHogUploadProguardMappingsTask : PostHogCliExecTask() { if (!mappingsFiles.isPresent || mappingsFiles.get().isEmpty) { error("[PostHog] Mapping files are missing!") } + // The mapping always binds to the release this build creates. posthog-cli reads + // POSTHOG_RELEASE_MODE for `proguard upload`, and an Exec task inherits the daemon + // environment, so a value set for another tool would otherwise leave the mapping + // release-independent. Pin it. A posthog-cli that has no such flag ignores the variable. + environment("POSTHOG_RELEASE_MODE", "symbol-set") super.exec() } From 5506553a4f4a3af4e28f65c6394f8acab19df187 Mon Sep 17 00:00:00 2001 From: ablaszkiewicz Date: Tue, 1 Sep 2026 17:00:37 +0200 Subject: [PATCH 3/4] chore(gradle-plugin): keep releaseMode as a warned no-op Review asked for deprecation instead of removal, so upgrading cannot silently change a configured build. The posthog.releaseMode property and the task's releaseMode input stay accepted, warn, and do nothing. The POSTHOG_RELEASE_MODE environment variable stays silent because it still steers other PostHog tools. Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_0177eam86deHk8HZYMKcJtbD --- .../deprecate-gradle-plugin-release-mode.md | 7 +++++++ .../remove-gradle-plugin-release-mode.md | 7 ------- .../android/PostHogAndroidGradlePlugin.kt | 2 ++ .../PostHogUploadProguardMappingsTask.kt | 15 +++++++++++++++ .../main/kotlin/com/posthog/android/Utils.kt | 19 +++++++++++++++++++ 5 files changed, 43 insertions(+), 7 deletions(-) create mode 100644 .changeset/deprecate-gradle-plugin-release-mode.md delete mode 100644 .changeset/remove-gradle-plugin-release-mode.md diff --git a/.changeset/deprecate-gradle-plugin-release-mode.md b/.changeset/deprecate-gradle-plugin-release-mode.md new file mode 100644 index 000000000..7436602a8 --- /dev/null +++ b/.changeset/deprecate-gradle-plugin-release-mode.md @@ -0,0 +1,7 @@ +--- +'posthog-android-gradle-plugin': minor +--- + +Deprecate the `posthog.releaseMode` gradle property and the upload task's `releaseMode` input. Both are ignored now, with a build-log warning: the plugin uploads the proguard mapping bound to the release it creates, which is what it did before the property existed. Remove the property to silence the warning. The `POSTHOG_RELEASE_MODE` environment variable no longer affects this upload either; the task pins `symbol-set` into the posthog-cli environment so an inherited value cannot leave the mapping release-independent on an older CLI. + +Event mode only helps when two releases ship a byte-identical mapping. The map id is already a content hash, so an ordinary release that changes code gets its own symbol set and never collides with an earlier one. diff --git a/.changeset/remove-gradle-plugin-release-mode.md b/.changeset/remove-gradle-plugin-release-mode.md deleted file mode 100644 index d8de363f2..000000000 --- a/.changeset/remove-gradle-plugin-release-mode.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'posthog-android-gradle-plugin': minor ---- - -Remove the `posthog.releaseMode` gradle property and the `POSTHOG_RELEASE_MODE` environment variable. The plugin uploads the proguard mapping bound to the release it creates, which is what it did before the property existed. - -Event mode only helps when two releases ship a byte-identical mapping. The map id is already a content hash, so an ordinary release that changes code gets its own symbol set and never collides with an earlier one. The property was experimental and undocumented, so it goes out directly. diff --git a/posthog-android-gradle-plugin/src/main/kotlin/com/posthog/android/PostHogAndroidGradlePlugin.kt b/posthog-android-gradle-plugin/src/main/kotlin/com/posthog/android/PostHogAndroidGradlePlugin.kt index 44dff8bf4..5adf6c654 100644 --- a/posthog-android-gradle-plugin/src/main/kotlin/com/posthog/android/PostHogAndroidGradlePlugin.kt +++ b/posthog-android-gradle-plugin/src/main/kotlin/com/posthog/android/PostHogAndroidGradlePlugin.kt @@ -38,6 +38,8 @@ internal abstract class PostHogAndroidGradlePlugin extension.uploadNativeSymbols.convention(false) extension.includeNativeSymbolSources.convention(false) + warnIfDeprecatedReleaseModeSet(project) + val failureTracker = project.gradle.sharedServices.registerIfAbsent( PostHogTaskFailureTracker.NAME, 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 4f4551b66..17f362490 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 @@ -53,10 +53,25 @@ public abstract class PostHogUploadProguardMappingsTask : PostHogCliExecTask() { @get:Optional public abstract val build: Property + @Deprecated("The value is ignored. The mapping always binds to the release the build creates.") + @get:Input + @get:Optional + public abstract val releaseMode: Property + override fun exec() { if (!mappingsFiles.isPresent || mappingsFiles.get().isEmpty) { error("[PostHog] Mapping files are missing!") } + + @Suppress("DEPRECATION") + val deprecatedReleaseMode = releaseMode + if (deprecatedReleaseMode.isPresent) { + logger.warn( + "[PostHog] releaseMode is deprecated and ignored. The mapping uploads bound to " + + "the release this build creates. Remove the assignment.", + ) + } + // The mapping always binds to the release this build creates. posthog-cli reads // POSTHOG_RELEASE_MODE for `proguard upload`, and an Exec task inherits the daemon // environment, so a value set for another tool would otherwise leave the mapping 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 e9ad0a884..748aa24e6 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 @@ -98,6 +98,25 @@ internal fun DirectoryProperty.getAndDelete(): File { internal const val POSTHOG_CLI_DEFAULT_EXECUTABLE = "posthog-cli" +internal const val POSTHOG_RELEASE_MODE_PROPERTY = "posthog.releaseMode" + +/** + * The property no longer does anything: the mapping always binds to the release the build creates. + * The POSTHOG_RELEASE_MODE environment variable stays silent here on purpose, because it still + * steers the sourcemap and hermes uploads of other PostHog tools, so a warning about it would not + * be actionable. + */ +internal fun warnIfDeprecatedReleaseModeSet(project: Project) { + val value = project.findProperty(POSTHOG_RELEASE_MODE_PROPERTY)?.toString()?.trim() + if (value.isNullOrEmpty()) { + return + } + project.logger.warn( + "[PostHog] $POSTHOG_RELEASE_MODE_PROPERTY is deprecated and ignored. The proguard " + + "mapping uploads bound to the release this build creates. Remove the property.", + ) +} + internal const val POSTHOG_DOTENV_FILE_PROPERTY = "posthog.dotenvFile" /** From 27cfc0cbf1358b923dd97053469e7579a051d3de Mon Sep 17 00:00:00 2001 From: ablaszkiewicz Date: Wed, 2 Sep 2026 09:49:34 +0200 Subject: [PATCH 4/4] fix(gradle-plugin): warn reliably under the configuration cache Review asked for three refinements. The posthog.releaseMode property now feeds the upload task's releaseMode input through gradleProperty, so the execution-time warning fires on every executed upload, including builds that reuse a configuration cache entry. An inherited POSTHOG_RELEASE_MODE that used to select event mode gets its own warning, worded to not ask for removal because the variable still steers other PostHog tools. The env pin comment names the CLI range it covers. A functional test runs the upload with the configuration cache twice and asserts the warning on the reused entry. Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_0177eam86deHk8HZYMKcJtbD --- .../deprecate-gradle-plugin-release-mode.md | 2 +- .../NativeSymbolsUploadFunctionalTest.kt | 62 +++++++++++++++++++ .../PostHogUploadProguardMappingsTask.kt | 30 +++++++-- 3 files changed, 88 insertions(+), 6 deletions(-) diff --git a/.changeset/deprecate-gradle-plugin-release-mode.md b/.changeset/deprecate-gradle-plugin-release-mode.md index 7436602a8..163506afb 100644 --- a/.changeset/deprecate-gradle-plugin-release-mode.md +++ b/.changeset/deprecate-gradle-plugin-release-mode.md @@ -2,6 +2,6 @@ 'posthog-android-gradle-plugin': minor --- -Deprecate the `posthog.releaseMode` gradle property and the upload task's `releaseMode` input. Both are ignored now, with a build-log warning: the plugin uploads the proguard mapping bound to the release it creates, which is what it did before the property existed. Remove the property to silence the warning. The `POSTHOG_RELEASE_MODE` environment variable no longer affects this upload either; the task pins `symbol-set` into the posthog-cli environment so an inherited value cannot leave the mapping release-independent on an older CLI. +Deprecate the `posthog.releaseMode` gradle property and the upload task's `releaseMode` input. Both are ignored now, with a build-log warning: the plugin uploads the proguard mapping bound to the release it creates, which is what it did before the property existed. Remove the property to silence the warning. The `POSTHOG_RELEASE_MODE` environment variable no longer affects this upload either: the task warns when an inherited value used to select event mode, and pins `symbol-set` into the posthog-cli environment so the value cannot leave the mapping release-independent on an older CLI. Event mode only helps when two releases ship a byte-identical mapping. The map id is already a content hash, so an ordinary release that changes code gets its own symbol set and never collides with an earlier one. diff --git a/posthog-android-gradle-plugin/src/functionalTest/kotlin/com/posthog/android/NativeSymbolsUploadFunctionalTest.kt b/posthog-android-gradle-plugin/src/functionalTest/kotlin/com/posthog/android/NativeSymbolsUploadFunctionalTest.kt index 3fe19ec1f..a9486963e 100644 --- a/posthog-android-gradle-plugin/src/functionalTest/kotlin/com/posthog/android/NativeSymbolsUploadFunctionalTest.kt +++ b/posthog-android-gradle-plugin/src/functionalTest/kotlin/com/posthog/android/NativeSymbolsUploadFunctionalTest.kt @@ -60,6 +60,7 @@ internal class NativeSymbolsUploadFunctionalTest( private fun setUpProject( uploadNativeSymbols: Boolean, includeNativeSymbolSources: Boolean = false, + minifyEnabled: Boolean = false, ): File { val fakeCliLog = File(projectDir.root, "fake-cli-args.txt") val fakeCli = File(projectDir.root, "fake-posthog-cli") @@ -102,6 +103,36 @@ internal class NativeSymbolsUploadFunctionalTest( File(app, "src/main/jniLibs/arm64-v8a").mkdirs() File(app, "src/main/jniLibs/arm64-v8a/libfake.so").writeBytes(byteArrayOf(0x7f, 0x45, 0x4c, 0x46)) + var minifyBlock = "" + if (minifyEnabled) { + // A kept-but-obfuscated class makes R8 write a non-empty mapping, so the + // mapping upload task has something to run on. + File(app, "src/main/java/com/posthog/test").mkdirs() + File(app, "src/main/java/com/posthog/test/Placeholder.java").writeText( + """ + package com.posthog.test; + + public class Placeholder { + public static String tag() { + return "placeholder"; + } + } + """.trimIndent(), + ) + File(app, "proguard-rules.pro").writeText( + "-keep,allowobfuscation class com.posthog.test.** { *; }\n", + ) + minifyBlock = + """ + | buildTypes { + | release { + | minifyEnabled true + | proguardFiles 'proguard-rules.pro' + | } + | } + """.trimMargin() + } + File(app, "build.gradle").writeText( """ apply plugin: 'com.android.application' @@ -115,6 +146,7 @@ internal class NativeSymbolsUploadFunctionalTest( versionCode 1 versionName '1.0' } + $minifyBlock } posthog { @@ -235,4 +267,34 @@ internal class NativeSymbolsUploadFunctionalTest( val scheduled = runner(":app:assembleDebug", "--dry-run").build() assertFalse(scheduled.output.contains(":app:uploadPostHogNativeSymbolsDebug"), scheduled.output) } + + @Test + fun `warns about the deprecated release mode on configuration-cache-reused builds`() { + setUpProject(uploadNativeSymbols = false, minifyEnabled = true) + // a non-cache warm-up stabilizes AGP's TestKit android.lock creation, + // which can otherwise invalidate the first stored entry + runner(":app:tasks").build() + + // --rerun-tasks on both runs keeps the cache key identical while forcing the upload task + // to execute on the reused entry, where a configuration-time warning cannot fire. + val arguments = + arrayOf( + ":app:uploadPostHogProguardMappingsRelease", + "--rerun-tasks", + "--configuration-cache", + "--configuration-cache-problems=fail", + "-Pposthog.releaseMode=event", + ) + val warning = "is deprecated and ignored" + + val first = runner(*arguments).build() + assertTrue(first.output.contains("Configuration cache entry stored"), first.output) + assertEquals(TaskOutcome.SUCCESS, first.task(":app:uploadPostHogProguardMappingsRelease")?.outcome) + assertTrue(first.output.contains(warning), first.output) + + val second = runner(*arguments).build() + assertTrue(second.output.contains("Reusing configuration cache"), second.output) + assertEquals(TaskOutcome.SUCCESS, second.task(":app:uploadPostHogProguardMappingsRelease")?.outcome) + assertTrue(second.output.contains(warning), second.output) + } } 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 17f362490..e0cfd8ca2 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 @@ -63,19 +63,35 @@ public abstract class PostHogUploadProguardMappingsTask : PostHogCliExecTask() { error("[PostHog] Mapping files are missing!") } + // Warns at execution time on purpose: a configuration-time warning goes silent on a reused + // configuration cache entry, and the plugin wires the posthog.releaseMode gradle property + // into this input so it lands here on every executed upload. @Suppress("DEPRECATION") val deprecatedReleaseMode = releaseMode if (deprecatedReleaseMode.isPresent) { logger.warn( "[PostHog] releaseMode is deprecated and ignored. The mapping uploads bound to " + - "the release this build creates. Remove the assignment.", + "the release this build creates. Remove posthog.releaseMode, or the " + + "releaseMode assignment on this task.", ) } - // The mapping always binds to the release this build creates. posthog-cli reads - // POSTHOG_RELEASE_MODE for `proguard upload`, and an Exec task inherits the daemon - // environment, so a value set for another tool would otherwise leave the mapping - // release-independent. Pin it. A posthog-cli that has no such flag ignores the variable. + // POSTHOG_RELEASE_MODE=event used to select event mode here too, so a build that still + // carries it gets told that the mapping binds again. The variable keeps steering the + // PostHog sourcemap and hermes uploads, so the message does not ask to remove it. + val inheritedReleaseMode = System.getenv("POSTHOG_RELEASE_MODE")?.trim() + if (!inheritedReleaseMode.isNullOrEmpty() && inheritedReleaseMode != "symbol-set") { + logger.warn( + "[PostHog] POSTHOG_RELEASE_MODE no longer affects the proguard mapping upload. " + + "The mapping uploads bound to the release this build creates.", + ) + } + + // The mapping always binds to the release this build creates. posthog-cli 0.13.0 up to + // the release that carries PostHog/posthog#92401 reads POSTHOG_RELEASE_MODE on `proguard + // upload`, and an Exec task inherits the daemon environment, so a value set for another + // tool would leave the mapping release-independent on those versions. Pin it. Older and + // newer CLIs ignore the variable, so the pin can go once that range has aged out. environment("POSTHOG_RELEASE_MODE", "symbol-set") super.exec() } @@ -138,6 +154,10 @@ public abstract class PostHogUploadProguardMappingsTask : PostHogCliExecTask() { releaseName?.let { this.releaseName.set(it) } releaseVersion?.let { this.releaseVersion.set(it) } build?.let { this.build.set(it) } + // Feeds the deprecated property into the execution-time warning above. + // gradleProperty is the configuration-cache-safe read. + @Suppress("DEPRECATION") + this.releaseMode.set(project.providers.gradleProperty(POSTHOG_RELEASE_MODE_PROPERTY)) resolvePostHogDotenvFile(project)?.let { this.postHogDotenvFile.set(it) } } return uploadPostHogProguardMappingsTask