Skip to content

Commit fee390c

Browse files
committed
RUM-16370: Support Android API 37
1 parent d4b6be3 commit fee390c

203 files changed

Lines changed: 999 additions & 1068 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.gitlab-ci.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,11 @@ variables:
1919

2020
CACHE_FALLBACK_KEY: "develop"
2121

22+
# Unify the Gradle user home across ALL jobs so every Gradle invocation shares one
23+
# GitLab-cacheable location ($CI_PROJECT_DIR/cache) instead of some jobs using the default,
24+
# non-cached /root/.gradle. Jobs that pass --gradle-user-home cache/ already match this.
25+
GRADLE_USER_HOME: "$CI_PROJECT_DIR/cache"
26+
2227
# Magic Mirror Depot proxy URLs. The depot proxies both Maven Central and the Gradle
2328
# Plugin Portal for the Java ecosystem from the same endpoint. Setting these routes
2429
# dependency/plugin resolution through Datadog's internal mirror to avoid HTTP 429

LICENSE-3rdparty.csv

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@ import,androidx.versionedparcelable,Apache-2.0,Copyright 2018 The Android Open S
5252
import,androidx.viewpager,Apache-2.0,Copyright 2018 The Android Open Source Project
5353
import,androidx.wear,Apache-2.0,Copyright 2018 The Android Open Source Project
5454
import,androidx.work,Apache-2.0,Copyright 2018 The Android Open Source Project
55+
import,app.cash.sql-psi,Apache-2.0,"Copyright 2016 Square, Inc"
56+
import,app.cash.sqldelight,Apache-2.0,"Copyright 2016 Square, Inc"
5557
import,com.android.tools,Apache-2.0,Copyright 2018 The Android Open Source Project
5658
import,com.apollographql.apollo,MIT,"Copyright (c) 2016-2024 Apollo Graph, Inc. (Formerly Meteor Development Group, Inc.)"
5759
import,com.benasher44,MIT,"Copyright (c) 2019 Ben Asher"
@@ -140,6 +142,7 @@ import(test),com.jakewharton.android.repackaged,Apache-2.0,"Copyright (C) 2007 T
140142
import(test),com.parse.bolts,"BSD License","Copyright (c) Facebook, Inc. and its affiliates."
141143
import(test),com.squareup,Apache-2.0,"Copyright 2015 Square, Inc."
142144
import(test),dev.drewhamilton.poko,Apache-2.0,Copyright 2020-Present Drew Hamilton
145+
import(test),dev.zacsweers.kctfork,MPL-2.0,Copyright (C) 2022 Zac Sweers
143146
import(test),greatest,ICT,"Copyright (c) 2011-2018 Scott Vokes <vokes.s@gmail.com>"
144147
import(test),io.github.davidburstrom.contester,Apache-2.0,"Copyright 2022-2024 David Burström"
145148
import(test),io.github.detekt.sarif4k,Apache-2.0,"Copyright 2021 Artur Bosch & Contributors"
@@ -183,7 +186,6 @@ build,com.fasterxml.jackson.core,Apache-2.0,"Copyright (c) 2007- Tatu Saloranta"
183186
build,com.fasterxml.jackson.dataformat,Apache-2.,"Copyright (c) 2007- Tatu Saloranta"
184187
build,com.fasterxml.jackson.module,Apache-2.0,"Copyright (c) 2007- Tatu Saloranta"
185188
build,com.fasterxml.woodstox,Apache-2.0,"Copyright (c) 2007- Tatu Saloranta"
186-
build,com.github.tschuchortdev,MPL-2.0,"Copyright (C) 2023 Thilo Schuchort"
187189
build,com.google.android,Apache-2.0,Copyright (C) 2013 The Android Open Source Project
188190
build,com.google.api.grpc,Apache-2.0,Copyright 2020 Google LLC
189191
build,com.google.auto,Apache-2.0,"Copyright 2014 Google LLC"
@@ -208,6 +210,7 @@ build,commons-io,Apache-2.0,Copyright 2002-2024 The Apache Software Foundation
208210
build,commons-logging,Apache-2.0,Copyright 2002-2024 The Apache Software Foundation
209211
build,io.github.aakira,Apache-2.0,"Copyright (C) 2019 A.Akira"
210212
build,io.github.classgraph,MIT,"Copyright (c) 2019 Luke Hutchison"
213+
build,io.github.java-diff-utils,Apache-2.0,"Copyright java-diff-utils contributors"
211214
build,io.github.microutils,Apache-2.0,Copyright (c) 2016-2018 Ohad Shai
212215
build,io.gitlab.arturbosch.detekt,Apache-2.0,Copyright 2016-2019 the original author or authors
213216
build,io.grpc,Apache-2.0,Copyright 2014 The gRPC Authors

build.gradle.kts

Lines changed: 8 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
*/
66
@file:Suppress("StringLiteralDuplication")
77

8-
import com.android.build.gradle.LibraryExtension
98
import com.datadog.gradle.config.AndroidConfig
109
import com.datadog.gradle.config.depotProxied
1110
import com.datadog.gradle.config.registerSubModuleAggregationTask
@@ -29,7 +28,6 @@ plugins {
2928
// don't add these to the classpath, otherwise there will be a conflict, because they are already coming
3029
// from buildSrc classpath. May be solved with convention plugins though.
3130
// alias(libs.plugins.androidLibraryPlugin) apply false
32-
// alias(libs.plugins.kotlinAndroidPlugin) apply false
3331
// alias(libs.plugins.dokkaGradlePlugin) apply false
3432
// alias(libs.plugins.versionsGradlePlugin) apply false
3533
}
@@ -207,20 +205,14 @@ tasks.register("printSdkDebugRuntimeClasspath") {
207205
allprojects.minus(project).forEach { subproject ->
208206
val childTask = subproject.tasks.register("printDebugRuntimeClasspath") {
209207
doLast {
210-
val ext =
211-
subproject.extensions.findByType(LibraryExtension::class.java) ?: return@doLast
212-
val classpath = ext.libraryVariants
213-
.filter { it.name == "jvmDebug" || it.name == "debug" }
214-
.map { libVariant ->
215-
// returns also test part of classpath for now, no idea how to filter it out
216-
libVariant.getCompileClasspath(null).filter { it.exists() }
217-
}
218-
.first()
219-
if (classpath is FileTree) {
220-
fileTreeClassPathCollector.addToUnion(classpath)
221-
} else {
222-
nonFileTreeClassPathCollector += classpath
223-
}
208+
val config = subproject.configurations.findByName("jvmDebugCompileClasspath")
209+
?: subproject.configurations.findByName("debugCompileClasspath")
210+
?: return@doLast
211+
// Use lenient resolution: AGP 9 variant resolution can fail for local project
212+
// dependencies when kotlin.platform.type attributes are missing on providers.
213+
val classpath = config.incoming.artifactView { isLenient = true }.files
214+
.filter { it.exists() }
215+
nonFileTreeClassPathCollector += classpath
224216
}
225217
}
226218
this@register.dependsOn(childTask)

buildSrc/build.gradle.kts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,10 @@ gradlePlugin {
8585
id = "verificationXml" // the alias
8686
implementationClass = "com.datadog.gradle.plugin.verification.VerificationXmlPlugin"
8787
}
88+
register("unitTestConvention") {
89+
id = "datadog.unit-test" // the alias
90+
implementationClass = "com.datadog.gradle.plugin.config.UnitTestConventionPlugin"
91+
}
8892
}
8993
}
9094

buildSrc/src/main/kotlin/com/datadog/gradle/config/AndroidConfig.kt

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,19 @@ package com.datadog.gradle.config
88

99
import com.android.build.api.dsl.CompileOptions
1010
import com.android.build.api.dsl.LibraryExtension
11+
import com.android.build.api.variant.HostTestBuilder
12+
import com.android.build.api.variant.LibraryAndroidComponentsExtension
13+
import com.android.build.api.variant.LibraryVariantBuilder
1114
import com.datadog.gradle.utils.Version
1215
import org.gradle.api.JavaVersion
1316
import org.gradle.api.Project
1417

1518
object AndroidConfig {
1619

17-
const val TARGET_SDK = 36
20+
const val TARGET_SDK = 37
1821
const val MIN_SDK = 23
1922
const val MIN_SDK_FOR_AUTO = 29
20-
const val BUILD_TOOLS_VERSION = "36.0.0"
23+
const val BUILD_TOOLS_VERSION = "37.0.0"
2124

2225
val VERSION = Version(3, 12, 0, Version.Type.Snapshot)
2326
}
@@ -47,13 +50,12 @@ fun Project.androidLibraryConfig() {
4750
}
4851

4952
sourceSets.all {
50-
java.srcDir("src/$name/kotlin")
53+
java.directories.add("src/$name/kotlin")
5154
}
5255
sourceSets.named("main") {
53-
java.srcDir("build/generated/json2kotlin/main/kotlin")
56+
kotlin.directories.add("build/generated/json2kotlin/main/kotlin")
5457
}
5558

56-
@Suppress("UnstableApiUsage")
5759
testOptions {
5860
unitTests.isReturnDefaultValues = true
5961
}
@@ -86,4 +88,9 @@ fun Project.androidLibraryConfig() {
8688
}
8789
}
8890
}
91+
extensionConfig<LibraryAndroidComponentsExtension> {
92+
beforeVariants { variant: LibraryVariantBuilder ->
93+
variant.hostTests[HostTestBuilder.UNIT_TEST_TYPE]?.enable = true
94+
}
95+
}
8996
}

buildSrc/src/main/kotlin/com/datadog/gradle/config/DetektCustomConfig.kt

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -128,20 +128,29 @@ fun Project.detektCustomConfig() {
128128
args("-ex", "**/*.kts")
129129
args("--jvm-target", "11")
130130

131+
// Resolve project paths at configuration time (config-cache friendly), but defer all
132+
// detekt_classpath file I/O to execution time. The file is produced by the
133+
// printDetektClasspath task, so it may not exist when this task is configured (e.g. while
134+
// computing the task graph for assembleLibrariesRelease). Reading it here would fail task
135+
// creation and break the whole build.
131136
val moduleDependencies = collectTransitiveProjectDependencies(project)
137+
val rootDirPath = rootDir.absolutePath
138+
val detektClasspathFile = File("${projectDir.absolutePath}/detekt_classpath")
132139

133-
val externalDependencies = File("${projectDir.absolutePath}/detekt_classpath").readText()
134-
val moduleDependenciesClasses = moduleDependencies.joinToString(":") {
135-
"${rootDir.absolutePath}${it.replace(':', '/')}/build/extracted/classes.jar"
136-
}
140+
doFirst {
141+
val externalDependencies = detektClasspathFile.readText()
142+
val moduleDependenciesClasses = moduleDependencies.joinToString(":") {
143+
"$rootDirPath${it.replace(':', '/')}/build/extracted/classes.jar"
144+
}
137145

138-
val dependencies = if (moduleDependenciesClasses.isBlank()) {
139-
externalDependencies
140-
} else {
141-
"$externalDependencies:$moduleDependenciesClasses"
142-
}
146+
val dependencies = if (moduleDependenciesClasses.isBlank()) {
147+
externalDependencies
148+
} else {
149+
"$externalDependencies:$moduleDependenciesClasses"
150+
}
143151

144-
args("-cp", dependencies)
152+
args("-cp", dependencies)
153+
}
145154
}
146155
}
147156

buildSrc/src/main/kotlin/com/datadog/gradle/config/KotlinConfig.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ fun Project.kotlinConfig(
2121
jvmTarget.set(jvmBytecodeTarget)
2222
val isCI = System.getenv("CI").toBoolean()
2323
allWarningsAsErrors.set(evaluateWarningsAsErrors && isCI)
24-
apiVersion.set(KotlinVersion.KOTLIN_1_8)
25-
languageVersion.set(KotlinVersion.KOTLIN_1_8)
24+
apiVersion.set(KotlinVersion.KOTLIN_2_1)
25+
languageVersion.set(KotlinVersion.KOTLIN_2_1)
2626
}
2727
}
2828
}

buildSrc/src/main/kotlin/com/datadog/gradle/config/TestPyramidConfig.kt

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,16 @@ fun Project.registerSubModuleAggregationTask(
2323
subProject.name.startsWith(subModuleNamePrefix) &&
2424
subProject.path.startsWith(subModulePathPrefix)
2525
) {
26-
dependsOn("${subProject.path}:$subModuleTaskName")
26+
// Depend on the task only if the submodule actually registers it, without
27+
// realizing every task. `tasks.names` lists registered task names without
28+
// configuring them, and `named()` returns a lazy provider. Using
29+
// `tasks.matching {}` here instead would configure every task in the submodule
30+
// (to evaluate the name predicate), which prematurely triggers configuration-time
31+
// work in unrelated tasks. A plain `dependsOn("path:task")` would throw when a
32+
// matched submodule doesn't register the task (e.g. printDetektClasspath).
33+
if (subModuleTaskName in subProject.tasks.names) {
34+
dependsOn(subProject.tasks.named(subModuleTaskName))
35+
}
2736
}
2837
}
2938
additionalConfiguration()

buildSrc/src/main/kotlin/com/datadog/gradle/plugin/apisurface/ApiSurfacePlugin.kt

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ class ApiSurfacePlugin : Plugin<Project> {
4040
this.kotlinSurfaceFile.set(generateApiSurfaceTask.flatMap { it.surfaceFile })
4141
if (target.plugins.hasPlugin(GEN_JAVA_API_LAYOUT_PLUGIN)) {
4242
this.javaSurfaceFile.set(javaSurfaceFile)
43-
dependsOn(TASK_GEN_JAVA_API_SURFACE)
43+
dependsOn(target.tasks.matching { it.name == TASK_GEN_JAVA_API_SURFACE })
4444
} else {
4545
logger.info(
4646
"No Java API layout plugin found, skipping API surface" +
@@ -72,15 +72,16 @@ class ApiSurfacePlugin : Plugin<Project> {
7272
// Java API generation task does a clean-up of all files in the output
7373
// folder, so let it run first
7474
if (target.plugins.hasPlugin(GEN_JAVA_API_LAYOUT_PLUGIN)) {
75+
val apiDumpTasks = target.tasks.matching { it.name == TASK_GEN_JAVA_API_SURFACE }
7576
val isCi = target.providers.environmentVariable("CI").isPresent
7677
if (isCi) {
7778
// Java API generation wires to the release build type, so we can afford triggering compilation
7879
// of release type locally when we run debug compilation, but we would like to avoid it on CI
7980
if (name == "compileReleaseKotlin") {
80-
finalizedBy(TASK_GEN_JAVA_API_SURFACE)
81+
finalizedBy(apiDumpTasks)
8182
}
8283
} else {
83-
finalizedBy(TASK_GEN_JAVA_API_SURFACE)
84+
finalizedBy(apiDumpTasks)
8485
}
8586
}
8687
finalizedBy(generateApiSurfaceTask)
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/*
2+
* Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0.
3+
* This product includes software developed at Datadog (https://www.datadoghq.com/).
4+
* Copyright 2016-Present Datadog, Inc.
5+
*/
6+
7+
package com.datadog.gradle.plugin.config
8+
9+
import org.gradle.api.Plugin
10+
import org.gradle.api.Project
11+
import org.gradle.api.artifacts.VersionCatalogsExtension
12+
import org.gradle.kotlin.dsl.getByType
13+
14+
/**
15+
* Convention plugin that wires the shared unit-test dependencies (JUnit 5 + the common test
16+
* tooling bundle: elmyr, AssertJ, mockito-kotlin, …) onto a module's `test` source set.
17+
*
18+
* Apply with `plugins { id("datadog.unit-test") }`. This centralizes what used to be repeated as
19+
* `testImplementation(libs.bundles.jUnit5)` / `testImplementation(libs.bundles.testTools)` in every
20+
* module, so the declarations live in one place instead of being duplicated (and drifting) per module.
21+
*
22+
* Note: `kotlin-stdlib` is intentionally NOT declared here — the Kotlin plugin adds it to every
23+
* source set automatically (`kotlin.stdlib.default.dependency`), so declaring it explicitly only
24+
* produces "declared multiple times" warnings.
25+
*/
26+
class UnitTestConventionPlugin : Plugin<Project> {
27+
28+
override fun apply(target: Project) {
29+
val libs = target.extensions.getByType<VersionCatalogsExtension>().named("libs")
30+
BUNDLES.forEach { bundleName ->
31+
libs.findBundle(bundleName).ifPresent { bundle ->
32+
target.dependencies.addProvider("testImplementation", bundle)
33+
}
34+
}
35+
}
36+
37+
private companion object {
38+
val BUNDLES = listOf("jUnit5", "testTools")
39+
}
40+
}

0 commit comments

Comments
 (0)