From 04cfa1ae7dc03bfc7cf172aeb42d1b9721364916 Mon Sep 17 00:00:00 2001 From: Alexey Kuznetsov Date: Fri, 15 May 2026 15:59:14 -0400 Subject: [PATCH 1/5] Centralize spotless setup as a buildSrc convention plugin. --- .gitlab-ci.yml | 4 +- build.gradle.kts | 35 +---- buildSrc/build.gradle.kts | 32 +++- .../build.gradle.kts | 12 -- ...trace-java.spotless-conventions.gradle.kts | 139 ++++++++++++++++++ dd-java-agent/agent-iast/build.gradle | 5 - dd-java-agent/appsec/build.gradle | 6 - .../play-perftest/build.gradle | 9 -- .../instrumentation/mule-4.5/build.gradle | 6 +- .../scala-promise-2.10/build.gradle | 14 -- .../scala-promise-2.13/build.gradle | 14 -- dd-smoke-tests/armeria-grpc/build.gradle | 9 -- dd-smoke-tests/kafka-3/build.gradle | 10 -- dd-smoke-tests/play-2.4/build.gradle | 9 -- dd-smoke-tests/play-2.5/build.gradle | 9 -- dd-smoke-tests/play-2.6/build.gradle | 9 -- dd-smoke-tests/play-2.7/build.gradle | 9 -- dd-smoke-tests/play-2.8-otel/build.gradle | 9 -- .../play-2.8-split-routes/build.gradle | 9 -- dd-smoke-tests/play-2.8/build.gradle | 9 -- dd-smoke-tests/quarkus-native/build.gradle | 10 -- dd-smoke-tests/quarkus/build.gradle | 10 -- dd-smoke-tests/rum/wildfly-15/build.gradle | 10 -- .../spring-boot-2.7-webflux/build.gradle | 10 -- .../spring-boot-3.0-native/build.gradle | 10 -- .../spring-boot-3.0-webflux/build.gradle | 10 -- .../spring-boot-3.0-webmvc/build.gradle | 10 -- .../spring-boot-3.3-webmvc/build.gradle | 10 -- .../springboot-openliberty-20/build.gradle | 13 -- .../springboot-openliberty-23/build.gradle | 13 -- dd-smoke-tests/vertx-3.4/build.gradle | 10 -- .../vertx-3.9-resteasy/build.gradle | 10 -- dd-smoke-tests/vertx-3.9/build.gradle | 10 -- dd-smoke-tests/vertx-4.2/build.gradle | 10 -- dd-smoke-tests/wildfly/build.gradle | 10 -- gradle/enforcement/spotless-scalafmt.conf | 2 +- gradle/java_no_deps.gradle | 1 - gradle/spotless.gradle | 111 -------------- test-published-dependencies/build.gradle | 5 - 39 files changed, 175 insertions(+), 458 deletions(-) create mode 100644 buildSrc/src/main/kotlin/dd-trace-java.spotless-conventions.gradle.kts delete mode 100644 gradle/spotless.gradle diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 5290d93abd0..46f7d88eab3 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -407,7 +407,9 @@ spotless: stage: tests needs: [] variables: - GRADLE_MEMORY_MAX: 6G + # Give spotlessCheck more heap and fewer parallel workers — it OOMs on CI otherwise. + GRADLE_MEMORY_MAX: 8G + GRADLE_WORKERS: 2 script: - ./gradlew --version - ./gradlew spotlessCheck $GRADLE_ARGS diff --git a/build.gradle.kts b/build.gradle.kts index 38169896069..42fd301c36c 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,4 +1,3 @@ -import com.diffplug.gradle.spotless.SpotlessExtension import datadog.gradle.plugin.ci.testAggregate plugins { @@ -10,8 +9,8 @@ plugins { id("dd-trace-java.dump-hanged-test") id("dd-trace-java.config-inversion-linter") id("dd-trace-java.ci-jobs") + id("dd-trace-java.spotless-conventions") - id("com.diffplug.spotless") version "8.4.0" id("me.champeau.gradle.japicmp") version "0.4.3" id("com.github.spotbugs") version "6.5.0" id("de.thetaphi.forbiddenapis") version "3.10" @@ -28,38 +27,6 @@ val isCI = providers.environmentVariable("CI") apply(from = rootDir.resolve("gradle/repositories.gradle")) apply(from = rootDir.resolve("gradle/ddprof-override.gradle")) -spotless { - // only resolve the spotless dependencies once in the build - predeclareDeps() -} - -with(extensions["spotlessPredeclare"] as SpotlessExtension) { - // these need to align with the types and versions in gradle/spotless.gradle - java { - removeUnusedImports() - - googleJavaFormat("1.35.0") - tableTestFormatter("1.1.1") - } - groovyGradle { - greclipse() - } - groovy { - greclipse() - } - kotlinGradle { - ktlint("1.8.0") - } - kotlin { - ktlint("1.8.0") - } - scala { - // TODO: For some reason Scala format is working correctly with this version only. - scalafmt("3.8.6") - } -} -apply(from = rootDir.resolve("gradle/spotless.gradle")) - val compileTask = tasks.register("compile") allprojects { diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index b1be2144929..113ea705280 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -1,20 +1,43 @@ +import org.gradle.api.attributes.java.TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE +import org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_1_8 + plugins { `java-gradle-plugin` `kotlin-dsl` `jvm-test-suite` - id("com.diffplug.spotless") version "8.4.0" } -// The buildSrc still needs to target Java 8 as build time instrumentation and muzzle plugin -// allow to schedule workers on different JDK version. +// Compile with a modern JDK toolchain (21), but keep the emitted bytecode at Java 8. +// Rationale: the build-time instrumentation and muzzle plugins schedule Gradle workers +// on different JDK versions, including Java 8, so any class loaded from buildSrc must +// remain Java 8 compatible. java { + toolchain { + languageVersion = JavaLanguageVersion.of(21) + } + sourceCompatibility = JavaVersion.VERSION_1_8 targetCompatibility = JavaVersion.VERSION_1_8 } +// Same split for Kotlin: compile on JDK 21 but target the Java 8 bytecode level so the +// Kotlin output can be loaded by the same Java-8 workers described above. kotlin { + jvmToolchain(21) + compilerOptions { - jvmTarget.set(org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_1_8) + jvmTarget.set(JVM_1_8) + } +} + +// Advertise Java 17 as the target JVM version when *resolving* dependencies. Several +// modern Gradle plugins (notably Spotless 8.x) publish only Java 17+ variants via Gradle +// Module Metadata; without this attribute, resolution fails with "no matching variant" +// because our targetCompatibility above declares Java 8. This affects dependency +// resolution only — it does not change the bytecode level we emit, which stays at Java 8. +configurations.configureEach { + if (isCanBeResolved) { + attributes.attribute(TARGET_JVM_VERSION_ATTRIBUTE, 17) } } @@ -78,6 +101,7 @@ dependencies { implementation(gradleApi()) implementation("net.bytebuddy", "byte-buddy-gradle-plugin", "1.18.8") + implementation("com.diffplug.spotless:spotless-plugin-gradle:8.5.0") implementation("org.eclipse.aether", "aether-connector-basic", "1.1.0") implementation("org.eclipse.aether", "aether-transport-http", "1.1.0") diff --git a/buildSrc/call-site-instrumentation-plugin/build.gradle.kts b/buildSrc/call-site-instrumentation-plugin/build.gradle.kts index 562ab980e91..50bf538b21e 100644 --- a/buildSrc/call-site-instrumentation-plugin/build.gradle.kts +++ b/buildSrc/call-site-instrumentation-plugin/build.gradle.kts @@ -1,6 +1,5 @@ plugins { java - id("com.diffplug.spotless") version "8.4.0" id("com.gradleup.shadow") version "8.3.9" } @@ -9,17 +8,6 @@ java { targetCompatibility = JavaVersion.VERSION_1_8 } -spotless { - java { - toggleOffOn() - // set explicit target to workaround https://github.com/diffplug/spotless/issues/1163 - target("src/**/*.java") - // ignore embedded test projects - targetExclude("src/test/resources/**") - googleJavaFormat("1.35.0") - } -} - apply { from("$rootDir/../gradle/repositories.gradle") } diff --git a/buildSrc/src/main/kotlin/dd-trace-java.spotless-conventions.gradle.kts b/buildSrc/src/main/kotlin/dd-trace-java.spotless-conventions.gradle.kts new file mode 100644 index 00000000000..e54b16606a9 --- /dev/null +++ b/buildSrc/src/main/kotlin/dd-trace-java.spotless-conventions.gradle.kts @@ -0,0 +1,139 @@ +import com.diffplug.gradle.spotless.SpotlessExtension +import com.diffplug.gradle.spotless.SpotlessExtensionPredeclare + +plugins { + id("com.diffplug.spotless") +} + +val googleJavaFormatVersion = "1.35.0" +val tableTestFormatterVersion = "1.1.1" +val ktlintVersion = "1.8.0" +val scalafmtVersion = "3.11.1" +val ktlintEditorConfigOverride = mapOf( + "ktlint_standard_trailing-comma-on-call-site" to "disabled", + "ktlint_standard_trailing-comma-on-declaration-site" to "disabled" +) + +// Resolve formatter dependencies once, then let all subprojects reuse the cached provisioner. +configure { + java { + tableTestFormatter(tableTestFormatterVersion) + googleJavaFormat(googleJavaFormatVersion) + } + + groovyGradle { + greclipse() + } + + groovy { + greclipse() + } + + kotlinGradle { + ktlint(ktlintVersion) + } + + kotlin { + ktlint(ktlintVersion) + } + + scala { + scalafmt(scalafmtVersion) + } +} + +// List of projects to exclude from processing by Spotless. +val spotlessExcludedProjects = setOf(":dd-java-agent:agent-jmxfetch") + +// Spotless applied per-module for parallel execution, configured centrally here. +allprojects { + if (path in spotlessExcludedProjects) { + return@allprojects + } + + apply(plugin = "com.diffplug.spotless") + + configure { + if (rootProject.hasProperty("skipSpotless")) { + isEnforceCheck = false + } + + // Gradle files and other formats we process globally from root + if (project == rootProject) { + val commonExcludes = listOf( + "build/**", + "buildSrc/build/**", + "dd-java-agent/agent-jmxfetch/**" + ) + + kotlinGradle { + toggleOffOn() + target("**/*.gradle.kts") + targetExclude(commonExcludes) + ktlint(ktlintVersion).editorConfigOverride(ktlintEditorConfigOverride) + } + + groovyGradle { + toggleOffOn() + target("**/*.gradle") + targetExclude(commonExcludes) + greclipse().configFile("$rootDir/gradle/enforcement/spotless-groovy.properties") + } + + format("markdown") { + toggleOffOn() + target("*.md", ".github/**/*.md", "src/**/*.md", "app*/**/*.md") + leadingTabsToSpaces() + endWithNewline() + } + + format("misc") { + toggleOffOn() + target(".gitignore", "*.sh", "tooling/*.sh", ".gitlab/*.sh") + leadingTabsToSpaces() + trimTrailingWhitespace() + endWithNewline() + } + } else { + // Configure source code formatting. + val commonExcludes = listOf("build/**", "src/test/resources/**") + + pluginManager.withPlugin("java") { + java { + toggleOffOn() + target("src/**/*.java", "app*/**/*.java") + targetExclude(commonExcludes) + tableTestFormatter(tableTestFormatterVersion) + googleJavaFormat(googleJavaFormatVersion) + } + } + + pluginManager.withPlugin("org.jetbrains.kotlin.jvm") { + kotlin { + toggleOffOn() + target("src/**/*.kt", "app*/**/*.kt") + targetExclude(commonExcludes) + ktlint(ktlintVersion).editorConfigOverride(ktlintEditorConfigOverride) + } + } + + pluginManager.withPlugin("scala") { + scala { + toggleOffOn() + target("src/**/*.scala", "app*/**/*.scala") + targetExclude(commonExcludes) + scalafmt(scalafmtVersion).configFile("$rootDir/gradle/enforcement/spotless-scalafmt.conf") + } + } + + pluginManager.withPlugin("groovy") { + groovy { + toggleOffOn() + target("src/**/*.groovy", "app*/**/*.groovy") + targetExclude(commonExcludes) + greclipse().configFile("$rootDir/gradle/enforcement/spotless-groovy.properties") + } + } + } + } +} diff --git a/dd-java-agent/agent-iast/build.gradle b/dd-java-agent/agent-iast/build.gradle index 55d0fbbe9e8..617a373bde8 100644 --- a/dd-java-agent/agent-iast/build.gradle +++ b/dd-java-agent/agent-iast/build.gradle @@ -100,11 +100,6 @@ ext { tasks.withType(Test).configureEach { jvmArgs += ['-Ddd.iast.enabled=true'] } -spotless { - java { - target 'src/**/*.java' - } -} jmh { jmhVersion = libs.versions.jmh.get() diff --git a/dd-java-agent/appsec/build.gradle b/dd-java-agent/appsec/build.gradle index b98f2422897..b0c92467b5e 100644 --- a/dd-java-agent/appsec/build.gradle +++ b/dd-java-agent/appsec/build.gradle @@ -111,9 +111,3 @@ tasks.withType(Test).configureEach { } def rootDir = project.rootDir - -spotless { - java { - target 'src/**/*.java' - } -} diff --git a/dd-java-agent/benchmark-integration/play-perftest/build.gradle b/dd-java-agent/benchmark-integration/play-perftest/build.gradle index 77653ebc6b1..7fcc7c15343 100644 --- a/dd-java-agent/benchmark-integration/play-perftest/build.gradle +++ b/dd-java-agent/benchmark-integration/play-perftest/build.gradle @@ -54,12 +54,3 @@ repositories { layout("ivy") } } - -spotless { - java { - target("**/*.java") - } - scala { - target("**/*.scala") - } -} diff --git a/dd-java-agent/instrumentation/mule-4.5/build.gradle b/dd-java-agent/instrumentation/mule-4.5/build.gradle index b25f5fe81f3..a6ffc65b272 100644 --- a/dd-java-agent/instrumentation/mule-4.5/build.gradle +++ b/dd-java-agent/instrumentation/mule-4.5/build.gradle @@ -271,8 +271,8 @@ def createAppResourceTask(Task task, String name) { } } -spotless { - java { - target "**/*.java" +idea { + module { + jdkName = '11' } } diff --git a/dd-java-agent/instrumentation/scala/scala-promise/scala-promise-2.10/build.gradle b/dd-java-agent/instrumentation/scala/scala-promise/scala-promise-2.10/build.gradle index 6f35ebf59e6..b6677142140 100644 --- a/dd-java-agent/instrumentation/scala/scala-promise/scala-promise-2.10/build.gradle +++ b/dd-java-agent/instrumentation/scala/scala-promise/scala-promise-2.10/build.gradle @@ -8,20 +8,6 @@ muzzle { } } -// We need to set up the spotless targets here before we apply the standard settings to avoid -// having all the scala files in the common test directories being added as well, making spotless -// fail because the files are outside this project directory -apply plugin: 'com.diffplug.spotless' -spotless { - groovy { - target('src/**/*.groovy') - } - scala { - target('src/**/*.scala') - } -} -project.ext.groovySkipJavaExclude = true - apply from: "$rootDir/gradle/java.gradle" apply plugin: 'scala' // Don't use test-with-scala since we want to pick our own version. diff --git a/dd-java-agent/instrumentation/scala/scala-promise/scala-promise-2.13/build.gradle b/dd-java-agent/instrumentation/scala/scala-promise/scala-promise-2.13/build.gradle index d9e9c16f706..4a0405a9fbe 100644 --- a/dd-java-agent/instrumentation/scala/scala-promise/scala-promise-2.13/build.gradle +++ b/dd-java-agent/instrumentation/scala/scala-promise/scala-promise-2.13/build.gradle @@ -8,20 +8,6 @@ muzzle { } } -// We need to set up the spotless targets here before we apply the standard settings to avoid -// having all the scala files in the common test directories being added as well, making spotless -// fail because the files are outside this project directory -apply plugin: 'com.diffplug.spotless' -spotless { - groovy { - target('src/**/*.groovy') - } - scala { - target('src/**/*.scala') - } -} -project.ext.groovySkipJavaExclude = true - apply from: "$rootDir/gradle/java.gradle" apply plugin: 'scala' // Don't use test-with-scala since we want to pick our own version. diff --git a/dd-smoke-tests/armeria-grpc/build.gradle b/dd-smoke-tests/armeria-grpc/build.gradle index ebe341a8190..fa6cd768921 100644 --- a/dd-smoke-tests/armeria-grpc/build.gradle +++ b/dd-smoke-tests/armeria-grpc/build.gradle @@ -92,12 +92,3 @@ tasks.withType(Test).configureEach { jvmArgs "-Ddatadog.smoketest.armeria.uberJar.path=$appBuildDir/libs/armeria-smoketest-all.jar" } -spotless { - java { - target "**/*.java" - } - - groovyGradle { - target '*.gradle', "**/*.gradle" - } -} diff --git a/dd-smoke-tests/kafka-3/build.gradle b/dd-smoke-tests/kafka-3/build.gradle index 0c92600de50..00a7e65276d 100644 --- a/dd-smoke-tests/kafka-3/build.gradle +++ b/dd-smoke-tests/kafka-3/build.gradle @@ -53,13 +53,3 @@ tasks.named('compileTestGroovy') { tasks.withType(Test).configureEach { jvmArgs "-Ddatadog.smoketest.springboot.shadowJar.path=${appBuildDir}/libs/kafka-3-smoketest.jar" } - -spotless { - java { - target "**/*.java" - } - - groovyGradle { - target '*.gradle', "**/*.gradle" - } -} diff --git a/dd-smoke-tests/play-2.4/build.gradle b/dd-smoke-tests/play-2.4/build.gradle index 1a0de08b58b..44c0bd37481 100644 --- a/dd-smoke-tests/play-2.4/build.gradle +++ b/dd-smoke-tests/play-2.4/build.gradle @@ -92,12 +92,3 @@ tasks.withType(AbstractCopyTask).configureEach { // Don't know why the play plugin tries to copy the logback.xml file twice, but only accept it once duplicatesStrategy = DuplicatesStrategy.EXCLUDE } - -spotless { - java { - target "**/*.java" - } - scala { - target "**/*.scala" - } -} diff --git a/dd-smoke-tests/play-2.5/build.gradle b/dd-smoke-tests/play-2.5/build.gradle index f0e71773b3a..d7f3f5cb284 100644 --- a/dd-smoke-tests/play-2.5/build.gradle +++ b/dd-smoke-tests/play-2.5/build.gradle @@ -93,12 +93,3 @@ tasks.withType(AbstractCopyTask).configureEach { // Don't know why the play plugin tries to copy the logback.xml file twice, but only accept it once duplicatesStrategy = DuplicatesStrategy.EXCLUDE } - -spotless { - java { - target "**/*.java" - } - scala { - target "**/*.scala" - } -} diff --git a/dd-smoke-tests/play-2.6/build.gradle b/dd-smoke-tests/play-2.6/build.gradle index 2d95b942697..066c62464e1 100644 --- a/dd-smoke-tests/play-2.6/build.gradle +++ b/dd-smoke-tests/play-2.6/build.gradle @@ -93,12 +93,3 @@ tasks.withType(AbstractCopyTask).configureEach { // Don't know why the play plugin tries to copy the logback.xml file twice, but only accept it once duplicatesStrategy = DuplicatesStrategy.EXCLUDE } - -spotless { - java { - target "**/*.java" - } - scala { - target "**/*.scala" - } -} diff --git a/dd-smoke-tests/play-2.7/build.gradle b/dd-smoke-tests/play-2.7/build.gradle index 32001a18e7e..410e7c70f48 100644 --- a/dd-smoke-tests/play-2.7/build.gradle +++ b/dd-smoke-tests/play-2.7/build.gradle @@ -93,12 +93,3 @@ tasks.withType(AbstractCopyTask).configureEach { // Don't know why the play plugin tries to copy the logback.xml file twice, but only accept it once duplicatesStrategy = DuplicatesStrategy.EXCLUDE } - -spotless { - java { - target "**/*.java" - } - scala { - target "**/*.scala" - } -} diff --git a/dd-smoke-tests/play-2.8-otel/build.gradle b/dd-smoke-tests/play-2.8-otel/build.gradle index 689d177c9dd..ef48dd1a595 100644 --- a/dd-smoke-tests/play-2.8-otel/build.gradle +++ b/dd-smoke-tests/play-2.8-otel/build.gradle @@ -89,12 +89,3 @@ tasks.withType(AbstractCopyTask).configureEach { // Don't know why the play plugin tries to copy the logback.xml file twice, but only accept it once duplicatesStrategy = DuplicatesStrategy.EXCLUDE } - -spotless { - java { - target "**/*.java" - } - scala { - target "**/*.scala" - } -} diff --git a/dd-smoke-tests/play-2.8-split-routes/build.gradle b/dd-smoke-tests/play-2.8-split-routes/build.gradle index 838c9aee693..f8d3096d033 100644 --- a/dd-smoke-tests/play-2.8-split-routes/build.gradle +++ b/dd-smoke-tests/play-2.8-split-routes/build.gradle @@ -89,12 +89,3 @@ tasks.withType(AbstractCopyTask).configureEach { // Don't know why the play plugin tries to copy the logback.xml file twice, but only accept it once duplicatesStrategy = DuplicatesStrategy.EXCLUDE } - -spotless { - java { - target "**/*.java" - } - scala { - target "**/*.scala" - } -} diff --git a/dd-smoke-tests/play-2.8/build.gradle b/dd-smoke-tests/play-2.8/build.gradle index 3cf6e17d7f7..1d5f509f6c9 100644 --- a/dd-smoke-tests/play-2.8/build.gradle +++ b/dd-smoke-tests/play-2.8/build.gradle @@ -92,12 +92,3 @@ tasks.withType(AbstractCopyTask).configureEach { // Don't know why the play plugin tries to copy the logback.xml file twice, but only accept it once duplicatesStrategy = DuplicatesStrategy.EXCLUDE } - -spotless { - java { - target "**/*.java" - } - scala { - target "**/*.scala" - } -} diff --git a/dd-smoke-tests/quarkus-native/build.gradle b/dd-smoke-tests/quarkus-native/build.gradle index 89d43864d70..d180f522e38 100644 --- a/dd-smoke-tests/quarkus-native/build.gradle +++ b/dd-smoke-tests/quarkus-native/build.gradle @@ -77,13 +77,3 @@ if (testGraalvmVersion >= 17) { enabled = false } } - -spotless { - java { - target "**/*.java" - } - - groovyGradle { - target '*.gradle', "**/*.gradle" - } -} diff --git a/dd-smoke-tests/quarkus/build.gradle b/dd-smoke-tests/quarkus/build.gradle index 56f0cee613a..1c2857edcb0 100644 --- a/dd-smoke-tests/quarkus/build.gradle +++ b/dd-smoke-tests/quarkus/build.gradle @@ -52,13 +52,3 @@ tasks.named("compileTestGroovy", GroovyCompile) { tasks.withType(Test).configureEach { jvmArgs "-Ddatadog.smoketest.quarkus.uberJar.path=$appBuildDir/quarkus-smoketest--runner.jar" } - -spotless { - java { - target "**/*.java" - } - - groovyGradle { - target '*.gradle', "**/*.gradle" - } -} diff --git a/dd-smoke-tests/rum/wildfly-15/build.gradle b/dd-smoke-tests/rum/wildfly-15/build.gradle index 00cc72f1b01..66e5a1089d7 100644 --- a/dd-smoke-tests/rum/wildfly-15/build.gradle +++ b/dd-smoke-tests/rum/wildfly-15/build.gradle @@ -81,16 +81,6 @@ tasks.named("compileTestGroovy", GroovyCompile) { } } -spotless { - java { - target "**/*.java" - } - - groovyGradle { - target '*.gradle', "**/*.gradle" - } -} - tasks.register("unzip", Copy) { dependsOn 'earBuild' mustRunAfter 'compileTestGroovy' diff --git a/dd-smoke-tests/spring-boot-2.7-webflux/build.gradle b/dd-smoke-tests/spring-boot-2.7-webflux/build.gradle index ec403dc3c20..0118c9d0965 100644 --- a/dd-smoke-tests/spring-boot-2.7-webflux/build.gradle +++ b/dd-smoke-tests/spring-boot-2.7-webflux/build.gradle @@ -47,13 +47,3 @@ tasks.named("compileTestGroovy", GroovyCompile) { tasks.withType(Test).configureEach { jvmArgs "-Ddatadog.smoketest.webflux.uberJar.path=$appBuildDir/libs/webflux-2.7-smoketest.jar" } - -spotless { - java { - target "**/*.java" - } - - groovyGradle { - target '*.gradle', "**/*.gradle" - } -} diff --git a/dd-smoke-tests/spring-boot-3.0-native/build.gradle b/dd-smoke-tests/spring-boot-3.0-native/build.gradle index e0dda4c6db6..7a090286b14 100644 --- a/dd-smoke-tests/spring-boot-3.0-native/build.gradle +++ b/dd-smoke-tests/spring-boot-3.0-native/build.gradle @@ -79,13 +79,3 @@ if (testGraalvmVersion >= 17) { enabled = false } } - -spotless { - java { - target "**/*.java" - } - - groovyGradle { - target '*.gradle', "**/*.gradle" - } -} diff --git a/dd-smoke-tests/spring-boot-3.0-webflux/build.gradle b/dd-smoke-tests/spring-boot-3.0-webflux/build.gradle index 6138aef945d..7146f6a3307 100644 --- a/dd-smoke-tests/spring-boot-3.0-webflux/build.gradle +++ b/dd-smoke-tests/spring-boot-3.0-webflux/build.gradle @@ -51,13 +51,3 @@ tasks.named("compileTestGroovy", GroovyCompile) { tasks.withType(Test).configureEach { jvmArgs "-Ddatadog.smoketest.webflux.uberJar.path=$appBuildDir/libs/webflux-3.0-smoketest.jar" } - -spotless { - java { - target "**/*.java" - } - - groovyGradle { - target '*.gradle', "**/*.gradle" - } -} diff --git a/dd-smoke-tests/spring-boot-3.0-webmvc/build.gradle b/dd-smoke-tests/spring-boot-3.0-webmvc/build.gradle index 46c00fbcec8..98b96e30f75 100644 --- a/dd-smoke-tests/spring-boot-3.0-webmvc/build.gradle +++ b/dd-smoke-tests/spring-boot-3.0-webmvc/build.gradle @@ -48,13 +48,3 @@ tasks.named("compileTestGroovy", GroovyCompile) { tasks.withType(Test).configureEach { jvmArgs "-Ddatadog.smoketest.springboot.uberJar.path=$appBuildDir/libs/webmvc-3.0-smoketest.jar" } - -spotless { - java { - target "**/*.java" - } - - groovyGradle { - target '*.gradle', "**/*.gradle" - } -} diff --git a/dd-smoke-tests/spring-boot-3.3-webmvc/build.gradle b/dd-smoke-tests/spring-boot-3.3-webmvc/build.gradle index 484ecfc5668..c80333e5071 100644 --- a/dd-smoke-tests/spring-boot-3.3-webmvc/build.gradle +++ b/dd-smoke-tests/spring-boot-3.3-webmvc/build.gradle @@ -48,13 +48,3 @@ tasks.named("compileTestGroovy", GroovyCompile) { tasks.withType(Test).configureEach { jvmArgs "-Ddatadog.smoketest.springboot.uberJar.path=$appBuildDir/libs/webmvc-3.3-smoketest.jar" } - -spotless { - java { - target "**/*.java" - } - - groovyGradle { - target '*.gradle', "**/*.gradle" - } -} diff --git a/dd-smoke-tests/springboot-openliberty-20/build.gradle b/dd-smoke-tests/springboot-openliberty-20/build.gradle index b8a4f0c8c5f..6b25513b9ed 100644 --- a/dd-smoke-tests/springboot-openliberty-20/build.gradle +++ b/dd-smoke-tests/springboot-openliberty-20/build.gradle @@ -44,16 +44,3 @@ tasks.named("compileTestGroovy", GroovyCompile) { tasks.withType(Test).configureEach { jvmArgs "-Ddatadog.smoketest.openliberty.jar.path=${jarPath}" } - - -spotless { - java { - target fileTree("$appDir") { - include "**/*.java" - } - } - - groovyGradle { - target '*.gradle', "**/*.gradle" - } -} diff --git a/dd-smoke-tests/springboot-openliberty-23/build.gradle b/dd-smoke-tests/springboot-openliberty-23/build.gradle index 68dc1ec98c7..bb67ea0cfd0 100644 --- a/dd-smoke-tests/springboot-openliberty-23/build.gradle +++ b/dd-smoke-tests/springboot-openliberty-23/build.gradle @@ -44,16 +44,3 @@ tasks.named("compileTestGroovy", GroovyCompile) { tasks.withType(Test).configureEach { jvmArgs "-Ddatadog.smoketest.openliberty.jar.path=${jarPath}" } - - -spotless { - java { - target fileTree("$appDir") { - include "**/*.java" - } - } - - groovyGradle { - target '*.gradle', "**/*.gradle" - } -} diff --git a/dd-smoke-tests/vertx-3.4/build.gradle b/dd-smoke-tests/vertx-3.4/build.gradle index a912e7b34e4..2605645f646 100644 --- a/dd-smoke-tests/vertx-3.4/build.gradle +++ b/dd-smoke-tests/vertx-3.4/build.gradle @@ -52,16 +52,6 @@ tasks.withType(Test).configureEach { jvmArgs "-Ddatadog.smoketest.vertx.uberJar.path=$appBuildDir/libs/vertx-3.4-1.0.0-SNAPSHOT-fat.jar" } -spotless { - java { - target "**/*.java" - } - - groovyGradle { - target '*.gradle', "**/*.gradle" - } -} - idea { module { excludeDirs += [file("$appDir")] diff --git a/dd-smoke-tests/vertx-3.9-resteasy/build.gradle b/dd-smoke-tests/vertx-3.9-resteasy/build.gradle index c7e3dd90565..3ce95acc239 100644 --- a/dd-smoke-tests/vertx-3.9-resteasy/build.gradle +++ b/dd-smoke-tests/vertx-3.9-resteasy/build.gradle @@ -49,16 +49,6 @@ tasks.withType(Test).configureEach { jvmArgs "-Ddatadog.smoketest.vertx.uberJar.path=$appBuildDir/libs/vertx-3.9-resteasy-1.0.0-SNAPSHOT-fat.jar" } -spotless { - java { - target "**/*.java" - } - - groovyGradle { - target '*.gradle', "**/*.gradle" - } -} - idea { module { excludeDirs += [file("$appDir")] diff --git a/dd-smoke-tests/vertx-3.9/build.gradle b/dd-smoke-tests/vertx-3.9/build.gradle index 2f374a5c699..c7ee8f25721 100644 --- a/dd-smoke-tests/vertx-3.9/build.gradle +++ b/dd-smoke-tests/vertx-3.9/build.gradle @@ -50,16 +50,6 @@ tasks.withType(Test).configureEach { jvmArgs "-Ddatadog.smoketest.vertx.uberJar.path=$appBuildDir/libs/vertx-3.9-1.0.0-SNAPSHOT-fat.jar" } -spotless { - java { - target "**/*.java" - } - - groovyGradle { - target '*.gradle', "**/*.gradle" - } -} - idea { module { excludeDirs += [file("$appDir")] diff --git a/dd-smoke-tests/vertx-4.2/build.gradle b/dd-smoke-tests/vertx-4.2/build.gradle index bc36d08acb0..7c9b8ad6950 100644 --- a/dd-smoke-tests/vertx-4.2/build.gradle +++ b/dd-smoke-tests/vertx-4.2/build.gradle @@ -51,16 +51,6 @@ tasks.withType(Test).configureEach { jvmArgs "-Ddatadog.smoketest.vertx.uberJar.path=$appBuildDir/libs/vertx-4.2-1.0.0-SNAPSHOT-fat.jar" } -spotless { - java { - target "**/*.java" - } - - groovyGradle { - target '*.gradle', "**/*.gradle" - } -} - idea { module { excludeDirs += [file("$appDir")] diff --git a/dd-smoke-tests/wildfly/build.gradle b/dd-smoke-tests/wildfly/build.gradle index 75941ba0288..32f451573bf 100644 --- a/dd-smoke-tests/wildfly/build.gradle +++ b/dd-smoke-tests/wildfly/build.gradle @@ -84,16 +84,6 @@ tasks.named("compileTestGroovy", GroovyCompile) { } } -spotless { - java { - target "**/*.java" - } - - groovyGradle { - target '*.gradle', "**/*.gradle" - } -} - tasks.register("unzip", Copy) { dependsOn 'earBuild' mustRunAfter 'compileTestGroovy' diff --git a/gradle/enforcement/spotless-scalafmt.conf b/gradle/enforcement/spotless-scalafmt.conf index d1e1ae77b97..a36828eaa4d 100644 --- a/gradle/enforcement/spotless-scalafmt.conf +++ b/gradle/enforcement/spotless-scalafmt.conf @@ -1,4 +1,4 @@ -version = 3.8.6 +version = 3.11.1 runner.dialect = scala213 align.preset = more maxColumn = 100 diff --git a/gradle/java_no_deps.gradle b/gradle/java_no_deps.gradle index 4d446e4a610..d24aad3ffd5 100644 --- a/gradle/java_no_deps.gradle +++ b/gradle/java_no_deps.gradle @@ -11,7 +11,6 @@ apply plugin: 'dd-trace-java.test-jvm-constraints' apply from: "$rootDir/gradle/codenarc.gradle" apply from: "$rootDir/gradle/forbiddenapis.gradle" -apply from: "$rootDir/gradle/spotless.gradle" apply from: "$rootDir/gradle/spotbugs.gradle" apply from: "$rootDir/gradle/repositories.gradle" apply from: "$rootDir/gradle/test-suites.gradle" diff --git a/gradle/spotless.gradle b/gradle/spotless.gradle deleted file mode 100644 index 93a817e6452..00000000000 --- a/gradle/spotless.gradle +++ /dev/null @@ -1,111 +0,0 @@ -apply plugin: 'com.diffplug.spotless' - -// This definition is needed since the spotless file is used from stand alone projects -def configPath = rootProject.hasProperty('sharedConfigDirectory') ? sharedConfigDirectory : project.rootProject.rootDir.path + '/gradle' -// This is necessary for some projects that set a special groovy target which can't coexist with excludeJava -boolean groovySkipJavaExclude = project.hasProperty('groovySkipJavaExclude') ? groovySkipJavaExclude : false - -def buildDirectoryFiles = project.layout.buildDirectory.asFileTree - -spotless { - if (rootProject.hasProperty('skipSpotless')) { - project.logger.quiet("Retiring 'skipSpotless' property, prefer '-x spotlessCheck' or '-x spotlessApply' to exclude spotless tasks.") - // Spotless in JDK 8 uses an older eclipse formatter, and it has a (flaky) bug crashing check_profiling. - // We disable it in CI, since we have a job dedicated to spotless anyway. - enforceCheck false - } - - project.pluginManager.withPlugin('java') { - java { - toggleOffOn() - // set explicit target to workaround https://github.com/diffplug/spotless/issues/1163 - target 'src/**/*.java' - // ignore embedded test projects and everything in build dir, e.g. generated sources - targetExclude('src/test/resources/**', buildDirectoryFiles) - tableTestFormatter('1.1.1') - googleJavaFormat('1.35.0') - } - } - - def isRootProject = project == project.rootProject - groovyGradle { - toggleOffOn() - // same as groovy, but for .gradle (defaults to '*.gradle') - if (isRootProject) { - // only do this for the root project since the instrumentation project has a subproject and directory named gradle - // that will confuse task dependencies - target '*.gradle', 'gradle/**/*.gradle' - } else { - target '*.gradle' - } - greclipse().configFile(configPath + '/enforcement/spotless-groovy.properties') - } - - kotlinGradle { - toggleOffOn() - // same as kotlin, but for .gradle.kts files (defaults to '*.gradle.kts') - target '*.gradle.kts' - ktlint('1.8.0').editorConfigOverride([ - // Disable trailing comma rules to minimize diff. - 'ktlint_standard_trailing-comma-on-call-site': 'disabled', - 'ktlint_standard_trailing-comma-on-declaration-site': 'disabled' - ]) - } - - project.pluginManager.withPlugin('groovy') { - groovy { - toggleOffOn() - if (!groovySkipJavaExclude) { - excludeJava() // excludes all Java sources within the Groovy source dirs from formatting - // the Groovy Eclipse formatter extends the Java Eclipse formatter, - // so it formats Java files by default (unless `excludeJava` is used). - } - targetExclude(buildDirectoryFiles) - greclipse().configFile(configPath + '/enforcement/spotless-groovy.properties') - } - } - - project.pluginManager.withPlugin('scala') { - scala { - toggleOffOn() - targetExclude(buildDirectoryFiles) - // TODO: For some reason Scala format is working correctly with this version only. - scalafmt('3.8.6').configFile(configPath + '/enforcement/spotless-scalafmt.conf') - } - } - - format 'markdown', { - toggleOffOn() - target '*.md', '.github/**/*.md', 'src/**/*.md', 'application/**/*.md' - leadingTabsToSpaces() - endWithNewline() - } - - format 'misc', { - toggleOffOn() - target '.gitignore', '*.sh', 'tooling/*.sh', '.gitlab/*.sh' - leadingTabsToSpaces() - trimTrailingWhitespace() - endWithNewline() - } - - project.pluginManager.withPlugin('kotlin') { - kotlin { - toggleOffOn() - targetExclude(buildDirectoryFiles) - ktlint('1.8.0').editorConfigOverride([ - // Disable trailing comma rules to minimize diff. - 'ktlint_standard_trailing-comma-on-call-site': 'disabled', - 'ktlint_standard_trailing-comma-on-declaration-site': 'disabled' - ]) - } - } -} - - -tasks.register('formatCode') { - dependsOn 'spotlessApply' -} -tasks.named("check") { - dependsOn 'spotlessCheck' -} diff --git a/test-published-dependencies/build.gradle b/test-published-dependencies/build.gradle index 0552f24244b..1ba28bf3cc8 100644 --- a/test-published-dependencies/build.gradle +++ b/test-published-dependencies/build.gradle @@ -1,7 +1,3 @@ -plugins { - id 'com.diffplug.spotless' version '8.4.0' -} - def sharedConfigDirectory = "$rootDir/../gradle" rootProject.ext.sharedConfigDirectory = sharedConfigDirectory @@ -13,5 +9,4 @@ allprojects { version = versionFromFile apply from: "$sharedConfigDirectory/repositories.gradle" - apply from: "$sharedConfigDirectory/spotless.gradle" } From d6439af1e9b7a227b77a10c8710e09e6633ef13b Mon Sep 17 00:00:00 2001 From: Alexey Kuznetsov Date: Fri, 15 May 2026 16:43:50 -0400 Subject: [PATCH 2/5] Spotless will hard fail on /** ... */ comments. --- ...ce-java.profiling-ddprof-override.gradle.kts | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/buildSrc/src/main/kotlin/dd-trace-java.profiling-ddprof-override.gradle.kts b/buildSrc/src/main/kotlin/dd-trace-java.profiling-ddprof-override.gradle.kts index 8fe48f9dc41..a1fff31a01a 100644 --- a/buildSrc/src/main/kotlin/dd-trace-java.profiling-ddprof-override.gradle.kts +++ b/buildSrc/src/main/kotlin/dd-trace-java.profiling-ddprof-override.gradle.kts @@ -1,12 +1,11 @@ -/** - * Convention plugin for overriding ddprof dependency version with snapshot. - * - * When the root project has the property 'ddprofUseSnapshot' set, this plugin: - * 1. Reads the calculated snapshot version from root project - * 2. Overrides all ddprof dependencies to use the snapshot version - * - * Apply this plugin only to projects that depend on ddprof. - */ +// +// Convention plugin for overriding ddprof dependency version with snapshot. +// +// When the root project has the property 'ddprofUseSnapshot' set, this plugin: +// 1. Reads the calculated snapshot version from root project +// 2. Overrides all ddprof dependencies to use the snapshot version +// +// Apply this plugin only to projects that depend on ddprof. if (rootProject.hasProperty("ddprofUseSnapshot")) { val ddprofSnapshotVersion = rootProject.property("ddprofSnapshotVersion").toString() From f3d3a5e1e4e8f88346b3f8c65be6ff27f9239639 Mon Sep 17 00:00:00 2001 From: Alexey Kuznetsov Date: Fri, 15 May 2026 16:44:24 -0400 Subject: [PATCH 3/5] Added buildSrc to spotlessScope --- ...trace-java.spotless-conventions.gradle.kts | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/buildSrc/src/main/kotlin/dd-trace-java.spotless-conventions.gradle.kts b/buildSrc/src/main/kotlin/dd-trace-java.spotless-conventions.gradle.kts index e54b16606a9..c8711ee864e 100644 --- a/buildSrc/src/main/kotlin/dd-trace-java.spotless-conventions.gradle.kts +++ b/buildSrc/src/main/kotlin/dd-trace-java.spotless-conventions.gradle.kts @@ -63,6 +63,7 @@ allprojects { val commonExcludes = listOf( "build/**", "buildSrc/build/**", + "buildSrc/**/build/**", "dd-java-agent/agent-jmxfetch/**" ) @@ -80,6 +81,24 @@ allprojects { greclipse().configFile("$rootDir/gradle/enforcement/spotless-groovy.properties") } + // buildSrc is a separate Gradle build, so its non-script sources are not + // covered by the per-subproject configuration below. Format them from root + // via file-glob targets so a single `./gradlew spotlessApply` covers them. + kotlin { + toggleOffOn() + target("buildSrc/**/*.kt") + targetExclude(commonExcludes) + ktlint(ktlintVersion).editorConfigOverride(ktlintEditorConfigOverride) + } + + java { + toggleOffOn() + target("buildSrc/**/*.java") + targetExclude(commonExcludes) + tableTestFormatter(tableTestFormatterVersion) + googleJavaFormat(googleJavaFormatVersion) + } + format("markdown") { toggleOffOn() target("*.md", ".github/**/*.md", "src/**/*.md", "app*/**/*.md") From faf291a1680397fd74e31ec7b8ea078f6ca7194d Mon Sep 17 00:00:00 2001 From: Alexey Kuznetsov Date: Fri, 15 May 2026 21:31:29 -0400 Subject: [PATCH 4/5] Fixed review comments. Code cleanup. --- buildSrc/build.gradle.kts | 5 + .../spotless/SpotlessConventionsPlugin.kt | 267 ++++++++++++++++++ ...trace-java.spotless-conventions.gradle.kts | 158 ----------- gradle/java_no_deps.gradle | 5 +- 4 files changed, 275 insertions(+), 160 deletions(-) create mode 100644 buildSrc/src/main/kotlin/datadog/gradle/plugin/spotless/SpotlessConventionsPlugin.kt delete mode 100644 buildSrc/src/main/kotlin/dd-trace-java.spotless-conventions.gradle.kts diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index 113ea705280..24b1c34892b 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -86,6 +86,11 @@ gradlePlugin { id = "dd-trace-java.instrumentation-naming" implementationClass = "datadog.gradle.plugin.naming.InstrumentationNamingPlugin" } + + create("spotless-conventions") { + id = "dd-trace-java.spotless-conventions" + implementationClass = "datadog.gradle.plugin.spotless.SpotlessConventionsPlugin" + } } } diff --git a/buildSrc/src/main/kotlin/datadog/gradle/plugin/spotless/SpotlessConventionsPlugin.kt b/buildSrc/src/main/kotlin/datadog/gradle/plugin/spotless/SpotlessConventionsPlugin.kt new file mode 100644 index 00000000000..0492855a97f --- /dev/null +++ b/buildSrc/src/main/kotlin/datadog/gradle/plugin/spotless/SpotlessConventionsPlugin.kt @@ -0,0 +1,267 @@ +package datadog.gradle.plugin.spotless + +import com.diffplug.gradle.spotless.FormatExtension +import com.diffplug.gradle.spotless.GroovyExtension +import com.diffplug.gradle.spotless.GroovyGradleExtension +import com.diffplug.gradle.spotless.JavaExtension +import com.diffplug.gradle.spotless.KotlinExtension +import com.diffplug.gradle.spotless.KotlinGradleExtension +import com.diffplug.gradle.spotless.ScalaExtension +import com.diffplug.gradle.spotless.SpotlessExtension +import com.diffplug.gradle.spotless.SpotlessExtensionPredeclare +import org.gradle.api.Action +import org.gradle.api.Plugin +import org.gradle.api.Project + +class SpotlessConventionsPlugin : Plugin { + private companion object { + const val GOOGLE_JAVA_FORMAT_VERSION = "1.35.0" + const val TABLE_TEST_FORMATTER_VERSION = "1.1.1" + const val KTLINT_VERSION = "1.8.0" + const val SCALAFMT_VERSION = "3.11.1" + + val KTLINT_EDITOR_CONFIG_OVERRIDE = + mapOf( + "ktlint_standard_trailing-comma-on-call-site" to "disabled", + "ktlint_standard_trailing-comma-on-declaration-site" to "disabled" + ) + + val EXCLUDED_PROJECTS = setOf(":dd-java-agent:agent-jmxfetch") + } + + override fun apply(project: Project) { + if (project.path in EXCLUDED_PROJECTS) { + return + } + + project.pluginManager.apply("com.diffplug.spotless") + + if (project == project.rootProject) { + configurePredeclaredDependencies(project) + configureRootFormatting(project) + } else { + configureProjectFormatting(project) + } + } + + private fun configurePredeclaredDependencies(project: Project) { + project.extensions.configure( + SpotlessExtensionPredeclare::class.java, + object : Action { + override fun execute(spotlessPredeclare: SpotlessExtensionPredeclare) { + spotlessPredeclare.java(object : Action { + override fun execute(java: JavaExtension) { + java.tableTestFormatter(TABLE_TEST_FORMATTER_VERSION) + java.googleJavaFormat(GOOGLE_JAVA_FORMAT_VERSION) + } + }) + + spotlessPredeclare.groovyGradle(object : Action { + override fun execute(groovyGradle: GroovyGradleExtension) { + groovyGradle.greclipse() + } + }) + + spotlessPredeclare.groovy(object : Action { + override fun execute(groovy: GroovyExtension) { + groovy.greclipse() + } + }) + + spotlessPredeclare.kotlinGradle(object : Action { + override fun execute(kotlinGradle: KotlinGradleExtension) { + kotlinGradle.ktlint(KTLINT_VERSION) + } + }) + + spotlessPredeclare.kotlin(object : Action { + override fun execute(kotlin: KotlinExtension) { + kotlin.ktlint(KTLINT_VERSION) + } + }) + + spotlessPredeclare.scala(object : Action { + override fun execute(scala: ScalaExtension) { + scala.scalafmt(SCALAFMT_VERSION) + } + }) + } + } + ) + } + + private fun configureRootFormatting(project: Project) { + project.extensions.configure( + SpotlessExtension::class.java, + object : Action { + override fun execute(spotless: SpotlessExtension) { + configureSkipSpotless(project, spotless) + + val rootExcludes = listOf( + "build/**", + "buildSrc/build/**", + "buildSrc/**/build/**", + "test-published-dependencies/**/build/**" + ) + + spotless.kotlinGradle(object : Action { + override fun execute(kotlinGradle: KotlinGradleExtension) { + kotlinGradle.toggleOffOn() + kotlinGradle.target( + "*.gradle.kts", + "buildSrc/**/*.gradle.kts", + "gradle/**/*.gradle.kts", + "test-published-dependencies/**/*.gradle.kts" + ) + kotlinGradle.targetExclude(rootExcludes) + kotlinGradle.ktlint(KTLINT_VERSION) + .editorConfigOverride(KTLINT_EDITOR_CONFIG_OVERRIDE) + } + }) + + spotless.groovyGradle(object : Action { + override fun execute(groovyGradle: GroovyGradleExtension) { + groovyGradle.toggleOffOn() + groovyGradle.target( + "*.gradle", + "buildSrc/**/*.gradle", + "gradle/**/*.gradle", + "test-published-dependencies/**/*.gradle" + ) + groovyGradle.targetExclude(rootExcludes) + groovyGradle.greclipse().configFile("${project.rootDir}/gradle/enforcement/spotless-groovy.properties") + } + }) + + spotless.kotlin(object : Action { + override fun execute(kotlin: KotlinExtension) { + kotlin.toggleOffOn() + kotlin.target("buildSrc/**/*.kt") + kotlin.targetExclude(rootExcludes) + kotlin.ktlint(KTLINT_VERSION) + .editorConfigOverride(KTLINT_EDITOR_CONFIG_OVERRIDE) + } + }) + + spotless.java(object : Action { + override fun execute(java: JavaExtension) { + java.toggleOffOn() + java.target("buildSrc/**/*.java", "test-published-dependencies/**/src/**/*.java") + java.targetExclude(rootExcludes) + java.tableTestFormatter(TABLE_TEST_FORMATTER_VERSION) + java.googleJavaFormat(GOOGLE_JAVA_FORMAT_VERSION) + } + }) + + spotless.format( + "markdown", + object : Action { + override fun execute(markdown: FormatExtension) { + markdown.toggleOffOn() + markdown.target("*.md", ".github/**/*.md", "src/**/*.md", "app*/**/*.md") + markdown.leadingTabsToSpaces() + markdown.endWithNewline() + } + } + ) + + spotless.format( + "misc", + object : Action { + override fun execute(misc: FormatExtension) { + misc.toggleOffOn() + misc.target(".gitignore", "*.sh", "tooling/*.sh", ".gitlab/*.sh") + misc.leadingTabsToSpaces() + misc.trimTrailingWhitespace() + misc.endWithNewline() + } + } + ) + } + } + ) + } + + private fun configureProjectFormatting(project: Project) { + project.extensions.configure( + SpotlessExtension::class.java, + object : Action { + override fun execute(spotless: SpotlessExtension) { + configureSkipSpotless(project, spotless) + + val commonExcludes = listOf("build/**", "src/test/resources/**") + + spotless.kotlinGradle(object : Action { + override fun execute(kotlinGradle: KotlinGradleExtension) { + kotlinGradle.toggleOffOn() + kotlinGradle.target("*.gradle.kts") + kotlinGradle.ktlint(KTLINT_VERSION) + .editorConfigOverride(KTLINT_EDITOR_CONFIG_OVERRIDE) + } + }) + + spotless.groovyGradle(object : Action { + override fun execute(groovyGradle: GroovyGradleExtension) { + groovyGradle.toggleOffOn() + groovyGradle.target("*.gradle") + groovyGradle.greclipse().configFile("${project.rootDir}/gradle/enforcement/spotless-groovy.properties") + } + }) + + project.pluginManager.withPlugin("java") { + spotless.java(object : Action { + override fun execute(java: JavaExtension) { + java.toggleOffOn() + java.target("src/**/*.java", "app*/**/*.java") + java.targetExclude(commonExcludes) + java.tableTestFormatter(TABLE_TEST_FORMATTER_VERSION) + java.googleJavaFormat(GOOGLE_JAVA_FORMAT_VERSION) + } + }) + } + + project.pluginManager.withPlugin("org.jetbrains.kotlin.jvm") { + spotless.kotlin(object : Action { + override fun execute(kotlin: KotlinExtension) { + kotlin.toggleOffOn() + kotlin.target("src/**/*.kt", "app*/**/*.kt") + kotlin.targetExclude(commonExcludes) + kotlin.ktlint(KTLINT_VERSION) + .editorConfigOverride(KTLINT_EDITOR_CONFIG_OVERRIDE) + } + }) + } + + project.pluginManager.withPlugin("scala") { + spotless.scala(object : Action { + override fun execute(scala: ScalaExtension) { + scala.toggleOffOn() + scala.target("src/**/*.scala", "app*/**/*.scala") + scala.targetExclude(commonExcludes) + scala.scalafmt(SCALAFMT_VERSION) + .configFile("${project.rootDir}/gradle/enforcement/spotless-scalafmt.conf") + } + }) + } + + project.pluginManager.withPlugin("groovy") { + spotless.groovy(object : Action { + override fun execute(groovy: GroovyExtension) { + groovy.toggleOffOn() + groovy.target("src/**/*.groovy", "app*/**/*.groovy") + groovy.targetExclude(commonExcludes) + groovy.greclipse().configFile("${project.rootDir}/gradle/enforcement/spotless-groovy.properties") + } + }) + } + } + } + ) + } + + private fun configureSkipSpotless(project: Project, spotless: SpotlessExtension) { + if (project.rootProject.hasProperty("skipSpotless")) { + spotless.setEnforceCheck(false) + } + } +} diff --git a/buildSrc/src/main/kotlin/dd-trace-java.spotless-conventions.gradle.kts b/buildSrc/src/main/kotlin/dd-trace-java.spotless-conventions.gradle.kts deleted file mode 100644 index c8711ee864e..00000000000 --- a/buildSrc/src/main/kotlin/dd-trace-java.spotless-conventions.gradle.kts +++ /dev/null @@ -1,158 +0,0 @@ -import com.diffplug.gradle.spotless.SpotlessExtension -import com.diffplug.gradle.spotless.SpotlessExtensionPredeclare - -plugins { - id("com.diffplug.spotless") -} - -val googleJavaFormatVersion = "1.35.0" -val tableTestFormatterVersion = "1.1.1" -val ktlintVersion = "1.8.0" -val scalafmtVersion = "3.11.1" -val ktlintEditorConfigOverride = mapOf( - "ktlint_standard_trailing-comma-on-call-site" to "disabled", - "ktlint_standard_trailing-comma-on-declaration-site" to "disabled" -) - -// Resolve formatter dependencies once, then let all subprojects reuse the cached provisioner. -configure { - java { - tableTestFormatter(tableTestFormatterVersion) - googleJavaFormat(googleJavaFormatVersion) - } - - groovyGradle { - greclipse() - } - - groovy { - greclipse() - } - - kotlinGradle { - ktlint(ktlintVersion) - } - - kotlin { - ktlint(ktlintVersion) - } - - scala { - scalafmt(scalafmtVersion) - } -} - -// List of projects to exclude from processing by Spotless. -val spotlessExcludedProjects = setOf(":dd-java-agent:agent-jmxfetch") - -// Spotless applied per-module for parallel execution, configured centrally here. -allprojects { - if (path in spotlessExcludedProjects) { - return@allprojects - } - - apply(plugin = "com.diffplug.spotless") - - configure { - if (rootProject.hasProperty("skipSpotless")) { - isEnforceCheck = false - } - - // Gradle files and other formats we process globally from root - if (project == rootProject) { - val commonExcludes = listOf( - "build/**", - "buildSrc/build/**", - "buildSrc/**/build/**", - "dd-java-agent/agent-jmxfetch/**" - ) - - kotlinGradle { - toggleOffOn() - target("**/*.gradle.kts") - targetExclude(commonExcludes) - ktlint(ktlintVersion).editorConfigOverride(ktlintEditorConfigOverride) - } - - groovyGradle { - toggleOffOn() - target("**/*.gradle") - targetExclude(commonExcludes) - greclipse().configFile("$rootDir/gradle/enforcement/spotless-groovy.properties") - } - - // buildSrc is a separate Gradle build, so its non-script sources are not - // covered by the per-subproject configuration below. Format them from root - // via file-glob targets so a single `./gradlew spotlessApply` covers them. - kotlin { - toggleOffOn() - target("buildSrc/**/*.kt") - targetExclude(commonExcludes) - ktlint(ktlintVersion).editorConfigOverride(ktlintEditorConfigOverride) - } - - java { - toggleOffOn() - target("buildSrc/**/*.java") - targetExclude(commonExcludes) - tableTestFormatter(tableTestFormatterVersion) - googleJavaFormat(googleJavaFormatVersion) - } - - format("markdown") { - toggleOffOn() - target("*.md", ".github/**/*.md", "src/**/*.md", "app*/**/*.md") - leadingTabsToSpaces() - endWithNewline() - } - - format("misc") { - toggleOffOn() - target(".gitignore", "*.sh", "tooling/*.sh", ".gitlab/*.sh") - leadingTabsToSpaces() - trimTrailingWhitespace() - endWithNewline() - } - } else { - // Configure source code formatting. - val commonExcludes = listOf("build/**", "src/test/resources/**") - - pluginManager.withPlugin("java") { - java { - toggleOffOn() - target("src/**/*.java", "app*/**/*.java") - targetExclude(commonExcludes) - tableTestFormatter(tableTestFormatterVersion) - googleJavaFormat(googleJavaFormatVersion) - } - } - - pluginManager.withPlugin("org.jetbrains.kotlin.jvm") { - kotlin { - toggleOffOn() - target("src/**/*.kt", "app*/**/*.kt") - targetExclude(commonExcludes) - ktlint(ktlintVersion).editorConfigOverride(ktlintEditorConfigOverride) - } - } - - pluginManager.withPlugin("scala") { - scala { - toggleOffOn() - target("src/**/*.scala", "app*/**/*.scala") - targetExclude(commonExcludes) - scalafmt(scalafmtVersion).configFile("$rootDir/gradle/enforcement/spotless-scalafmt.conf") - } - } - - pluginManager.withPlugin("groovy") { - groovy { - toggleOffOn() - target("src/**/*.groovy", "app*/**/*.groovy") - targetExclude(commonExcludes) - greclipse().configFile("$rootDir/gradle/enforcement/spotless-groovy.properties") - } - } - } - } -} diff --git a/gradle/java_no_deps.gradle b/gradle/java_no_deps.gradle index d24aad3ffd5..7cba98eb94f 100644 --- a/gradle/java_no_deps.gradle +++ b/gradle/java_no_deps.gradle @@ -5,14 +5,15 @@ import groovy.transform.CompileStatic import java.nio.file.Files import java.nio.file.LinkOption -apply plugin: 'dd-trace-java.configure-tests' apply plugin: 'java-library' +apply plugin: 'dd-trace-java.configure-tests' +apply plugin: 'dd-trace-java.spotless-conventions' apply plugin: 'dd-trace-java.test-jvm-constraints' apply from: "$rootDir/gradle/codenarc.gradle" apply from: "$rootDir/gradle/forbiddenapis.gradle" -apply from: "$rootDir/gradle/spotbugs.gradle" apply from: "$rootDir/gradle/repositories.gradle" +apply from: "$rootDir/gradle/spotbugs.gradle" apply from: "$rootDir/gradle/test-suites.gradle" // Glue code for Groovy DSL. From 0fe5e87dca9e72d7c18251fd0646cfe5bb1eb59d Mon Sep 17 00:00:00 2001 From: Alexey Kuznetsov Date: Mon, 18 May 2026 14:04:30 -0400 Subject: [PATCH 5/5] Fixed review comments --- .../spotless/SpotlessConventionsPlugin.kt | 320 +++++++----------- 1 file changed, 128 insertions(+), 192 deletions(-) diff --git a/buildSrc/src/main/kotlin/datadog/gradle/plugin/spotless/SpotlessConventionsPlugin.kt b/buildSrc/src/main/kotlin/datadog/gradle/plugin/spotless/SpotlessConventionsPlugin.kt index 0492855a97f..b9a34086c02 100644 --- a/buildSrc/src/main/kotlin/datadog/gradle/plugin/spotless/SpotlessConventionsPlugin.kt +++ b/buildSrc/src/main/kotlin/datadog/gradle/plugin/spotless/SpotlessConventionsPlugin.kt @@ -1,17 +1,10 @@ package datadog.gradle.plugin.spotless -import com.diffplug.gradle.spotless.FormatExtension -import com.diffplug.gradle.spotless.GroovyExtension -import com.diffplug.gradle.spotless.GroovyGradleExtension -import com.diffplug.gradle.spotless.JavaExtension -import com.diffplug.gradle.spotless.KotlinExtension -import com.diffplug.gradle.spotless.KotlinGradleExtension -import com.diffplug.gradle.spotless.ScalaExtension import com.diffplug.gradle.spotless.SpotlessExtension import com.diffplug.gradle.spotless.SpotlessExtensionPredeclare -import org.gradle.api.Action import org.gradle.api.Plugin import org.gradle.api.Project +import org.gradle.kotlin.dsl.configure class SpotlessConventionsPlugin : Plugin { private companion object { @@ -45,218 +38,161 @@ class SpotlessConventionsPlugin : Plugin { } private fun configurePredeclaredDependencies(project: Project) { - project.extensions.configure( - SpotlessExtensionPredeclare::class.java, - object : Action { - override fun execute(spotlessPredeclare: SpotlessExtensionPredeclare) { - spotlessPredeclare.java(object : Action { - override fun execute(java: JavaExtension) { - java.tableTestFormatter(TABLE_TEST_FORMATTER_VERSION) - java.googleJavaFormat(GOOGLE_JAVA_FORMAT_VERSION) - } - }) + project.extensions.configure { + java { + tableTestFormatter(TABLE_TEST_FORMATTER_VERSION) + googleJavaFormat(GOOGLE_JAVA_FORMAT_VERSION) + } - spotlessPredeclare.groovyGradle(object : Action { - override fun execute(groovyGradle: GroovyGradleExtension) { - groovyGradle.greclipse() - } - }) + groovyGradle { + greclipse() + } - spotlessPredeclare.groovy(object : Action { - override fun execute(groovy: GroovyExtension) { - groovy.greclipse() - } - }) + groovy { + greclipse() + } - spotlessPredeclare.kotlinGradle(object : Action { - override fun execute(kotlinGradle: KotlinGradleExtension) { - kotlinGradle.ktlint(KTLINT_VERSION) - } - }) + kotlinGradle { + ktlint(KTLINT_VERSION) + } - spotlessPredeclare.kotlin(object : Action { - override fun execute(kotlin: KotlinExtension) { - kotlin.ktlint(KTLINT_VERSION) - } - }) + kotlin { + ktlint(KTLINT_VERSION) + } - spotlessPredeclare.scala(object : Action { - override fun execute(scala: ScalaExtension) { - scala.scalafmt(SCALAFMT_VERSION) - } - }) - } + scala { + scalafmt(SCALAFMT_VERSION) } - ) + } } private fun configureRootFormatting(project: Project) { - project.extensions.configure( - SpotlessExtension::class.java, - object : Action { - override fun execute(spotless: SpotlessExtension) { - configureSkipSpotless(project, spotless) - - val rootExcludes = listOf( - "build/**", - "buildSrc/build/**", - "buildSrc/**/build/**", - "test-published-dependencies/**/build/**" - ) + project.extensions.configure { + configureSkipSpotless(project, this) + + val rootExcludes = listOf( + "build/**", + "buildSrc/build/**", + "buildSrc/**/build/**", + "test-published-dependencies/**/build/**" + ) - spotless.kotlinGradle(object : Action { - override fun execute(kotlinGradle: KotlinGradleExtension) { - kotlinGradle.toggleOffOn() - kotlinGradle.target( - "*.gradle.kts", - "buildSrc/**/*.gradle.kts", - "gradle/**/*.gradle.kts", - "test-published-dependencies/**/*.gradle.kts" - ) - kotlinGradle.targetExclude(rootExcludes) - kotlinGradle.ktlint(KTLINT_VERSION) - .editorConfigOverride(KTLINT_EDITOR_CONFIG_OVERRIDE) - } - }) + kotlinGradle { + toggleOffOn() + target( + "*.gradle.kts", + "buildSrc/**/*.gradle.kts", + "gradle/**/*.gradle.kts", + "test-published-dependencies/**/*.gradle.kts" + ) + targetExclude(rootExcludes) + ktlint(KTLINT_VERSION) + .editorConfigOverride(KTLINT_EDITOR_CONFIG_OVERRIDE) + } - spotless.groovyGradle(object : Action { - override fun execute(groovyGradle: GroovyGradleExtension) { - groovyGradle.toggleOffOn() - groovyGradle.target( - "*.gradle", - "buildSrc/**/*.gradle", - "gradle/**/*.gradle", - "test-published-dependencies/**/*.gradle" - ) - groovyGradle.targetExclude(rootExcludes) - groovyGradle.greclipse().configFile("${project.rootDir}/gradle/enforcement/spotless-groovy.properties") - } - }) + groovyGradle { + toggleOffOn() + target( + "*.gradle", + "buildSrc/**/*.gradle", + "gradle/**/*.gradle", + "test-published-dependencies/**/*.gradle" + ) + targetExclude(rootExcludes) + greclipse().configFile("${project.rootDir}/gradle/enforcement/spotless-groovy.properties") + } - spotless.kotlin(object : Action { - override fun execute(kotlin: KotlinExtension) { - kotlin.toggleOffOn() - kotlin.target("buildSrc/**/*.kt") - kotlin.targetExclude(rootExcludes) - kotlin.ktlint(KTLINT_VERSION) - .editorConfigOverride(KTLINT_EDITOR_CONFIG_OVERRIDE) - } - }) + kotlin { + toggleOffOn() + target("buildSrc/**/*.kt") + targetExclude(rootExcludes) + ktlint(KTLINT_VERSION) + .editorConfigOverride(KTLINT_EDITOR_CONFIG_OVERRIDE) + } - spotless.java(object : Action { - override fun execute(java: JavaExtension) { - java.toggleOffOn() - java.target("buildSrc/**/*.java", "test-published-dependencies/**/src/**/*.java") - java.targetExclude(rootExcludes) - java.tableTestFormatter(TABLE_TEST_FORMATTER_VERSION) - java.googleJavaFormat(GOOGLE_JAVA_FORMAT_VERSION) - } - }) + java { + toggleOffOn() + target("buildSrc/**/*.java", "test-published-dependencies/**/src/**/*.java") + targetExclude(rootExcludes) + tableTestFormatter(TABLE_TEST_FORMATTER_VERSION) + googleJavaFormat(GOOGLE_JAVA_FORMAT_VERSION) + } - spotless.format( - "markdown", - object : Action { - override fun execute(markdown: FormatExtension) { - markdown.toggleOffOn() - markdown.target("*.md", ".github/**/*.md", "src/**/*.md", "app*/**/*.md") - markdown.leadingTabsToSpaces() - markdown.endWithNewline() - } - } - ) + format("markdown") { + toggleOffOn() + target("*.md", ".github/**/*.md", "src/**/*.md", "app*/**/*.md") + leadingTabsToSpaces() + endWithNewline() + } - spotless.format( - "misc", - object : Action { - override fun execute(misc: FormatExtension) { - misc.toggleOffOn() - misc.target(".gitignore", "*.sh", "tooling/*.sh", ".gitlab/*.sh") - misc.leadingTabsToSpaces() - misc.trimTrailingWhitespace() - misc.endWithNewline() - } - } - ) - } + format("misc") { + toggleOffOn() + target(".gitignore", "*.sh", "tooling/*.sh", ".gitlab/*.sh") + leadingTabsToSpaces() + trimTrailingWhitespace() + endWithNewline() } - ) + } } private fun configureProjectFormatting(project: Project) { - project.extensions.configure( - SpotlessExtension::class.java, - object : Action { - override fun execute(spotless: SpotlessExtension) { - configureSkipSpotless(project, spotless) + project.extensions.configure { + configureSkipSpotless(project, this) - val commonExcludes = listOf("build/**", "src/test/resources/**") + val commonExcludes = listOf("build/**", "src/test/resources/**") - spotless.kotlinGradle(object : Action { - override fun execute(kotlinGradle: KotlinGradleExtension) { - kotlinGradle.toggleOffOn() - kotlinGradle.target("*.gradle.kts") - kotlinGradle.ktlint(KTLINT_VERSION) - .editorConfigOverride(KTLINT_EDITOR_CONFIG_OVERRIDE) - } - }) + kotlinGradle { + toggleOffOn() + target("*.gradle.kts") + ktlint(KTLINT_VERSION) + .editorConfigOverride(KTLINT_EDITOR_CONFIG_OVERRIDE) + } - spotless.groovyGradle(object : Action { - override fun execute(groovyGradle: GroovyGradleExtension) { - groovyGradle.toggleOffOn() - groovyGradle.target("*.gradle") - groovyGradle.greclipse().configFile("${project.rootDir}/gradle/enforcement/spotless-groovy.properties") - } - }) + groovyGradle { + toggleOffOn() + target("*.gradle") + greclipse().configFile("${project.rootDir}/gradle/enforcement/spotless-groovy.properties") + } - project.pluginManager.withPlugin("java") { - spotless.java(object : Action { - override fun execute(java: JavaExtension) { - java.toggleOffOn() - java.target("src/**/*.java", "app*/**/*.java") - java.targetExclude(commonExcludes) - java.tableTestFormatter(TABLE_TEST_FORMATTER_VERSION) - java.googleJavaFormat(GOOGLE_JAVA_FORMAT_VERSION) - } - }) - } + project.pluginManager.withPlugin("java") { + java { + toggleOffOn() + target("src/**/*.java", "app*/**/*.java") + targetExclude(commonExcludes) + tableTestFormatter(TABLE_TEST_FORMATTER_VERSION) + googleJavaFormat(GOOGLE_JAVA_FORMAT_VERSION) + } + } - project.pluginManager.withPlugin("org.jetbrains.kotlin.jvm") { - spotless.kotlin(object : Action { - override fun execute(kotlin: KotlinExtension) { - kotlin.toggleOffOn() - kotlin.target("src/**/*.kt", "app*/**/*.kt") - kotlin.targetExclude(commonExcludes) - kotlin.ktlint(KTLINT_VERSION) - .editorConfigOverride(KTLINT_EDITOR_CONFIG_OVERRIDE) - } - }) - } + project.pluginManager.withPlugin("org.jetbrains.kotlin.jvm") { + kotlin { + toggleOffOn() + target("src/**/*.kt", "app*/**/*.kt") + targetExclude(commonExcludes) + ktlint(KTLINT_VERSION) + .editorConfigOverride(KTLINT_EDITOR_CONFIG_OVERRIDE) + } + } - project.pluginManager.withPlugin("scala") { - spotless.scala(object : Action { - override fun execute(scala: ScalaExtension) { - scala.toggleOffOn() - scala.target("src/**/*.scala", "app*/**/*.scala") - scala.targetExclude(commonExcludes) - scala.scalafmt(SCALAFMT_VERSION) - .configFile("${project.rootDir}/gradle/enforcement/spotless-scalafmt.conf") - } - }) - } + project.pluginManager.withPlugin("scala") { + scala { + toggleOffOn() + target("src/**/*.scala", "app*/**/*.scala") + targetExclude(commonExcludes) + scalafmt(SCALAFMT_VERSION) + .configFile("${project.rootDir}/gradle/enforcement/spotless-scalafmt.conf") + } + } - project.pluginManager.withPlugin("groovy") { - spotless.groovy(object : Action { - override fun execute(groovy: GroovyExtension) { - groovy.toggleOffOn() - groovy.target("src/**/*.groovy", "app*/**/*.groovy") - groovy.targetExclude(commonExcludes) - groovy.greclipse().configFile("${project.rootDir}/gradle/enforcement/spotless-groovy.properties") - } - }) - } + project.pluginManager.withPlugin("groovy") { + groovy { + toggleOffOn() + target("src/**/*.groovy", "app*/**/*.groovy") + targetExclude(commonExcludes) + greclipse().configFile("${project.rootDir}/gradle/enforcement/spotless-groovy.properties") } } - ) + } } private fun configureSkipSpotless(project: Project, spotless: SpotlessExtension) {