diff --git a/build-logic/conventions/src/main/kotlin/dd-trace-java.conventions.testing.kotlin.gradle.kts b/build-logic/conventions/src/main/kotlin/dd-trace-java.conventions.testing.kotlin.gradle.kts new file mode 100644 index 00000000000..aa66eea1526 --- /dev/null +++ b/build-logic/conventions/src/main/kotlin/dd-trace-java.conventions.testing.kotlin.gradle.kts @@ -0,0 +1,64 @@ +import org.gradle.api.artifacts.VersionCatalogsExtension +import org.gradle.api.file.SourceDirectorySet +import org.gradle.api.plugins.jvm.JvmTestSuite +import org.gradle.api.tasks.SourceSet +import org.gradle.api.tasks.SourceSetContainer +import org.gradle.api.tasks.compile.GroovyCompile +import org.gradle.api.tasks.compile.JavaCompile +import org.gradle.kotlin.dsl.getByType +import org.gradle.kotlin.dsl.named +import org.gradle.kotlin.dsl.withType +import org.gradle.testing.base.TestingExtension + +val libs = extensions.getByType().named("libs") + +// Make compiled Kotlin classes visible to Groovy/Spock tests. +fun wireKotlinOutputToGroovy(sourceSet: SourceSet) { + val compileKotlin = tasks.named(sourceSet.getCompileTaskName("kotlin")) + tasks.named(sourceSet.getCompileTaskName("groovy")) { + // Task-backed outputs avoid a Kotlin Gradle plugin API dependency and retain task ordering. + classpath += files(compileKotlin) + } +} + +pluginManager.withPlugin("org.jetbrains.kotlin.jvm") { + val sourceSets = extensions.getByType() + + // Having Groovy, Kotlin and Java in the same project is a bit problematic. + // Remove Kotlin from main to avoid compilation issues. + sourceSets.named(SourceSet.MAIN_SOURCE_SET_NAME) { + val kotlin = extensions.getByName("kotlin") as SourceDirectorySet + kotlin.setSrcDirs(emptyList()) + java.setSrcDirs(listOf("src/main/java")) + } + + // Create Kotlin output directories to make JavaCompile tasks work. + val createKotlinDirs = tasks.register("createKotlinDirs") { + val dirsToCreate = listOf(layout.buildDirectory.dir("classes/kotlin/main")) + doFirst { + dirsToCreate.forEach { it.get().asFile.mkdirs() } + } + outputs.dirs(dirsToCreate) + } + + tasks.withType().configureEach { + inputs.files(createKotlinDirs) + } + + // Prevent Kotlin libraries from being included in the tracer JAR. + dependencies.add("compileOnly", libs.findLibrary("kotlin").get()) + + pluginManager.withPlugin("groovy") { + pluginManager.withPlugin("jvm-test-suite") { + extensions.getByType().suites.withType().configureEach { + wireKotlinOutputToGroovy(sources) + } + } + + pluginManager.withPlugin("java-test-fixtures") { + sourceSets.named("testFixtures") { + wireKotlinOutputToGroovy(this) + } + } + } +} diff --git a/dd-java-agent/agent-ci-visibility/build.gradle b/dd-java-agent/agent-ci-visibility/build.gradle index 1547b9862c3..375df7c0315 100644 --- a/dd-java-agent/agent-ci-visibility/build.gradle +++ b/dd-java-agent/agent-ci-visibility/build.gradle @@ -8,10 +8,9 @@ plugins { id 'dd-trace-java.version-file' id 'dd-trace-java.module.product-subsystem' id 'dd-trace-java.conventions.testing.scala' + id 'dd-trace-java.conventions.testing.kotlin' } -apply from: "$rootDir/gradle/test-with-kotlin.gradle" - minimumBranchCoverage = 0.0 minimumInstructionCoverage = 0.0 diff --git a/dd-java-agent/benchmark-integration/build.gradle b/dd-java-agent/benchmark-integration/build.gradle index 49f94e0714e..c1432ba79f8 100644 --- a/dd-java-agent/benchmark-integration/build.gradle +++ b/dd-java-agent/benchmark-integration/build.gradle @@ -1,4 +1,6 @@ -apply from: "$rootDir/gradle/java.gradle" +plugins { + id 'dd-trace-java.conventions.java' +} description = 'Integration Level Agent benchmarks.' @@ -6,8 +8,3 @@ java { sourceCompatibility = JavaVersion.VERSION_1_8 targetCompatibility = JavaVersion.VERSION_1_8 } - -subprojects { sub -> - sub.apply plugin: 'com.gradleup.shadow' - sub.apply from: "$rootDir/gradle/java.gradle" -} diff --git a/dd-java-agent/benchmark-integration/jetty-perftest/build.gradle b/dd-java-agent/benchmark-integration/jetty-perftest/build.gradle index c9e3ff8dc80..37f757ec933 100644 --- a/dd-java-agent/benchmark-integration/jetty-perftest/build.gradle +++ b/dd-java-agent/benchmark-integration/jetty-perftest/build.gradle @@ -1,3 +1,8 @@ +plugins { + id 'com.gradleup.shadow' + id 'dd-trace-java.conventions.java' +} + dependencies { implementation project(':dd-trace-api') implementation project(':dd-java-agent:benchmark-integration') diff --git a/dd-java-agent/benchmark-integration/play-perftest/build.gradle b/dd-java-agent/benchmark-integration/play-perftest/build.gradle index 77653ebc6b1..25309eed9d1 100644 --- a/dd-java-agent/benchmark-integration/play-perftest/build.gradle +++ b/dd-java-agent/benchmark-integration/play-perftest/build.gradle @@ -1,4 +1,6 @@ plugins { + id 'com.gradleup.shadow' + id 'dd-trace-java.conventions.java' id 'org.gradle.playframework' } diff --git a/dd-java-agent/benchmark/build.gradle b/dd-java-agent/benchmark/build.gradle index 178eefd2def..213da29f278 100644 --- a/dd-java-agent/benchmark/build.gradle +++ b/dd-java-agent/benchmark/build.gradle @@ -1,9 +1,8 @@ plugins { id 'dd-trace-java.jmh-conventions' + id 'dd-trace-java.conventions.java' } -apply from: "$rootDir/gradle/java.gradle" - dependencies { jmh project(':dd-trace-api') jmh libs.bytebuddyagent @@ -48,4 +47,3 @@ tasks.named('jmh') { (using https://github.com/brendangregg/FlameGraph) ./flamegraph.pl --color=java dd-java-agent/benchmark/build/reports/jmh/profiler-cleaned.txt > dd-java-agent/benchmark/build/reports/jmh/jmh-master.svg */ - diff --git a/dd-java-agent/build.gradle b/dd-java-agent/build.gradle index 66917378481..424a233a218 100644 --- a/dd-java-agent/build.gradle +++ b/dd-java-agent/build.gradle @@ -7,11 +7,11 @@ import java.util.jar.JarFile plugins { id 'com.gradleup.shadow' + id 'dd-trace-java.conventions.java' } description = 'dd-java-agent' -apply from: "$rootDir/gradle/java.gradle" apply from: "$rootDir/gradle/publish.gradle" configurations { diff --git a/dd-java-agent/instrumentation/junit/junit-4/junit-4.10/build.gradle b/dd-java-agent/instrumentation/junit/junit-4/junit-4.10/build.gradle index ad6c2f982dd..b7fcafee58b 100644 --- a/dd-java-agent/instrumentation/junit/junit-4/junit-4.10/build.gradle +++ b/dd-java-agent/instrumentation/junit/junit-4/junit-4.10/build.gradle @@ -5,10 +5,9 @@ plugins { id 'org.jetbrains.kotlin.jvm' id 'dd-trace-java.instrumentation.testing-framework-tests' id 'dd-trace-java.module.instrumentation' + id 'dd-trace-java.conventions.testing.kotlin' } -apply from: "$rootDir/gradle/test-with-kotlin.gradle" - muzzle { pass { group = 'junit' @@ -28,10 +27,6 @@ kotlin { addTestSuiteForDir('latestDepTest', 'test') -tasks.named("compileLatestDepTestGroovy", GroovyCompile) { - classpath += files(tasks.named('compileLatestDepTestKotlin').map { it.destinationDirectory }) -} - dependencies { compileOnly group: 'junit', name: 'junit', version: '4.10' diff --git a/dd-java-agent/instrumentation/kotlin-coroutines-1.3/build.gradle b/dd-java-agent/instrumentation/kotlin-coroutines-1.3/build.gradle index 2e0499bdab5..86abd12eb08 100644 --- a/dd-java-agent/instrumentation/kotlin-coroutines-1.3/build.gradle +++ b/dd-java-agent/instrumentation/kotlin-coroutines-1.3/build.gradle @@ -5,6 +5,7 @@ plugins { id 'java-test-fixtures' id 'org.jetbrains.kotlin.jvm' id 'dd-trace-java.module.instrumentation' + id 'dd-trace-java.conventions.testing.kotlin' } muzzle { @@ -26,8 +27,6 @@ muzzle { } } -apply from: "$rootDir/gradle/test-with-kotlin.gradle" - kotlin { compilerOptions { jvmTarget = JvmTarget.JVM_1_8 @@ -38,18 +37,6 @@ kotlin { addTestSuite('latestDepTest') -tasks.named("compileTestFixturesGroovy", GroovyCompile) { - classpath += files(tasks.named('compileTestFixturesKotlin').map { it.destinationDirectory }) -} - -tasks.named("compileTestGroovy", GroovyCompile) { - classpath += files(tasks.named('compileTestKotlin').map { it.destinationDirectory }) -} - -tasks.named("compileLatestDepTestGroovy", GroovyCompile) { - classpath += files(tasks.named('compileLatestDepTestKotlin').map { it.destinationDirectory }) -} - dependencies { api project(':dd-java-agent:instrumentation:java:java-concurrent:java-concurrent-1.8') compileOnly libs.kotlin diff --git a/dd-java-agent/instrumentation/spring/spring-messaging-4.0/build.gradle b/dd-java-agent/instrumentation/spring/spring-messaging-4.0/build.gradle index b60941adfcf..36106ea7ea2 100644 --- a/dd-java-agent/instrumentation/spring/spring-messaging-4.0/build.gradle +++ b/dd-java-agent/instrumentation/spring/spring-messaging-4.0/build.gradle @@ -4,6 +4,7 @@ import org.jetbrains.kotlin.gradle.dsl.KotlinVersion plugins { id 'org.jetbrains.kotlin.jvm' id 'dd-trace-java.module.instrumentation' + id 'dd-trace-java.conventions.testing.kotlin' } muzzle { @@ -18,8 +19,6 @@ muzzle { } } -apply from: "$rootDir/gradle/test-with-kotlin.gradle" - testJvmConstraints { minJavaVersion = JavaVersion.VERSION_17 } @@ -27,10 +26,8 @@ testJvmConstraints { addTestSuiteForDir('latestDepTest', 'test') ["compileTestGroovy", "compileLatestDepTestGroovy"].each { name -> - def kotlinTaskName = name.replace("Groovy", "Kotlin") tasks.named(name, GroovyCompile) { configureCompiler(it, 17) - classpath += files(tasks.named(kotlinTaskName).map { it.destinationDirectory }) } } diff --git a/dd-java-agent/load-generator/build.gradle b/dd-java-agent/load-generator/build.gradle index 277b4f6f36a..3a7e2b7df48 100644 --- a/dd-java-agent/load-generator/build.gradle +++ b/dd-java-agent/load-generator/build.gradle @@ -1,4 +1,6 @@ -apply from: "$rootDir/gradle/java.gradle" +plugins { + id 'dd-trace-java.conventions.java' +} dependencies { implementation project(':dd-trace-api') diff --git a/gradle/spotless.gradle b/gradle/spotless.gradle index 0f6cbf5f2f7..7536733d14d 100644 --- a/gradle/spotless.gradle +++ b/gradle/spotless.gradle @@ -7,26 +7,22 @@ boolean groovySkipJavaExclude = project.hasProperty('groovySkipJavaExclude') ? g def buildDirectoryFiles = project.layout.buildDirectory.asFileTree -// Temporary exclusions as conventions are properly setup for these projects. -def javaGradleApplyExceptions = [ - ':dd-java-agent', - ':dd-java-agent:benchmark', - ':dd-java-agent:benchmark-integration', - ':dd-java-agent:load-generator', -] as Set -boolean forbidJavaGradleApply = project.rootProject.name == 'dd-trace-java' && !javaGradleApplyExceptions.contains(project.path) +def scriptApplyExceptions = [ + 'gradle/publish.gradle': [':dd-java-agent'] as Set, +] +boolean forbidLegacyScriptApplies = project.rootProject.name == 'dd-trace-java' def javaGradleApplyLinePattern = ~/^\s*(?:\w+\.)?apply(?:\s+from\s*:|\s*\(\s*from\s*=).*/ // Script plugins that must be applied through a 'dd-trace-java.module.*' convention plugin instead. def forbiddenScriptApplies = [ 'gradle/java.gradle' : 'Apply a \'dd-trace-java.module.*\' convention plugin instead of applying the script plugin \'gradle/java.gradle\' directly.', 'gradle/publish.gradle': 'Apply the \'dd-trace-java.module.distributable.*\' convention plugin instead of applying the script plugin \'gradle/publish.gradle\' directly.', ] -def forbidJavaGradleApplyStep = { String text -> - if (forbidJavaGradleApply) { +def forbidLegacyScriptApplyStep = { String text -> + if (forbidLegacyScriptApplies) { text.readLines().each { line -> if (javaGradleApplyLinePattern.matcher(line).matches()) { forbiddenScriptApplies.each { script, message -> - if (line.contains(script)) { + if (line.contains(script) && !scriptApplyExceptions.getOrDefault(script, []).contains(project.path)) { throw new AssertionError(message) } } @@ -70,7 +66,7 @@ spotless { target '*.gradle' } greclipse(libs.versions.greclipse.get()).configFile(configPath + '/enforcement/spotless-groovy.properties') - custom 'forbidGradleJavaScriptPlugin', forbidJavaGradleApplyStep + custom 'forbidGradleJavaScriptPlugin', forbidLegacyScriptApplyStep } kotlinGradle { @@ -82,7 +78,7 @@ spotless { 'ktlint_standard_trailing-comma-on-call-site': 'disabled', 'ktlint_standard_trailing-comma-on-declaration-site': 'disabled' ]) - custom 'forbidGradleJavaScriptPlugin', forbidJavaGradleApplyStep + custom 'forbidGradleJavaScriptPlugin', forbidLegacyScriptApplyStep } project.pluginManager.withPlugin('groovy') { diff --git a/gradle/test-with-kotlin.gradle b/gradle/test-with-kotlin.gradle deleted file mode 100644 index f03c2a0a202..00000000000 --- a/gradle/test-with-kotlin.gradle +++ /dev/null @@ -1,47 +0,0 @@ -// Enable testing kotlin code in groovy spock tests. -project.pluginManager.withPlugin('kotlin') { - tasks.named("compileTestGroovy", GroovyCompile) { - //Note: look like it should be `classpath += files(sourceSets.test.kotlin.classesDirectory)` - //instead, but kotlin plugin doesn't support it (yet?) - classpath += files(tasks.named('compileTestKotlin').map { it.destinationDirectory }) - } - - // Having Groovy, Kotlin and Java in the same project is a bit problematic - // this removes Kotlin from main source set to avoid compilation issues - sourceSets { - main { - kotlin { - srcDirs = [] - } - java { - srcDirs = ["src/main/java"] - } - } - } - - // this creates Kotlin dirs to make JavaCompile tasks work - def createKotlinDirs = tasks.register("createKotlinDirs") { - def dirsToCreate = ["classes/kotlin/main"] - doFirst { - dirsToCreate.forEach { - new File(project.buildDir, it).mkdirs() - } - } - - outputs.dirs( - dirsToCreate.collect { - project.layout.buildDirectory.dir(it) - } - ) - } - - tasks.withType(JavaCompile).configureEach { - inputs.files(createKotlinDirs) - } - - dependencies { - // prevents Kotlin libs from being included into the tracer JAR - compileOnly libs.kotlin - } -} -