Skip to content

Commit

Permalink
RUM-713 Allow customer to use non standard obfuscation
Browse files Browse the repository at this point in the history
  • Loading branch information
xgouchet committed Oct 10, 2023
1 parent 288840c commit 8bdb7c1
Show file tree
Hide file tree
Showing 6 changed files with 232 additions and 31 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ class DdAndroidGradlePlugin @Inject constructor(
val androidExtension = target.extensions.findByType(AppExtension::class.java)
if (androidExtension == null) {
LOGGER.error(ERROR_NOT_ANDROID)
} else if (!extension.enabled) {
LOGGER.info("Datadog extension disabled, no upload task created")
} else {
androidExtension.applicationVariants.all { variant ->
configureVariantForUploadTask(target, variant, apiKey, extension)
Expand Down Expand Up @@ -73,13 +75,13 @@ class DdAndroidGradlePlugin @Inject constructor(
apiKey: ApiKey,
extension: DdExtension
): Task? {
if (!variant.buildType.isMinifyEnabled) {
LOGGER.info("Minifying disabled for variant ${variant.name}, no upload task created")
return null
}
val extensionConfiguration = resolveExtensionConfiguration(extension, variant)
val isDefaultObfuscationEnabled = variant.buildType.isMinifyEnabled
val isNonDefaultObfuscationEnabled = extensionConfiguration.nonDefaultObfuscation
val isObfuscationEnabled = isDefaultObfuscationEnabled || isNonDefaultObfuscationEnabled

if (!extension.enabled) {
LOGGER.info("Extension disabled for variant ${variant.name}, no upload task created")
if (!isObfuscationEnabled) {
LOGGER.info("Minifying disabled for variant ${variant.name}, no upload task created")
return null
}

Expand All @@ -91,13 +93,10 @@ class DdAndroidGradlePlugin @Inject constructor(
DdMappingFileUploadTask::class.java,
GitRepositoryDetector(execOps)
)
val extensionConfiguration = resolveExtensionConfiguration(extension, variant)

configureVariantTask(uploadTask, apiKey, flavorName, extensionConfiguration, variant)

val outputsDir = File(target.buildDir, "outputs")
uploadTask.mappingFilePath =
resolveMappingFilePath(extensionConfiguration, outputsDir, variant)
uploadTask.mappingFilePath = resolveMappingFilePath(extensionConfiguration, target, variant)
uploadTask.mappingFilePackagesAliases =
filterMappingFileReplacements(
extensionConfiguration.mappingFilePackageAliases,
Expand All @@ -108,9 +107,7 @@ class DdAndroidGradlePlugin @Inject constructor(
uploadTask.datadogCiFile = findDatadogCiFile(target.projectDir)
}

val reportsDir = File(outputsDir, "reports")
val datadogDir = File(reportsDir, "datadog")
uploadTask.repositoryFile = File(datadogDir, "repository.json")
uploadTask.repositoryFile = resolveDatadogRepositoryFile(target)

val roots = mutableListOf<File>()
variant.sourceSets.forEach {
Expand Down Expand Up @@ -187,19 +184,27 @@ class DdAndroidGradlePlugin @Inject constructor(

private fun resolveMappingFilePath(
extensionConfiguration: DdExtensionConfiguration,
outputsDir: File,
target: Project,
variant: ApplicationVariant
): String {
val customPath = extensionConfiguration.mappingFilePath
return if (customPath != null) {
customPath
} else {
val outputsDir = File(target.buildDir, "outputs")
val mappingDir = File(outputsDir, "mapping")
val flavorDir = File(mappingDir, variant.name)
File(flavorDir, "mapping.txt").path
}
}

private fun resolveDatadogRepositoryFile(target: Project): File {
val outputsDir = File(target.buildDir, "outputs")
val reportsDir = File(outputsDir, "reports")
val datadogDir = File(reportsDir, "datadog")
return File(datadogDir, "repository.json")
}

private fun filterMappingFileReplacements(
replacements: Map<String, String>,
applicationId: String
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,13 @@ open class DdExtensionConfiguration(
*/
var mappingFileTrimIndents: Boolean = false

/**
* This property declares that the obfuscation technology used is not the default
* R8/Proguard included in the Android toolchain (e.g.: Dexguard, …).
* Doing so will create an upload task for all variants and all
*/
var nonDefaultObfuscation: Boolean = false

/**
* Ignore the config declared in `datadog-ci.json` file if found.
*/
Expand All @@ -98,5 +105,6 @@ open class DdExtensionConfiguration(
mappingFilePackageAliases = config.mappingFilePackageAliases
mappingFileTrimIndents = config.mappingFileTrimIndents
ignoreDatadogCiFileConfig = config.ignoreDatadogCiFileConfig
nonDefaultObfuscation = config.nonDefaultObfuscation
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,45 @@ internal class DdAndroidGradlePluginFunctionalTest {
.isEqualTo(TaskOutcome.SUCCESS)
}

@Test
fun `M success W assembleDebug { non default obfuscation }`() {
// Given
stubGradleBuildFromResourceFile(
"build_with_non_default_obfuscation.gradle",
appBuildGradleFile
)
// When
val result = GradleRunner.create()
.withProjectDir(testProjectDir)
.withArguments(":samples:app:assembleDebug")
.withPluginClasspath(getTestConfigurationClasspath())
.build()

// Then
assertThat(result.task(":samples:app:assembleDebug")?.outcome)
.isEqualTo(TaskOutcome.SUCCESS)
}

@Test
fun `M success W assembleDebug { plugin disabled }`() {
// Given
stubGradleBuildFromResourceFile(
"build_with_plugin_disabled.gradle",
appBuildGradleFile
)
// When
val result = GradleRunner.create()
.withProjectDir(testProjectDir)
.withArguments(":samples:app:assembleDebug")
.withPluginClasspath(getTestConfigurationClasspath())
.build()

// Then
assertThat(result.task(":samples:app:assembleDebug")?.outcome)
.isEqualTo(TaskOutcome.SUCCESS)
assertThat(result.output).contains("Datadog extension disabled, no upload task created")
}

@Test
fun `M success W assembleDebug { build cache }`() {
// Given
Expand Down Expand Up @@ -486,7 +525,7 @@ internal class DdAndroidGradlePluginFunctionalTest {

val result = GradleRunner.create()
.withProjectDir(testProjectDir)
.withArguments(taskName, "--info", "-PDD_API_KEY=fakekey")
.withArguments(taskName, "--info", "--stacktrace", "-PDD_API_KEY=fakekey")
.withPluginClasspath(getTestConfigurationClasspath())
.buildAndFail()

Expand Down Expand Up @@ -525,7 +564,7 @@ internal class DdAndroidGradlePluginFunctionalTest {

val result = GradleRunner.create()
.withProjectDir(testProjectDir)
.withArguments(taskName, "--info", "-PDD_API_KEY=fakekey", "-Pdd-disable-gzip")
.withArguments(taskName, "--info", "--stacktrace", "-PDD_API_KEY=fakekey", "-Pdd-disable-gzip")
.withPluginClasspath(getTestConfigurationClasspath())
.buildAndFail()

Expand Down Expand Up @@ -611,7 +650,7 @@ internal class DdAndroidGradlePluginFunctionalTest {

val result = GradleRunner.create()
.withProjectDir(testProjectDir)
.withArguments(taskName, "--info", "-PDD_API_KEY=fakekey")
.withArguments(taskName, "--info", "--stacktrace", "-PDD_API_KEY=fakekey")
.withPluginClasspath(getTestConfigurationClasspath())
.buildAndFail()

Expand Down Expand Up @@ -649,7 +688,7 @@ internal class DdAndroidGradlePluginFunctionalTest {

val result = GradleRunner.create()
.withProjectDir(testProjectDir)
.withArguments(taskName, "--info", "-PDD_API_KEY=fakekey")
.withArguments(taskName, "--info", "--stacktrace", "-PDD_API_KEY=fakekey")
.withPluginClasspath(getTestConfigurationClasspath())
.buildAndFail()

Expand Down Expand Up @@ -693,7 +732,7 @@ internal class DdAndroidGradlePluginFunctionalTest {

val result = GradleRunner.create()
.withProjectDir(testProjectDir)
.withArguments(taskName, "--info", "-PDD_API_KEY=fakekey")
.withArguments(taskName, "--info", "--stacktrace", "-PDD_API_KEY=fakekey")
.withPluginClasspath(getTestConfigurationClasspath())
.buildAndFail()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,7 @@ internal class DdAndroidGradlePluginTest {
fakeExtension.mappingFilePackageAliases = emptyMap()
fakeExtension.mappingFileTrimIndents = false
val variantName = "$flavorName${buildTypeName.replaceFirstChar { capitalizeChar(it) }}"
val fakeMappingFilePath = "${fakeProject.buildDir}/outputs/mapping/$variantName/mapping.txt"
whenever(mockVariant.name) doReturn variantName
whenever(mockVariant.flavorName) doReturn flavorName
whenever(mockVariant.versionName) doReturn versionName
Expand Down Expand Up @@ -279,8 +280,7 @@ internal class DdAndroidGradlePluginTest {
assertThat(task.serviceName).isEqualTo(packageName)
assertThat(task.remoteRepositoryUrl).isEmpty()
assertThat(task.site).isEqualTo("")
assertThat(task.mappingFilePath)
.isEqualTo("${fakeProject.buildDir}/outputs/mapping/$variantName/mapping.txt")
assertThat(task.mappingFilePath).isEqualTo(fakeMappingFilePath)
assertThat(task.mappingFilePackagesAliases).isEmpty()
assertThat(task.mappingFileTrimIndents).isFalse
assertThat(task.datadogCiFile).isNull()
Expand All @@ -303,6 +303,7 @@ internal class DdAndroidGradlePluginTest {
fakeExtension.mappingFileTrimIndents = false
fakeExtension.ignoreDatadogCiFileConfig = false
val variantName = "$flavorName${buildTypeName.replaceFirstChar { capitalizeChar(it) }}"
val fakeMappingFilePath = "${fakeProject.buildDir}/outputs/mapping/$variantName/mapping.txt"
whenever(mockVariant.name) doReturn variantName
whenever(mockVariant.flavorName) doReturn flavorName
whenever(mockVariant.versionName) doReturn versionName
Expand Down Expand Up @@ -335,8 +336,7 @@ internal class DdAndroidGradlePluginTest {
assertThat(task.serviceName).isEqualTo(packageName)
assertThat(task.remoteRepositoryUrl).isEmpty()
assertThat(task.site).isEqualTo("")
assertThat(task.mappingFilePath)
.isEqualTo("${fakeProject.buildDir}/outputs/mapping/$variantName/mapping.txt")
assertThat(task.mappingFilePath).isEqualTo(fakeMappingFilePath)
assertThat(task.mappingFilePackagesAliases).isEmpty()
assertThat(task.mappingFileTrimIndents).isFalse
assertThat(task.datadogCiFile).isEqualTo(fakeDatadogCiFile)
Expand All @@ -359,6 +359,7 @@ internal class DdAndroidGradlePluginTest {
fakeExtension.mappingFileTrimIndents = false
fakeExtension.ignoreDatadogCiFileConfig = true
val variantName = "$flavorName${buildTypeName.replaceFirstChar { capitalizeChar(it) }}"
val fakeMappingFilePath = "${fakeProject.buildDir}/outputs/mapping/$variantName/mapping.txt"
whenever(mockVariant.name) doReturn variantName
whenever(mockVariant.flavorName) doReturn flavorName
whenever(mockVariant.versionName) doReturn versionName
Expand Down Expand Up @@ -391,15 +392,14 @@ internal class DdAndroidGradlePluginTest {
assertThat(task.serviceName).isEqualTo(packageName)
assertThat(task.remoteRepositoryUrl).isEmpty()
assertThat(task.site).isEqualTo("")
assertThat(task.mappingFilePath)
.isEqualTo("${fakeProject.buildDir}/outputs/mapping/$variantName/mapping.txt")
assertThat(task.mappingFilePath).isEqualTo(fakeMappingFilePath)
assertThat(task.mappingFilePackagesAliases).isEmpty()
assertThat(task.mappingFileTrimIndents).isFalse
assertThat(task.datadogCiFile).isNull()
}

@Test
fun `𝕄 do nothing 𝕎 configureVariant() {minify disabled}`(
fun `𝕄 do nothing 𝕎 configureVariant() { no deobfuscation }`(
@StringForgery(case = Case.LOWER) flavorName: String,
@StringForgery(case = Case.LOWER) buildTypeName: String,
@StringForgery versionName: String,
Expand All @@ -412,7 +412,6 @@ internal class DdAndroidGradlePluginTest {
whenever(mockVariant.versionName) doReturn versionName
whenever(mockVariant.applicationId) doReturn packageName
whenever(mockVariant.buildType) doReturn mockBuildType
whenever(mockBuildType.isMinifyEnabled) doReturn false
whenever(mockBuildType.name) doReturn fakeBuildTypeName

// When
Expand All @@ -428,21 +427,21 @@ internal class DdAndroidGradlePluginTest {
}

@Test
fun `𝕄 do nothing 𝕎 configureVariant() {plugin disabled}`(
fun `𝕄 configure the upload task 𝕎 configureVariant() { non default obfuscation }`(
@StringForgery(case = Case.LOWER) flavorName: String,
@StringForgery(case = Case.LOWER) buildTypeName: String,
@StringForgery versionName: String,
@StringForgery packageName: String
) {
// Given
fakeExtension.enabled = false
fakeExtension.nonDefaultObfuscation = true
val variantName = "$flavorName${buildTypeName.replaceFirstChar { capitalizeChar(it) }}"
whenever(mockVariant.name) doReturn variantName
whenever(mockVariant.flavorName) doReturn flavorName
whenever(mockVariant.versionName) doReturn versionName
whenever(mockVariant.applicationId) doReturn packageName
whenever(mockVariant.buildType) doReturn mockBuildType
whenever(mockBuildType.isMinifyEnabled) doReturn true
whenever(mockBuildType.isMinifyEnabled) doReturn false
whenever(mockBuildType.name) doReturn fakeBuildTypeName

// When
Expand All @@ -454,7 +453,24 @@ internal class DdAndroidGradlePluginTest {
)

// Then
assertThat(task).isNull()
check(task is DdMappingFileUploadTask)
assertThat(task.repositoryDetector).isInstanceOf(GitRepositoryDetector::class.java)
assertThat(task.name).isEqualTo(
"uploadMapping${variantName.replaceFirstChar { capitalizeChar(it) }}"
)
assertThat(task.apiKey).isEqualTo(fakeApiKey.value)
assertThat(task.apiKeySource).isEqualTo(fakeApiKey.source)
assertThat(task.variantName).isEqualTo(flavorName)
assertThat(task.versionName).isEqualTo(fakeExtension.versionName)
assertThat(task.serviceName).isEqualTo(fakeExtension.serviceName)
assertThat(task.site).isEqualTo(fakeExtension.site)
assertThat(task.remoteRepositoryUrl).isEqualTo(fakeExtension.remoteRepositoryUrl)
assertThat(task.mappingFilePath).isEqualTo(fakeExtension.mappingFilePath)
assertThat(task.mappingFilePackagesAliases)
.isEqualTo(fakeExtension.mappingFilePackageAliases)
assertThat(task.mappingFileTrimIndents)
.isEqualTo(fakeExtension.mappingFileTrimIndents)
assertThat(task.datadogCiFile).isNull()
}

// endregion
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
plugins {
id("com.android.application")
id("kotlin-android")
id("com.datadoghq.dd-sdk-android-gradle-plugin")
}

repositories {
google()
mavenCentral()
}

android {
compileSdkVersion = 31
buildToolsVersion = "31.0.0"

defaultConfig {
applicationId "com.example.variants"
minSdkVersion 21
targetSdkVersion 31
versionCode 1
versionName "1.0"
multiDexEnabled = true
}

buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile ('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}

compileOptions {
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
}

flavorDimensions("version", "colour")
productFlavors {
demo {
dimension "version"
applicationIdSuffix ".demo"
versionNameSuffix "-demo"
}
full {
dimension "version"
applicationIdSuffix ".full"
versionNameSuffix "-full"
}

green {
dimension "colour"
}
blue {
dimension "colour"
}
}
}

dependencies {
implementation(project(':samples:lib-module'))
implementation("com.datadoghq:dd-sdk-android:1.18.0")
}

datadog {
enabled = false
nonDefaultObfuscation = true
}
Loading

0 comments on commit 8bdb7c1

Please sign in to comment.