diff --git a/dd-sdk-android-gradle-plugin/src/main/kotlin/com/datadog/gradle/plugin/DdAndroidGradlePlugin.kt b/dd-sdk-android-gradle-plugin/src/main/kotlin/com/datadog/gradle/plugin/DdAndroidGradlePlugin.kt index a690f29..8769e1d 100644 --- a/dd-sdk-android-gradle-plugin/src/main/kotlin/com/datadog/gradle/plugin/DdAndroidGradlePlugin.kt +++ b/dd-sdk-android-gradle-plugin/src/main/kotlin/com/datadog/gradle/plugin/DdAndroidGradlePlugin.kt @@ -21,6 +21,7 @@ import org.gradle.api.Project import org.gradle.api.Task import org.gradle.api.file.RegularFile import org.gradle.api.logging.Logging +import org.gradle.api.model.ObjectFactory import org.gradle.api.provider.Provider import org.gradle.api.provider.ProviderFactory import org.gradle.api.tasks.TaskContainer @@ -210,12 +211,15 @@ class DdAndroidGradlePlugin @Inject constructor( ) } val extensionConfiguration = resolveExtensionConfiguration(extension, variant) - configureVariantTask(uploadTask, apiKey, variant.flavorName, extensionConfiguration, variant) + configureVariantTask( + target.objects, + uploadTask, + apiKey, + extensionConfiguration, + variant + ) uploadTask.buildId.set(buildIdGenerationTask.lazyBuildIdProvider(providerFactory)) - - uploadTask.applicationId.set(variant.applicationId) - uploadTask.mappingFile.set(resolveMappingFile(extensionConfiguration, target, variant)) uploadTask.mappingFilePackagesAliases = extensionConfiguration.mappingFilePackageAliases uploadTask.mappingFileTrimIndents = extensionConfiguration.mappingFileTrimIndents if (!extensionConfiguration.ignoreDatadogCiFileConfig) { @@ -223,7 +227,6 @@ class DdAndroidGradlePlugin @Inject constructor( } uploadTask.repositoryFile = TaskUtils.resolveDatadogRepositoryFile(target) - uploadTask.sourceSetRoots.set(variant.collectJavaAndKotlinSourceDirectories()) } } @@ -296,27 +299,32 @@ class DdAndroidGradlePlugin @Inject constructor( private fun resolveMappingFile( extensionConfiguration: DdExtensionConfiguration, - target: Project, + objectFactory: ObjectFactory, variant: AppVariant ): Provider { val customPath = extensionConfiguration.mappingFilePath return if (customPath != null) { - target.objects.fileProperty().fileValue(File(customPath)) + objectFactory.fileProperty().fileValue(File(customPath)) } else { variant.mappingFile } } private fun configureVariantTask( + objectFactory: ObjectFactory, uploadTask: MappingFileUploadTask, apiKey: ApiKey, - flavorName: String, extensionConfiguration: DdExtensionConfiguration, variant: AppVariant ) { uploadTask.apiKey = apiKey.value uploadTask.apiKeySource = apiKey.source - uploadTask.variantName = flavorName + uploadTask.variantName = variant.flavorName + + uploadTask.applicationId.set(variant.applicationId) + + uploadTask.mappingFile.set(resolveMappingFile(extensionConfiguration, objectFactory, variant)) + uploadTask.sourceSetRoots.set(variant.collectJavaAndKotlinSourceDirectories()) uploadTask.site = extensionConfiguration.site ?: "" if (extensionConfiguration.versionName != null) { @@ -331,6 +339,8 @@ class DdAndroidGradlePlugin @Inject constructor( uploadTask.serviceName.set(variant.applicationId) } uploadTask.remoteRepositoryUrl = extensionConfiguration.remoteRepositoryUrl ?: "" + + variant.bindWith(uploadTask) } internal fun resolveExtensionConfiguration( diff --git a/dd-sdk-android-gradle-plugin/src/main/kotlin/com/datadog/gradle/plugin/internal/CurrentAgpVersion.kt b/dd-sdk-android-gradle-plugin/src/main/kotlin/com/datadog/gradle/plugin/internal/CurrentAgpVersion.kt index 4257439..8d99fa7 100644 --- a/dd-sdk-android-gradle-plugin/src/main/kotlin/com/datadog/gradle/plugin/internal/CurrentAgpVersion.kt +++ b/dd-sdk-android-gradle-plugin/src/main/kotlin/com/datadog/gradle/plugin/internal/CurrentAgpVersion.kt @@ -20,4 +20,7 @@ internal object CurrentAgpVersion { val EXTERNAL_NATIVE_BUILD_SOFOLDER_IS_PUBLIC: Boolean get() = TaskUtils.isAgpAbove(major = 8, minor = 0, patch = 0) + + val CAN_QUERY_MAPPING_FILE_PROVIDER: Boolean + get() = TaskUtils.isAgpAbove(major = 7, minor = 0, patch = 0) } diff --git a/dd-sdk-android-gradle-plugin/src/main/kotlin/com/datadog/gradle/plugin/internal/variant/AppVariant.kt b/dd-sdk-android-gradle-plugin/src/main/kotlin/com/datadog/gradle/plugin/internal/variant/AppVariant.kt index 09e8c6e..249d3be 100644 --- a/dd-sdk-android-gradle-plugin/src/main/kotlin/com/datadog/gradle/plugin/internal/variant/AppVariant.kt +++ b/dd-sdk-android-gradle-plugin/src/main/kotlin/com/datadog/gradle/plugin/internal/variant/AppVariant.kt @@ -8,6 +8,7 @@ package com.datadog.gradle.plugin.internal.variant import com.android.build.gradle.AppExtension import com.datadog.gradle.plugin.GenerateBuildIdTask +import com.datadog.gradle.plugin.MappingFileUploadTask import com.datadog.gradle.plugin.NdkSymbolFileUploadTask import org.gradle.api.Project import org.gradle.api.artifacts.Configuration @@ -47,6 +48,8 @@ internal interface AppVariant { fun bindWith(ndkUploadTask: NdkSymbolFileUploadTask) + fun bindWith(mappingFileUploadTask: MappingFileUploadTask) + // new variant API doesn't allow to run addGeneratedSourceDirectory from inside Task#configure, thus this fun bindWith(generateBuildIdTask: TaskProvider, buildIdDirectory: Provider) diff --git a/dd-sdk-android-gradle-plugin/src/main/kotlin/com/datadog/gradle/plugin/internal/variant/LegacyApiAppVariant.kt b/dd-sdk-android-gradle-plugin/src/main/kotlin/com/datadog/gradle/plugin/internal/variant/LegacyApiAppVariant.kt index 04ba945..e0d4a96 100644 --- a/dd-sdk-android-gradle-plugin/src/main/kotlin/com/datadog/gradle/plugin/internal/variant/LegacyApiAppVariant.kt +++ b/dd-sdk-android-gradle-plugin/src/main/kotlin/com/datadog/gradle/plugin/internal/variant/LegacyApiAppVariant.kt @@ -8,7 +8,9 @@ package com.datadog.gradle.plugin.internal.variant import com.android.build.gradle.AppExtension import com.android.build.gradle.api.ApplicationVariant +import com.datadog.gradle.plugin.DdAndroidGradlePlugin import com.datadog.gradle.plugin.GenerateBuildIdTask +import com.datadog.gradle.plugin.MappingFileUploadTask import com.datadog.gradle.plugin.NdkSymbolFileUploadTask import com.datadog.gradle.plugin.internal.CurrentAgpVersion import com.datadog.gradle.plugin.internal.getSearchObjDirs @@ -19,6 +21,7 @@ import org.gradle.api.file.RegularFile import org.gradle.api.provider.Provider import org.gradle.api.tasks.TaskProvider import java.io.File +import java.nio.file.Path import java.nio.file.Paths internal class LegacyApiAppVariant( @@ -28,6 +31,7 @@ internal class LegacyApiAppVariant( ) : AppVariant { private val providerFactory = target.providers + private val projectLayout = target.layout override val name: String get() = variant.name @@ -50,9 +54,30 @@ internal class LegacyApiAppVariant( override val flavors: List get() = variant.productFlavors.map { it.name } override val mappingFile: Provider - get() = target.layout.buildDirectory.file( - Paths.get("outputs", "mapping", variant.name, "mapping.txt").toString() - ) + get() = if (CurrentAgpVersion.CAN_QUERY_MAPPING_FILE_PROVIDER) { + variant.mappingFileProvider + .flatMap { + providerFactory.provider { + try { + projectLayout.projectDirectory.file(it.singleFile.absolutePath) + } catch (e: IllegalStateException) { + DdAndroidGradlePlugin.LOGGER.info( + "Mapping FileCollection is empty or contains multiple files", + e + ) + null + } + }.orElse(legacyMappingFileProvider) + } + } else { + legacyMappingFileProvider + } + + private val legacyMappingFileProvider: Provider + get() = projectLayout.buildDirectory.file(legacyMappingFilePath.toString()) + + private val legacyMappingFilePath: Path + get() = Paths.get("outputs", "mapping", variant.name, "mapping.txt") override fun collectJavaAndKotlinSourceDirectories(): Provider> { val roots = mutableListOf() @@ -75,6 +100,11 @@ internal class LegacyApiAppVariant( } } + override fun bindWith(mappingFileUploadTask: MappingFileUploadTask) { + val minifyTask = target.tasks.findByName("minify${variant.name.capitalize()}WithR8") ?: return + mappingFileUploadTask.dependsOn(minifyTask) + } + override fun bindWith( generateBuildIdTask: TaskProvider, buildIdDirectory: Provider diff --git a/dd-sdk-android-gradle-plugin/src/main/kotlin/com/datadog/gradle/plugin/internal/variant/NewApiAppVariant.kt b/dd-sdk-android-gradle-plugin/src/main/kotlin/com/datadog/gradle/plugin/internal/variant/NewApiAppVariant.kt index 05c0e7f..fbe0fc8 100644 --- a/dd-sdk-android-gradle-plugin/src/main/kotlin/com/datadog/gradle/plugin/internal/variant/NewApiAppVariant.kt +++ b/dd-sdk-android-gradle-plugin/src/main/kotlin/com/datadog/gradle/plugin/internal/variant/NewApiAppVariant.kt @@ -11,6 +11,7 @@ import com.android.build.api.variant.ApplicationVariant import com.android.build.api.variant.VariantOutput import com.android.build.gradle.tasks.ExternalNativeBuildTask import com.datadog.gradle.plugin.GenerateBuildIdTask +import com.datadog.gradle.plugin.MappingFileUploadTask import com.datadog.gradle.plugin.NdkSymbolFileUploadTask import com.datadog.gradle.plugin.internal.getSearchObjDirs import org.gradle.api.Project @@ -78,6 +79,10 @@ internal class NewApiAppVariant( } } + override fun bindWith(mappingFileUploadTask: MappingFileUploadTask) { + // nothing is needed, dependency on minification task is created by mapping file provider + } + override fun bindWith( generateBuildIdTask: TaskProvider, buildIdDirectory: Provider diff --git a/dd-sdk-android-gradle-plugin/src/test/kotlin/com/datadog/gradle/plugin/internal/variant/LegacyApiAppVariantTest.kt b/dd-sdk-android-gradle-plugin/src/test/kotlin/com/datadog/gradle/plugin/internal/variant/LegacyApiAppVariantTest.kt index a8e4bfc..e7ff259 100644 --- a/dd-sdk-android-gradle-plugin/src/test/kotlin/com/datadog/gradle/plugin/internal/variant/LegacyApiAppVariantTest.kt +++ b/dd-sdk-android-gradle-plugin/src/test/kotlin/com/datadog/gradle/plugin/internal/variant/LegacyApiAppVariantTest.kt @@ -240,9 +240,56 @@ internal class LegacyApiAppVariantTest { @Test fun `M return mapping file W mappingFile`( + @TempDir fakeMappingDirectory: File, + @StringForgery fakeVariantName: String, + @StringForgery fakeMappingFileName: String + ) { + // Given + val fakeMappingFile = File(fakeMappingDirectory, fakeMappingFileName) + whenever( + mockAndroidVariant.mappingFileProvider + ) doReturn fakeProject.provider { fakeProject.files(fakeMappingFile) } + whenever(mockAndroidVariant.name) doReturn fakeVariantName + + // When + val mappingFile = testedAppVariant.mappingFile + + // Then + assertThat(mappingFile.get().asFile).isEqualTo(fakeMappingFile) + } + + @Test + fun `M return mapping file W mappingFile { fallback to legacy, no mapping files in provider }`( @StringForgery fakeVariantName: String ) { // Given + whenever( + mockAndroidVariant.mappingFileProvider + ) doReturn fakeProject.provider { fakeProject.files() } + whenever(mockAndroidVariant.name) doReturn fakeVariantName + + // When + val mappingFile = testedAppVariant.mappingFile + + // Then + assertThat(mappingFile.get().asFile.path).endsWith( + Paths.get("outputs", "mapping", fakeVariantName, "mapping.txt").toString() + ) + } + + @Test + fun `M return mapping file W mappingFile { fallback to legacy, multiple files in provider }`( + @TempDir fakeMappingDirectory: File, + @StringForgery fakeVariantName: String, + @StringForgery fakeMappingFileNameA: String, + @StringForgery fakeMappingFileNameB: String + ) { + // Given + val fileA = File(fakeMappingDirectory, fakeMappingFileNameA) + val fileB = File(fakeMappingDirectory, fakeMappingFileNameB) + whenever( + mockAndroidVariant.mappingFileProvider + ) doReturn fakeProject.provider { fakeProject.files(fileA, fileB) } whenever(mockAndroidVariant.name) doReturn fakeVariantName // When