From 827c1c70aa5255bd27fb3ff35e07acbbaf172673 Mon Sep 17 00:00:00 2001 From: Brice Dutheil Date: Mon, 15 Sep 2025 16:13:47 +0200 Subject: [PATCH 01/15] refactor: Proper task for muzzle printReferences --- .../gradle/plugin/muzzle/MuzzlePlugin.kt | 8 ++---- .../plugin/muzzle/tasks/AbstractMuzzleTask.kt | 9 ++++++ .../muzzle/tasks/MuzzlePrintReferencesTask.kt | 28 +++++++++++++++++++ .../plugin/muzzle/{ => tasks}/MuzzleTask.kt | 26 ++++------------- 4 files changed, 46 insertions(+), 25 deletions(-) create mode 100644 buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/tasks/AbstractMuzzleTask.kt create mode 100644 buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/tasks/MuzzlePrintReferencesTask.kt rename buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/{ => tasks}/MuzzleTask.kt (80%) diff --git a/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/MuzzlePlugin.kt b/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/MuzzlePlugin.kt index 1e4961a01dd..9b8ca6c14b7 100644 --- a/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/MuzzlePlugin.kt +++ b/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/MuzzlePlugin.kt @@ -5,6 +5,8 @@ import datadog.gradle.plugin.muzzle.MuzzleMavenRepoUtils.muzzleDirectiveToArtifa import datadog.gradle.plugin.muzzle.MuzzleMavenRepoUtils.resolveVersionRange import datadog.gradle.plugin.muzzle.MuzzleReportUtils.dumpVersionRanges import datadog.gradle.plugin.muzzle.MuzzleReportUtils.mergeReports +import datadog.gradle.plugin.muzzle.tasks.MuzzleTask +import datadog.gradle.plugin.muzzle.tasks.MuzzlePrintReferencesTask import org.eclipse.aether.artifact.Artifact import org.gradle.api.NamedDomainObjectProvider import org.gradle.api.Plugin @@ -89,11 +91,7 @@ class MuzzlePlugin : Plugin { dependsOn(compileMuzzle) } - project.tasks.register("printReferences") { - description = "Print references created by instrumentation muzzle" - doLast { - printMuzzle(project) - } + project.tasks.register("printReferences") { dependsOn(compileMuzzle) } diff --git a/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/tasks/AbstractMuzzleTask.kt b/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/tasks/AbstractMuzzleTask.kt new file mode 100644 index 00000000000..f2dab2de15b --- /dev/null +++ b/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/tasks/AbstractMuzzleTask.kt @@ -0,0 +1,9 @@ +package datadog.gradle.plugin.muzzle.tasks + +import org.gradle.api.DefaultTask + +abstract class AbstractMuzzleTask : DefaultTask() { + init { + group = "Muzzle" + } +} diff --git a/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/tasks/MuzzlePrintReferencesTask.kt b/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/tasks/MuzzlePrintReferencesTask.kt new file mode 100644 index 00000000000..a878bebf607 --- /dev/null +++ b/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/tasks/MuzzlePrintReferencesTask.kt @@ -0,0 +1,28 @@ +package datadog.gradle.plugin.muzzle.tasks + +import datadog.gradle.plugin.muzzle.mainSourceSet +import org.gradle.api.Project +import org.gradle.api.tasks.TaskAction +import java.lang.reflect.Method +import java.net.URLClassLoader +import javax.inject.Inject + +abstract class MuzzlePrintReferencesTask @Inject constructor( + private val instrumentationProject: Project +) : AbstractMuzzleTask() { + init { + description = "Print references created by instrumentation muzzle" + } + + @TaskAction + fun printMuzzle() { + val cp = instrumentationProject.mainSourceSet.runtimeClasspath + val cl = URLClassLoader(cp.map { it.toURI().toURL() }.toTypedArray(), null) + val printMethod: Method = cl.loadClass("datadog.trace.agent.tooling.muzzle.MuzzleVersionScanPlugin") + .getMethod( + "printMuzzleReferences", + ClassLoader::class.java + ) + printMethod.invoke(null, cl) + } +} diff --git a/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/MuzzleTask.kt b/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/tasks/MuzzleTask.kt similarity index 80% rename from buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/MuzzleTask.kt rename to buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/tasks/MuzzleTask.kt index 0a2fb159134..8d6e404fce6 100644 --- a/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/MuzzleTask.kt +++ b/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/tasks/MuzzleTask.kt @@ -1,26 +1,23 @@ -package datadog.gradle.plugin.muzzle +package datadog.gradle.plugin.muzzle.tasks +import datadog.gradle.plugin.muzzle.MuzzleAction +import datadog.gradle.plugin.muzzle.MuzzleDirective +import datadog.gradle.plugin.muzzle.allMainSourceSet +import datadog.gradle.plugin.muzzle.mainSourceSet import org.gradle.api.DefaultTask import org.gradle.api.NamedDomainObjectProvider import org.gradle.api.Project import org.gradle.api.artifacts.Configuration import org.gradle.api.file.FileCollection import org.gradle.api.invocation.BuildInvocationDetails -import org.gradle.api.tasks.SourceSet -import org.gradle.api.tasks.SourceSetContainer import org.gradle.jvm.toolchain.JavaLanguageVersion import org.gradle.jvm.toolchain.JavaToolchainService -import org.gradle.kotlin.dsl.getByType import org.gradle.workers.WorkerExecutor import java.lang.reflect.Method import java.net.URLClassLoader import javax.inject.Inject -abstract class MuzzleTask : DefaultTask() { - init { - group = "Muzzle" - } - +abstract class MuzzleTask : AbstractMuzzleTask() { @get:Inject abstract val javaToolchainService: JavaToolchainService @@ -63,17 +60,6 @@ abstract class MuzzleTask : DefaultTask() { } } - fun printMuzzle(instrumentationProject: Project) { - val cp = instrumentationProject.mainSourceSet.runtimeClasspath - val cl = URLClassLoader(cp.map { it.toURI().toURL() }.toTypedArray(), null) - val printMethod: Method = cl.loadClass("datadog.trace.agent.tooling.muzzle.MuzzleVersionScanPlugin") - .getMethod( - "printMuzzleReferences", - ClassLoader::class.java - ) - printMethod.invoke(null, cl) - } - private fun createAgentClassPath(project: Project): FileCollection { project.logger.info("Creating agent classpath for $project") val cp = project.files() From 89662523a63ebf908b6fa080ef0b999101b52ced Mon Sep 17 00:00:00 2001 From: Brice Dutheil Date: Mon, 15 Sep 2025 17:20:22 +0200 Subject: [PATCH 02/15] refactor: Proper tasks for muzzle reports --- .../gradle/plugin/muzzle/MuzzlePlugin.kt | 21 ++--- .../gradle/plugin/muzzle/MuzzleReportUtils.kt | 88 ------------------- .../muzzle/tasks/AbstractMuzzleReportTask.kt | 32 +++++++ .../muzzle/tasks/MuzzleGenerateReportTask.kt | 51 +++++++++++ .../muzzle/tasks/MuzzleMergeReportsTask.kt | 49 +++++++++++ .../muzzle/tasks/MuzzlePrintReferencesTask.kt | 8 +- .../gradle/plugin/muzzle/tasks/MuzzleTask.kt | 4 - 7 files changed, 139 insertions(+), 114 deletions(-) create mode 100644 buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/tasks/AbstractMuzzleReportTask.kt create mode 100644 buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/tasks/MuzzleGenerateReportTask.kt create mode 100644 buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/tasks/MuzzleMergeReportsTask.kt diff --git a/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/MuzzlePlugin.kt b/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/MuzzlePlugin.kt index 9b8ca6c14b7..34ae2672d64 100644 --- a/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/MuzzlePlugin.kt +++ b/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/MuzzlePlugin.kt @@ -3,18 +3,16 @@ package datadog.gradle.plugin.muzzle import datadog.gradle.plugin.muzzle.MuzzleMavenRepoUtils.inverseOf import datadog.gradle.plugin.muzzle.MuzzleMavenRepoUtils.muzzleDirectiveToArtifacts import datadog.gradle.plugin.muzzle.MuzzleMavenRepoUtils.resolveVersionRange -import datadog.gradle.plugin.muzzle.MuzzleReportUtils.dumpVersionRanges -import datadog.gradle.plugin.muzzle.MuzzleReportUtils.mergeReports -import datadog.gradle.plugin.muzzle.tasks.MuzzleTask +import datadog.gradle.plugin.muzzle.tasks.MuzzleGenerateReportTask +import datadog.gradle.plugin.muzzle.tasks.MuzzleMergeReportsTask import datadog.gradle.plugin.muzzle.tasks.MuzzlePrintReferencesTask +import datadog.gradle.plugin.muzzle.tasks.MuzzleTask import org.eclipse.aether.artifact.Artifact import org.gradle.api.NamedDomainObjectProvider import org.gradle.api.Plugin import org.gradle.api.Project import org.gradle.api.Task import org.gradle.api.artifacts.Configuration -import org.gradle.api.plugins.JavaBasePlugin -import org.gradle.api.plugins.JavaPlugin import org.gradle.api.tasks.TaskProvider import org.gradle.kotlin.dsl.create import org.gradle.kotlin.dsl.exclude @@ -95,20 +93,11 @@ class MuzzlePlugin : Plugin { dependsOn(compileMuzzle) } - project.tasks.register("generateMuzzleReport") { - description = "Print instrumentation version report" - doLast { - dumpVersionRanges(project) - } + project.tasks.register("generateMuzzleReport") { dependsOn(compileMuzzle) } - project.tasks.register("mergeMuzzleReports") { - description = "Merge generated version reports in one unique csv" - doLast { - mergeReports(project) - } - } + project.tasks.register("mergeMuzzleReports") val hasRelevantTask = project.gradle.startParameter.taskNames.any { taskName -> // removing leading ':' if present diff --git a/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/MuzzleReportUtils.kt b/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/MuzzleReportUtils.kt index 1808a50b552..5ec4e47f19f 100644 --- a/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/MuzzleReportUtils.kt +++ b/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/MuzzleReportUtils.kt @@ -14,96 +14,8 @@ import java.util.TreeMap import java.util.function.BiFunction internal object MuzzleReportUtils { - private const val MUZZLE_DEPS_RESULTS = "muzzle-deps-results" private const val MUZZLE_TEST_RESULTS = "muzzle-test-results" - fun dumpVersionRanges(project: Project) { - val system: RepositorySystem = MuzzleMavenRepoUtils.newRepositorySystem() - val session: RepositorySystemSession = MuzzleMavenRepoUtils.newRepositorySystemSession(system) - val versions = TreeMap() - - project.extensions.getByType().directives - .filter { !it.isCoreJdk && !it.skipFromReport } - .forEach { directive -> - val range = MuzzleMavenRepoUtils.resolveVersionRange(directive, system, session) - val cp = project.files(project.mainSourceSet.runtimeClasspath).map { it.toURI().toURL() }.toTypedArray() - val cl = URLClassLoader(cp, null) - val partials = resolveInstrumentationAndJarVersions(directive, cl, range.lowestVersion, range.highestVersion) - - partials.forEach { (key, value) -> - versions.merge(key, value, BiFunction { x, y -> - TestedArtifact( - x.instrumentation, x.group, x.module, - lowest(x.lowVersion, y.lowVersion), - highest(x.highVersion, y.highVersion) - ) - }) - } - } - dumpVersionsToCsv(project, versions) - } - - private fun dumpVersionsToCsv(project: Project, versions: SortedMap) { - val filename = project.path.replaceFirst("^:".toRegex(), "").replace(":", "_") - - val verrsionsFile = project.rootProject.layout.buildDirectory.file("$MUZZLE_DEPS_RESULTS/$filename.csv") - with(project.file(verrsionsFile)) { - parentFile.mkdirs() - writeText("instrumentation,jarGroupId,jarArtifactId,lowestVersion,highestVersion\n") - versions.values.forEach { - appendText( - listOf( - it.instrumentation, - it.group, - it.module, - it.lowVersion.toString(), - it.highVersion.toString() - ).joinToString(",") + "\n" - ) - } - project.logger.info("Wrote muzzle versions report to\n $this") - } - } - - /** - * Merges all muzzle report CSVs in the build directory into a single map and writes the merged results to a CSV. - */ - fun mergeReports(project: Project) { - val versionReports = project.fileTree(project.rootProject.layout.buildDirectory.dir(MUZZLE_DEPS_RESULTS)) { - include("*.csv") - } - - val map = TreeMap() - val versionScheme = GenericVersionScheme() - - versionReports.forEach { - project.logger.info("Processing muzzle report: $it") - it.useLines { lines -> - lines.forEachIndexed { idx, line -> - if (idx == 0) return@forEachIndexed // skip header - val split = line.split(",") - val parsed = TestedArtifact( - split[0], - split[1], - split[2], - versionScheme.parseVersion(split[3]), - versionScheme.parseVersion(split[4]) - ) - map.merge(parsed.key(), parsed) { x, y -> - TestedArtifact( - x.instrumentation, - x.group, - x.module, - MuzzleMavenRepoUtils.lowest(x.lowVersion, y.lowVersion), - MuzzleMavenRepoUtils.highest(x.highVersion, y.highVersion) - ) - } - } - } - } - - dumpVersionsToCsv(project, map) - } /** * Generates a JUnit-style XML report for muzzle results. diff --git a/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/tasks/AbstractMuzzleReportTask.kt b/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/tasks/AbstractMuzzleReportTask.kt new file mode 100644 index 00000000000..f86d5636e6c --- /dev/null +++ b/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/tasks/AbstractMuzzleReportTask.kt @@ -0,0 +1,32 @@ +package datadog.gradle.plugin.muzzle.tasks + +import datadog.gradle.plugin.muzzle.TestedArtifact +import java.util.SortedMap + +abstract class AbstractMuzzleReportTask : AbstractMuzzleTask() { + internal fun dumpVersionsToCsv(versions: SortedMap) { + val filename = project.path.replaceFirst("^:".toRegex(), "").replace(":", "_") + + val versionsFile = project.rootProject.layout.buildDirectory.file("${MUZZLE_DEPS_RESULTS}/$filename.csv") + with(project.file(versionsFile)) { + parentFile.mkdirs() + writeText("instrumentation,jarGroupId,jarArtifactId,lowestVersion,highestVersion\n") + versions.values.forEach { + appendText( + listOf( + it.instrumentation, + it.group, + it.module, + it.lowVersion.toString(), + it.highVersion.toString() + ).joinToString(",") + "\n" + ) + } + project.logger.info("Wrote muzzle versions report to\n $this") + } + } + + companion object { + internal const val MUZZLE_DEPS_RESULTS = "muzzle-deps-results" + } +} diff --git a/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/tasks/MuzzleGenerateReportTask.kt b/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/tasks/MuzzleGenerateReportTask.kt new file mode 100644 index 00000000000..b209622b24d --- /dev/null +++ b/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/tasks/MuzzleGenerateReportTask.kt @@ -0,0 +1,51 @@ +package datadog.gradle.plugin.muzzle.tasks + +import datadog.gradle.plugin.muzzle.MuzzleMavenRepoUtils +import datadog.gradle.plugin.muzzle.TestedArtifact +import org.eclipse.aether.util.version.GenericVersionScheme +import org.gradle.api.tasks.TaskAction +import java.util.TreeMap + +abstract class MuzzleGenerateReportTask : AbstractMuzzleReportTask() { + init { + description = "Print instrumentation version report" + } + + /** + * Merges all muzzle report CSVs in the build directory into a single map and writes the merged results to a CSV. + */ + @TaskAction + fun mergeReports() { + val versionReports = project.fileTree(project.rootProject.layout.buildDirectory.dir(MUZZLE_DEPS_RESULTS)) { + include("*.csv") + } + val map = TreeMap() + val versionScheme = GenericVersionScheme() + versionReports.forEach { + project.logger.info("Processing muzzle report: $it") + it.useLines { lines -> + lines.forEachIndexed { idx, line -> + if (idx == 0) return@forEachIndexed // skip header + val split = line.split(",") + val parsed = TestedArtifact( + split[0], + split[1], + split[2], + versionScheme.parseVersion(split[3]), + versionScheme.parseVersion(split[4]) + ) + map.merge(parsed.key(), parsed) { x, y -> + TestedArtifact( + x.instrumentation, + x.group, + x.module, + MuzzleMavenRepoUtils.lowest(x.lowVersion, y.lowVersion), + MuzzleMavenRepoUtils.highest(x.highVersion, y.highVersion) + ) + } + } + } + } + dumpVersionsToCsv(map) + } +} diff --git a/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/tasks/MuzzleMergeReportsTask.kt b/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/tasks/MuzzleMergeReportsTask.kt new file mode 100644 index 00000000000..d443caeae08 --- /dev/null +++ b/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/tasks/MuzzleMergeReportsTask.kt @@ -0,0 +1,49 @@ +package datadog.gradle.plugin.muzzle.tasks + +import datadog.gradle.plugin.muzzle.MuzzleExtension +import datadog.gradle.plugin.muzzle.MuzzleMavenRepoUtils +import datadog.gradle.plugin.muzzle.MuzzleMavenRepoUtils.highest +import datadog.gradle.plugin.muzzle.MuzzleMavenRepoUtils.lowest +import datadog.gradle.plugin.muzzle.MuzzleMavenRepoUtils.resolveInstrumentationAndJarVersions +import datadog.gradle.plugin.muzzle.TestedArtifact +import datadog.gradle.plugin.muzzle.mainSourceSet +import org.eclipse.aether.RepositorySystem +import org.eclipse.aether.RepositorySystemSession +import org.gradle.api.tasks.TaskAction +import org.gradle.kotlin.dsl.getByType +import java.net.URL +import java.net.URLClassLoader +import java.util.TreeMap +import java.util.function.BiFunction + +abstract class MuzzleMergeReportsTask : AbstractMuzzleReportTask() { + init { + description = "Print instrumentation version report" + } + + @TaskAction + fun dumpVersionRanges() { + val system: RepositorySystem = MuzzleMavenRepoUtils.newRepositorySystem() + val session: RepositorySystemSession = MuzzleMavenRepoUtils.newRepositorySystemSession(system) + val versions = TreeMap() + project.extensions.getByType().directives + .filter { !it.isCoreJdk && !it.skipFromReport } + .forEach { directive -> + val range = MuzzleMavenRepoUtils.resolveVersionRange(directive, system, session) + val cp = project.files(project.mainSourceSet.runtimeClasspath).map { it.toURI().toURL() }.toTypedArray() + val cl = URLClassLoader(cp, null) + val partials = resolveInstrumentationAndJarVersions(directive, cl, range.lowestVersion, range.highestVersion) + + partials.forEach { (key, value) -> + versions.merge(key, value, BiFunction { x, y -> + TestedArtifact( + x.instrumentation, x.group, x.module, + lowest(x.lowVersion, y.lowVersion), + highest(x.highVersion, y.highVersion) + ) + }) + } + } + dumpVersionsToCsv(versions) + } +} diff --git a/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/tasks/MuzzlePrintReferencesTask.kt b/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/tasks/MuzzlePrintReferencesTask.kt index a878bebf607..0a80c168b11 100644 --- a/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/tasks/MuzzlePrintReferencesTask.kt +++ b/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/tasks/MuzzlePrintReferencesTask.kt @@ -1,22 +1,18 @@ package datadog.gradle.plugin.muzzle.tasks import datadog.gradle.plugin.muzzle.mainSourceSet -import org.gradle.api.Project import org.gradle.api.tasks.TaskAction import java.lang.reflect.Method import java.net.URLClassLoader -import javax.inject.Inject -abstract class MuzzlePrintReferencesTask @Inject constructor( - private val instrumentationProject: Project -) : AbstractMuzzleTask() { +abstract class MuzzlePrintReferencesTask : AbstractMuzzleTask() { init { description = "Print references created by instrumentation muzzle" } @TaskAction fun printMuzzle() { - val cp = instrumentationProject.mainSourceSet.runtimeClasspath + val cp = project.mainSourceSet.runtimeClasspath val cl = URLClassLoader(cp.map { it.toURI().toURL() }.toTypedArray(), null) val printMethod: Method = cl.loadClass("datadog.trace.agent.tooling.muzzle.MuzzleVersionScanPlugin") .getMethod( diff --git a/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/tasks/MuzzleTask.kt b/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/tasks/MuzzleTask.kt index 8d6e404fce6..8fc1e0cd9a3 100644 --- a/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/tasks/MuzzleTask.kt +++ b/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/tasks/MuzzleTask.kt @@ -3,8 +3,6 @@ package datadog.gradle.plugin.muzzle.tasks import datadog.gradle.plugin.muzzle.MuzzleAction import datadog.gradle.plugin.muzzle.MuzzleDirective import datadog.gradle.plugin.muzzle.allMainSourceSet -import datadog.gradle.plugin.muzzle.mainSourceSet -import org.gradle.api.DefaultTask import org.gradle.api.NamedDomainObjectProvider import org.gradle.api.Project import org.gradle.api.artifacts.Configuration @@ -13,8 +11,6 @@ import org.gradle.api.invocation.BuildInvocationDetails import org.gradle.jvm.toolchain.JavaLanguageVersion import org.gradle.jvm.toolchain.JavaToolchainService import org.gradle.workers.WorkerExecutor -import java.lang.reflect.Method -import java.net.URLClassLoader import javax.inject.Inject abstract class MuzzleTask : AbstractMuzzleTask() { From 28efcadbffd2f53e2a2c03b618956b49e76d04b7 Mon Sep 17 00:00:00 2001 From: Brice Dutheil Date: Mon, 15 Sep 2025 18:12:30 +0200 Subject: [PATCH 03/15] refactor: Proper tasks for muzzle checks --- .../gradle/plugin/muzzle/MuzzlePlugin.kt | 33 ++++++------ .../gradle/plugin/muzzle/MuzzleReportUtils.kt | 44 --------------- .../plugin/muzzle/tasks/MuzzleEndTask.kt | 36 +++++++++++++ .../gradle/plugin/muzzle/tasks/MuzzleTask.kt | 54 +++++++++++++++---- 4 files changed, 97 insertions(+), 70 deletions(-) delete mode 100644 buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/MuzzleReportUtils.kt create mode 100644 buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/tasks/MuzzleEndTask.kt diff --git a/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/MuzzlePlugin.kt b/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/MuzzlePlugin.kt index 34ae2672d64..f468ac228ca 100644 --- a/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/MuzzlePlugin.kt +++ b/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/MuzzlePlugin.kt @@ -3,6 +3,7 @@ package datadog.gradle.plugin.muzzle import datadog.gradle.plugin.muzzle.MuzzleMavenRepoUtils.inverseOf import datadog.gradle.plugin.muzzle.MuzzleMavenRepoUtils.muzzleDirectiveToArtifacts import datadog.gradle.plugin.muzzle.MuzzleMavenRepoUtils.resolveVersionRange +import datadog.gradle.plugin.muzzle.tasks.MuzzleEndTask import datadog.gradle.plugin.muzzle.tasks.MuzzleGenerateReportTask import datadog.gradle.plugin.muzzle.tasks.MuzzleMergeReportsTask import datadog.gradle.plugin.muzzle.tasks.MuzzlePrintReferencesTask @@ -79,13 +80,15 @@ class MuzzlePlugin : Plugin { } val muzzleTask = project.tasks.register("muzzle") { - description = "Run instrumentation muzzle on compile time dependencies" - doLast { - if (!project.extensions.getByType().directives.any { it.assertPass }) { - project.logger.info("No muzzle pass directives configured. Asserting pass against instrumentation compile-time dependencies") - assertMuzzle(muzzleBootstrap, muzzleTooling, project) - } - } + this.muzzleBootstrap.set(muzzleBootstrap) + this.muzzleTooling.set(muzzleTooling) + // description = "Run instrumentation muzzle on compile time dependencies" + // doLast { + // if (!project.extensions.getByType().directives.any { it.assertPass }) { + // project.logger.info("No muzzle pass directives configured. Asserting pass against instrumentation compile-time dependencies") + // assertMuzzle(muzzleBootstrap, muzzleTooling, project) + // } + // } dependsOn(compileMuzzle) } @@ -144,11 +147,8 @@ class MuzzlePlugin : Plugin { project.logger.info("configured $directive") } - val timingTask = project.tasks.register("muzzle-end") { - doLast { - val endTime = System.currentTimeMillis() - MuzzleReportUtils.generateResultsXML(project, endTime - startTime) - } + val timingTask = project.tasks.register("muzzle-end") { + startTimeMs.set(startTime) } // last muzzle task to run runAfter.configure { @@ -239,9 +239,12 @@ class MuzzlePlugin : Plugin { } val muzzleTask = instrumentationProject.tasks.register(muzzleTaskName) { - doLast { - assertMuzzle(muzzleBootstrap, muzzleTooling, instrumentationProject, muzzleDirective) - } + this.muzzleDirective.set(muzzleDirective) + this.muzzleBootstrap.set(muzzleBootstrap) + this.muzzleTooling.set(muzzleTooling) + // doLast { + // assertMuzzle(muzzleBootstrap, muzzleTooling, instrumentationProject, muzzleDirective) + // } } runAfterTask.configure { diff --git a/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/MuzzleReportUtils.kt b/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/MuzzleReportUtils.kt deleted file mode 100644 index 5ec4e47f19f..00000000000 --- a/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/MuzzleReportUtils.kt +++ /dev/null @@ -1,44 +0,0 @@ -package datadog.gradle.plugin.muzzle - -import datadog.gradle.plugin.muzzle.MuzzleMavenRepoUtils.highest -import datadog.gradle.plugin.muzzle.MuzzleMavenRepoUtils.lowest -import datadog.gradle.plugin.muzzle.MuzzleMavenRepoUtils.resolveInstrumentationAndJarVersions -import org.eclipse.aether.RepositorySystem -import org.eclipse.aether.RepositorySystemSession -import org.eclipse.aether.util.version.GenericVersionScheme -import org.gradle.api.Project -import org.gradle.kotlin.dsl.getByType -import java.net.URLClassLoader -import java.util.SortedMap -import java.util.TreeMap -import java.util.function.BiFunction - -internal object MuzzleReportUtils { - private const val MUZZLE_TEST_RESULTS = "muzzle-test-results" - - - /** - * Generates a JUnit-style XML report for muzzle results. - */ - fun generateResultsXML(project: Project, millis: Long) { - val seconds = millis.toDouble() / 1000.0 - val name = "${project.path}:muzzle" - val dirname = name.replaceFirst("^:".toRegex(), "").replace(":", "_") - - val dir = project.rootProject.layout.buildDirectory.dir("$MUZZLE_TEST_RESULTS/$dirname/results.xml") - - with(project.file(dir)) { - parentFile.mkdirs() - writeText( - """ - - - - - - """.trimIndent() - ) - project.logger.info("Wrote muzzle results report to\n $this") - } - } -} diff --git a/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/tasks/MuzzleEndTask.kt b/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/tasks/MuzzleEndTask.kt new file mode 100644 index 00000000000..13f5f664567 --- /dev/null +++ b/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/tasks/MuzzleEndTask.kt @@ -0,0 +1,36 @@ +package datadog.gradle.plugin.muzzle.tasks + +import org.gradle.api.provider.Property +import org.gradle.api.tasks.Input +import org.gradle.api.tasks.TaskAction + +abstract class MuzzleEndTask : AbstractMuzzleTask() { + @get:Input + abstract val startTimeMs: Property + + @TaskAction + fun generatesResultFile() { + val endTimeMs = System.currentTimeMillis() + val seconds = (endTimeMs - startTimeMs.get()).toDouble() / 1000.0 + val name = "${project.path}:muzzle" + val dirname = name.replaceFirst("^:".toRegex(), "").replace(":", "_") + val dir = project.rootProject.layout.buildDirectory.dir("${MUZZLE_TEST_RESULTS}/$dirname/results.xml") + with(project.file(dir)) { + parentFile.mkdirs() + writeText( + """ + + + + + + """.trimIndent() + ) + project.logger.info("Wrote muzzle results report to\n $this") + } + } + + companion object { + private const val MUZZLE_TEST_RESULTS = "muzzle-test-results" + } +} diff --git a/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/tasks/MuzzleTask.kt b/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/tasks/MuzzleTask.kt index 8fc1e0cd9a3..47f5385a93e 100644 --- a/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/tasks/MuzzleTask.kt +++ b/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/tasks/MuzzleTask.kt @@ -2,18 +2,32 @@ package datadog.gradle.plugin.muzzle.tasks import datadog.gradle.plugin.muzzle.MuzzleAction import datadog.gradle.plugin.muzzle.MuzzleDirective +import datadog.gradle.plugin.muzzle.MuzzleExtension import datadog.gradle.plugin.muzzle.allMainSourceSet -import org.gradle.api.NamedDomainObjectProvider import org.gradle.api.Project import org.gradle.api.artifacts.Configuration import org.gradle.api.file.FileCollection import org.gradle.api.invocation.BuildInvocationDetails +import org.gradle.api.provider.Property +import org.gradle.api.tasks.Input +import org.gradle.api.tasks.InputFiles +import org.gradle.api.tasks.Optional +import org.gradle.api.tasks.TaskAction import org.gradle.jvm.toolchain.JavaLanguageVersion import org.gradle.jvm.toolchain.JavaToolchainService +import org.gradle.kotlin.dsl.getByType import org.gradle.workers.WorkerExecutor import javax.inject.Inject abstract class MuzzleTask : AbstractMuzzleTask() { + override fun getDescription(): String { + return if (muzzleDirective.isPresent) { + "Run instrumentation muzzle on ${muzzleDirective.get().name} dependency" + } else { + "Run instrumentation muzzle on compile time dependencies" + } + } + @get:Inject abstract val javaToolchainService: JavaToolchainService @@ -23,12 +37,30 @@ abstract class MuzzleTask : AbstractMuzzleTask() { @get:Inject abstract val workerExecutor: WorkerExecutor - fun assertMuzzle( - muzzleBootstrap: NamedDomainObjectProvider, - muzzleTooling: NamedDomainObjectProvider, - instrumentationProject: Project, - muzzleDirective: MuzzleDirective? = null - ) { + @get:InputFiles + abstract val muzzleBootstrap: Property + + @get:InputFiles + abstract val muzzleTooling: Property + + @get:Input + @get:Optional + abstract val muzzleDirective : Property + + @TaskAction + fun muzzle() { + when { + !project.extensions.getByType().directives.any { it.assertPass } -> { + project.logger.info("No muzzle pass directives configured. Asserting pass against instrumentation compile-time dependencies") + assertMuzzle() + } + muzzleDirective.isPresent -> { + assertMuzzle(muzzleDirective.get()) + } + } + } + + private fun assertMuzzle(muzzleDirective: MuzzleDirective? = null) { val workQueue = if (muzzleDirective?.javaVersion != null) { val javaLauncher = javaToolchainService.launcherFor { languageVersion.set(JavaLanguageVersion.of(muzzleDirective.javaVersion!!)) @@ -43,10 +75,10 @@ abstract class MuzzleTask : AbstractMuzzleTask() { } workQueue.submit(MuzzleAction::class.java) { buildStartedTime.set(invocationDetails.buildStartedTime) - bootstrapClassPath.setFrom(muzzleBootstrap.get()) - toolingClassPath.setFrom(muzzleTooling.get()) - instrumentationClassPath.setFrom(createAgentClassPath(instrumentationProject)) - testApplicationClassPath.setFrom(createMuzzleClassPath(instrumentationProject, name)) + bootstrapClassPath.setFrom(muzzleBootstrap) + toolingClassPath.setFrom(muzzleTooling) + instrumentationClassPath.setFrom(createAgentClassPath(project)) + testApplicationClassPath.setFrom(createMuzzleClassPath(project, name)) if (muzzleDirective != null) { assertPass.set(muzzleDirective.assertPass) this.muzzleDirective.set(muzzleDirective.name ?: muzzleDirective.module) From aa881574788bbba74f36730415a1268516ad8497 Mon Sep 17 00:00:00 2001 From: Brice Dutheil Date: Mon, 15 Sep 2025 22:11:21 +0200 Subject: [PATCH 04/15] refactor: Makes MuzzleTask Cacheable Note, this only caches the muzzle assertion, tasks are being still registered depending on what is brought back from maven. I.e. if a new dependency is discovered a new task will be registered and as such will be executed. --- .../gradle/plugin/muzzle/MuzzleAction.kt | 7 ++++ .../gradle/plugin/muzzle/MuzzleDirective.kt | 13 ++++--- .../gradle/plugin/muzzle/MuzzleExtension.kt | 7 ++-- .../gradle/plugin/muzzle/MuzzlePlugin.kt | 12 +----- .../plugin/muzzle/MuzzleWorkParameters.kt | 2 + .../gradle/plugin/muzzle/tasks/MuzzleTask.kt | 37 +++++++++++++++++-- 6 files changed, 54 insertions(+), 24 deletions(-) diff --git a/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/MuzzleAction.kt b/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/MuzzleAction.kt index 90c6fd2e274..d9d1793ca55 100644 --- a/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/MuzzleAction.kt +++ b/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/MuzzleAction.kt @@ -1,5 +1,6 @@ package datadog.gradle.plugin.muzzle +import org.gradle.api.GradleException import org.gradle.api.file.FileCollection import org.gradle.workers.WorkAction import java.lang.reflect.Method @@ -42,6 +43,12 @@ abstract class MuzzleAction : WorkAction { Boolean::class.java, String::class.java ) + try { assertionMethod.invoke(null, instCL, testCL, assertPass, muzzleDirective) + parameters.resultFile.get().asFile.writeText("PASSING") + } catch (e: Exception) { + parameters.resultFile.get().asFile.writeText(e.stackTraceToString()) + throw GradleException("Muzzle validation failed", e) + } } } diff --git a/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/MuzzleDirective.kt b/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/MuzzleDirective.kt index f0948bc4457..d82e706e13d 100644 --- a/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/MuzzleDirective.kt +++ b/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/MuzzleDirective.kt @@ -1,11 +1,12 @@ package datadog.gradle.plugin.muzzle import org.eclipse.aether.repository.RemoteRepository +import java.io.Serializable /** * A pass or fail directive for a single dependency. */ -open class MuzzleDirective { +open class MuzzleDirective : Serializable { /** * Name is optional and is used to further define the scope of a directive. The motivation for this is that this * plugin creates a config for each of the dependencies under test with name '...---'. @@ -20,7 +21,7 @@ open class MuzzleDirective { var versions: String? = null var skipVersions: MutableSet = HashSet() var additionalDependencies: MutableList = ArrayList() - internal var additionalRepositories: MutableList = ArrayList() + internal var additionalRepositories: MutableList> = ArrayList() internal var excludedDependencies: MutableList = ArrayList() var assertPass: Boolean = false var assertInverse: Boolean = false @@ -51,7 +52,7 @@ open class MuzzleDirective { * @param type the type of repository, defaults to "default" */ fun extraRepository(id: String, url: String, type: String = "default") { - additionalRepositories.add(RemoteRepository.Builder(id, type, url).build()) + additionalRepositories.add(Triple(id, type, url)) } /** @@ -69,13 +70,15 @@ open class MuzzleDirective { * @param defaults the default repositories * @return a list of the default repositories followed by any additional repositories */ - fun getRepositories(defaults: List): List { + internal fun getRepositories(defaults: List): List { return if (additionalRepositories.isEmpty()) { defaults } else { ArrayList(defaults.size + additionalRepositories.size).apply { addAll(defaults) - addAll(additionalRepositories) + addAll(additionalRepositories.map { (id, type, url) -> + RemoteRepository.Builder(id, type, url).build() + }) } } } diff --git a/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/MuzzleExtension.kt b/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/MuzzleExtension.kt index 7c51e1bc144..43ed5c4950a 100644 --- a/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/MuzzleExtension.kt +++ b/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/MuzzleExtension.kt @@ -1,6 +1,5 @@ package datadog.gradle.plugin.muzzle -import org.eclipse.aether.repository.RemoteRepository import org.gradle.api.Action import org.gradle.api.model.ObjectFactory import javax.inject.Inject @@ -9,9 +8,9 @@ import java.util.Locale /** * Muzzle extension containing all pass and fail directives. */ -abstract class MuzzleExtension @Inject constructor(protected val objectFactory: ObjectFactory) { +abstract class MuzzleExtension @Inject constructor(private val objectFactory: ObjectFactory) { val directives: MutableList = ArrayList() - private val additionalRepositories: MutableList = ArrayList() + private val additionalRepositories: MutableList> = ArrayList() fun pass(action: Action) { val pass = objectFactory.newInstance(MuzzleDirective::class.java) @@ -39,7 +38,7 @@ abstract class MuzzleExtension @Inject constructor(protected val objectFactory: */ @JvmOverloads fun extraRepository(id: String, url: String, type: String = "default") { - additionalRepositories.add(RemoteRepository.Builder(id, type, url).build()) + additionalRepositories.add(Triple(id, type, url)) } private fun postConstruct(directive: MuzzleDirective) { diff --git a/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/MuzzlePlugin.kt b/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/MuzzlePlugin.kt index f468ac228ca..5262408935f 100644 --- a/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/MuzzlePlugin.kt +++ b/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/MuzzlePlugin.kt @@ -82,13 +82,6 @@ class MuzzlePlugin : Plugin { val muzzleTask = project.tasks.register("muzzle") { this.muzzleBootstrap.set(muzzleBootstrap) this.muzzleTooling.set(muzzleTooling) - // description = "Run instrumentation muzzle on compile time dependencies" - // doLast { - // if (!project.extensions.getByType().directives.any { it.assertPass }) { - // project.logger.info("No muzzle pass directives configured. Asserting pass against instrumentation compile-time dependencies") - // assertMuzzle(muzzleBootstrap, muzzleTooling, project) - // } - // } dependsOn(compileMuzzle) } @@ -123,7 +116,7 @@ class MuzzlePlugin : Plugin { var runAfter: TaskProvider = muzzleTask project.extensions.getByType().directives.forEach { directive -> - project.logger.debug("configuring $directive") + project.logger.debug("configuring {}", directive) if (directive.isCoreJdk) { runAfter = addMuzzleTask(directive, null, project, runAfter, muzzleBootstrap, muzzleTooling) @@ -242,9 +235,6 @@ class MuzzlePlugin : Plugin { this.muzzleDirective.set(muzzleDirective) this.muzzleBootstrap.set(muzzleBootstrap) this.muzzleTooling.set(muzzleTooling) - // doLast { - // assertMuzzle(muzzleBootstrap, muzzleTooling, instrumentationProject, muzzleDirective) - // } } runAfterTask.configure { diff --git a/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/MuzzleWorkParameters.kt b/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/MuzzleWorkParameters.kt index d9ae2e0bf68..5af13d9a10d 100644 --- a/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/MuzzleWorkParameters.kt +++ b/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/MuzzleWorkParameters.kt @@ -1,6 +1,7 @@ package datadog.gradle.plugin.muzzle import org.gradle.api.file.ConfigurableFileCollection +import org.gradle.api.file.RegularFileProperty import org.gradle.api.provider.Property import org.gradle.workers.WorkParameters @@ -12,5 +13,6 @@ interface MuzzleWorkParameters : WorkParameters { val testApplicationClassPath: ConfigurableFileCollection val assertPass: Property val muzzleDirective: Property + val resultFile: RegularFileProperty } diff --git a/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/tasks/MuzzleTask.kt b/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/tasks/MuzzleTask.kt index 47f5385a93e..4f6d7193f43 100644 --- a/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/tasks/MuzzleTask.kt +++ b/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/tasks/MuzzleTask.kt @@ -7,19 +7,30 @@ import datadog.gradle.plugin.muzzle.allMainSourceSet import org.gradle.api.Project import org.gradle.api.artifacts.Configuration import org.gradle.api.file.FileCollection +import org.gradle.api.file.RegularFileProperty import org.gradle.api.invocation.BuildInvocationDetails +import org.gradle.api.model.ObjectFactory import org.gradle.api.provider.Property +import org.gradle.api.provider.ProviderFactory +import org.gradle.api.tasks.CacheableTask +import org.gradle.api.tasks.Classpath import org.gradle.api.tasks.Input import org.gradle.api.tasks.InputFiles import org.gradle.api.tasks.Optional +import org.gradle.api.tasks.OutputFile import org.gradle.api.tasks.TaskAction import org.gradle.jvm.toolchain.JavaLanguageVersion import org.gradle.jvm.toolchain.JavaToolchainService import org.gradle.kotlin.dsl.getByType +import org.gradle.kotlin.dsl.property import org.gradle.workers.WorkerExecutor import javax.inject.Inject -abstract class MuzzleTask : AbstractMuzzleTask() { +@CacheableTask +abstract class MuzzleTask @Inject constructor( + objects: ObjectFactory, + providers: ProviderFactory, +) : AbstractMuzzleTask() { override fun getDescription(): String { return if (muzzleDirective.isPresent) { "Run instrumentation muzzle on ${muzzleDirective.get().name} dependency" @@ -38,14 +49,31 @@ abstract class MuzzleTask : AbstractMuzzleTask() { abstract val workerExecutor: WorkerExecutor @get:InputFiles + @get:Classpath abstract val muzzleBootstrap: Property @get:InputFiles + @get:Classpath abstract val muzzleTooling: Property + @get:InputFiles + @get:Classpath + protected val agentClassPath = providers.provider { createAgentClassPath(project) } + + @get:InputFiles + @get:Classpath + protected val muzzleClassPath = providers.provider { createMuzzleClassPath(project, name) } + @get:Input @get:Optional - abstract val muzzleDirective : Property + val muzzleDirective: Property = objects.property() + + // This output is only used to make the task cacheable, this is not exposed + @get:OutputFile + @get:Optional + protected val result: RegularFileProperty = objects.fileProperty().convention( + project.layout.buildDirectory.file("reports/${name}.txt") + ) @TaskAction fun muzzle() { @@ -77,14 +105,15 @@ abstract class MuzzleTask : AbstractMuzzleTask() { buildStartedTime.set(invocationDetails.buildStartedTime) bootstrapClassPath.setFrom(muzzleBootstrap) toolingClassPath.setFrom(muzzleTooling) - instrumentationClassPath.setFrom(createAgentClassPath(project)) - testApplicationClassPath.setFrom(createMuzzleClassPath(project, name)) + instrumentationClassPath.setFrom(agentClassPath.get()) + testApplicationClassPath.setFrom(muzzleClassPath.get()) if (muzzleDirective != null) { assertPass.set(muzzleDirective.assertPass) this.muzzleDirective.set(muzzleDirective.name ?: muzzleDirective.module) } else { assertPass.set(true) } + resultFile.set(result) } } From 8e027395466f4a64f51b24699db377c78db14361 Mon Sep 17 00:00:00 2001 From: Brice Dutheil Date: Tue, 16 Sep 2025 11:03:41 +0200 Subject: [PATCH 05/15] refactor: Makes muzzle printReferences Cacheable --- .../gradle/plugin/muzzle/MuzzlePlugin.kt | 11 +++- .../muzzle/tasks/MuzzleGetReferencesTask.kt | 50 +++++++++++++++++++ .../muzzle/tasks/MuzzlePrintReferencesTask.kt | 24 --------- .../muzzle/MuzzleVersionScanPlugin.java | 10 ++-- 4 files changed, 66 insertions(+), 29 deletions(-) create mode 100644 buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/tasks/MuzzleGetReferencesTask.kt delete mode 100644 buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/tasks/MuzzlePrintReferencesTask.kt diff --git a/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/MuzzlePlugin.kt b/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/MuzzlePlugin.kt index 5262408935f..b791f1f9a45 100644 --- a/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/MuzzlePlugin.kt +++ b/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/MuzzlePlugin.kt @@ -6,7 +6,7 @@ import datadog.gradle.plugin.muzzle.MuzzleMavenRepoUtils.resolveVersionRange import datadog.gradle.plugin.muzzle.tasks.MuzzleEndTask import datadog.gradle.plugin.muzzle.tasks.MuzzleGenerateReportTask import datadog.gradle.plugin.muzzle.tasks.MuzzleMergeReportsTask -import datadog.gradle.plugin.muzzle.tasks.MuzzlePrintReferencesTask +import datadog.gradle.plugin.muzzle.tasks.MuzzleGetReferencesTask import datadog.gradle.plugin.muzzle.tasks.MuzzleTask import org.eclipse.aether.artifact.Artifact import org.gradle.api.NamedDomainObjectProvider @@ -85,8 +85,15 @@ class MuzzlePlugin : Plugin { dependsOn(compileMuzzle) } - project.tasks.register("printReferences") { + project.tasks.register("printReferences") { dependsOn(compileMuzzle) + }.also { + val printReferencesTask = project.tasks.register("actuallyPrintReferences") { + doLast { + println(it.get().outputFile.get().asFile.readText()) + } + } + it.configure { finalizedBy(printReferencesTask) } } project.tasks.register("generateMuzzleReport") { diff --git a/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/tasks/MuzzleGetReferencesTask.kt b/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/tasks/MuzzleGetReferencesTask.kt new file mode 100644 index 00000000000..ca5cda83a7d --- /dev/null +++ b/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/tasks/MuzzleGetReferencesTask.kt @@ -0,0 +1,50 @@ +package datadog.gradle.plugin.muzzle.tasks + +import datadog.gradle.plugin.muzzle.mainSourceSet +import org.gradle.api.model.ObjectFactory +import org.gradle.api.provider.ProviderFactory +import org.gradle.api.tasks.CacheableTask +import org.gradle.api.tasks.Classpath +import org.gradle.api.tasks.InputFiles +import org.gradle.api.tasks.OutputFile +import org.gradle.api.tasks.TaskAction +import java.io.PrintWriter +import java.io.StringWriter +import java.lang.reflect.Method +import java.net.URLClassLoader +import javax.inject.Inject + +@CacheableTask +abstract class MuzzleGetReferencesTask @Inject constructor( + providers: ProviderFactory, + objects: ObjectFactory, +) : AbstractMuzzleTask() { + init { + description = "Print references created by instrumentation muzzle" + } + + @get:InputFiles + @get:Classpath + val classpath = providers.provider { project.mainSourceSet.runtimeClasspath } + + // This output is only used to make the task cacheable, this is not exposed + @get:OutputFile + val outputFile = objects.fileProperty().convention( + project.layout.buildDirectory.file("reports/references.txt") + ) + + @TaskAction + fun printMuzzle() { + val cl = URLClassLoader(classpath.get().map { it.toURI().toURL() }.toTypedArray(), null) + val printMethod: Method = cl.loadClass("datadog.trace.agent.tooling.muzzle.MuzzleVersionScanPlugin") + .getMethod( + "printMuzzleReferences", + ClassLoader::class.java, + PrintWriter::class.java, + ) + val stringWriter = StringWriter() + printMethod.invoke(null, cl, PrintWriter(stringWriter)) + + outputFile.get().asFile.writeText(stringWriter.toString()) + } +} diff --git a/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/tasks/MuzzlePrintReferencesTask.kt b/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/tasks/MuzzlePrintReferencesTask.kt deleted file mode 100644 index 0a80c168b11..00000000000 --- a/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/tasks/MuzzlePrintReferencesTask.kt +++ /dev/null @@ -1,24 +0,0 @@ -package datadog.gradle.plugin.muzzle.tasks - -import datadog.gradle.plugin.muzzle.mainSourceSet -import org.gradle.api.tasks.TaskAction -import java.lang.reflect.Method -import java.net.URLClassLoader - -abstract class MuzzlePrintReferencesTask : AbstractMuzzleTask() { - init { - description = "Print references created by instrumentation muzzle" - } - - @TaskAction - fun printMuzzle() { - val cp = project.mainSourceSet.runtimeClasspath - val cl = URLClassLoader(cp.map { it.toURI().toURL() }.toTypedArray(), null) - val printMethod: Method = cl.loadClass("datadog.trace.agent.tooling.muzzle.MuzzleVersionScanPlugin") - .getMethod( - "printMuzzleReferences", - ClassLoader::class.java - ) - printMethod.invoke(null, cl) - } -} diff --git a/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/muzzle/MuzzleVersionScanPlugin.java b/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/muzzle/MuzzleVersionScanPlugin.java index 65e99aa8e49..93300e082c5 100644 --- a/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/muzzle/MuzzleVersionScanPlugin.java +++ b/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/muzzle/MuzzleVersionScanPlugin.java @@ -8,6 +8,7 @@ import datadog.trace.agent.tooling.bytebuddy.matcher.HierarchyMatchers; import de.thetaphi.forbiddenapis.SuppressForbidden; import java.io.IOException; +import java.io.PrintWriter; import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; @@ -142,13 +143,16 @@ private static Map createHelperMap(final InstrumenterModule modu } @SuppressForbidden - public static void printMuzzleReferences(final ClassLoader instrumentationLoader) { + public static void printMuzzleReferences( + final ClassLoader instrumentationLoader, + final PrintWriter out + ) { for (InstrumenterModule module : ServiceLoader.load(InstrumenterModule.class, instrumentationLoader)) { final ReferenceMatcher muzzle = module.getInstrumentationMuzzle(); - System.out.println(module.getClass().getName()); + out.println(module.getClass().getName()); for (final Reference ref : muzzle.getReferences()) { - System.out.println(prettyPrint(" ", ref)); + out.println(prettyPrint(" ", ref)); } } } From f0d55c8e953b4a176b479d38c45a9002e40349fe Mon Sep 17 00:00:00 2001 From: Brice Dutheil Date: Tue, 16 Sep 2025 12:02:03 +0200 Subject: [PATCH 06/15] style: make google-java-format happy --- .../trace/agent/tooling/muzzle/MuzzleVersionScanPlugin.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/muzzle/MuzzleVersionScanPlugin.java b/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/muzzle/MuzzleVersionScanPlugin.java index 93300e082c5..2d32e652c52 100644 --- a/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/muzzle/MuzzleVersionScanPlugin.java +++ b/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/muzzle/MuzzleVersionScanPlugin.java @@ -144,9 +144,7 @@ private static Map createHelperMap(final InstrumenterModule modu @SuppressForbidden public static void printMuzzleReferences( - final ClassLoader instrumentationLoader, - final PrintWriter out - ) { + final ClassLoader instrumentationLoader, final PrintWriter out) { for (InstrumenterModule module : ServiceLoader.load(InstrumenterModule.class, instrumentationLoader)) { final ReferenceMatcher muzzle = module.getInstrumentationMuzzle(); From 3d87f06d2a97601f1ca05e9fb743155c164ee740 Mon Sep 17 00:00:00 2001 From: Brice Dutheil Date: Thu, 18 Sep 2025 16:59:57 +0200 Subject: [PATCH 07/15] chore: PR reviews --- .../datadog/gradle/plugin/muzzle/MuzzlePlugin.kt | 2 +- .../datadog/gradle/plugin/muzzle/MuzzlePluginUtils.kt | 3 +++ .../plugin/muzzle/tasks/AbstractMuzzleReportTask.kt | 7 ++++--- .../gradle/plugin/muzzle/tasks/MuzzleEndTask.kt | 11 +++++------ 4 files changed, 13 insertions(+), 10 deletions(-) diff --git a/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/MuzzlePlugin.kt b/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/MuzzlePlugin.kt index b791f1f9a45..e593be6b9c4 100644 --- a/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/MuzzlePlugin.kt +++ b/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/MuzzlePlugin.kt @@ -90,7 +90,7 @@ class MuzzlePlugin : Plugin { }.also { val printReferencesTask = project.tasks.register("actuallyPrintReferences") { doLast { - println(it.get().outputFile.get().asFile.readText()) + project.logger.quiet(it.get().outputFile.get().asFile.readText()) } } it.configure { finalizedBy(printReferencesTask) } diff --git a/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/MuzzlePluginUtils.kt b/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/MuzzlePluginUtils.kt index 3e9cb0b3ab6..60e790e79bd 100644 --- a/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/MuzzlePluginUtils.kt +++ b/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/MuzzlePluginUtils.kt @@ -17,3 +17,6 @@ internal val Project.allMainSourceSet: List get() = extensions.findByType() ?.filter { it.name.startsWith(MAIN_SOURCE_SET_NAME) } .orEmpty() + +internal val Project.pathSlug: String + get() = path.removePrefix(":").replace(':', '_') \ No newline at end of file diff --git a/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/tasks/AbstractMuzzleReportTask.kt b/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/tasks/AbstractMuzzleReportTask.kt index f86d5636e6c..91f16ee89c6 100644 --- a/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/tasks/AbstractMuzzleReportTask.kt +++ b/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/tasks/AbstractMuzzleReportTask.kt @@ -1,13 +1,14 @@ package datadog.gradle.plugin.muzzle.tasks +import datadog.gradle.plugin.muzzle.pathSlug import datadog.gradle.plugin.muzzle.TestedArtifact import java.util.SortedMap abstract class AbstractMuzzleReportTask : AbstractMuzzleTask() { internal fun dumpVersionsToCsv(versions: SortedMap) { - val filename = project.path.replaceFirst("^:".toRegex(), "").replace(":", "_") - - val versionsFile = project.rootProject.layout.buildDirectory.file("${MUZZLE_DEPS_RESULTS}/$filename.csv") + val filename = "${project.pathSlug}.csv" + val resultsDir = project.rootProject.layout.buildDirectory + val versionsFile = resultsDir.file("${MUZZLE_DEPS_RESULTS}/$filename") with(project.file(versionsFile)) { parentFile.mkdirs() writeText("instrumentation,jarGroupId,jarArtifactId,lowestVersion,highestVersion\n") diff --git a/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/tasks/MuzzleEndTask.kt b/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/tasks/MuzzleEndTask.kt index 13f5f664567..edd36cf843d 100644 --- a/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/tasks/MuzzleEndTask.kt +++ b/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/tasks/MuzzleEndTask.kt @@ -1,5 +1,6 @@ package datadog.gradle.plugin.muzzle.tasks +import datadog.gradle.plugin.muzzle.pathSlug import org.gradle.api.provider.Property import org.gradle.api.tasks.Input import org.gradle.api.tasks.TaskAction @@ -12,17 +13,15 @@ abstract class MuzzleEndTask : AbstractMuzzleTask() { fun generatesResultFile() { val endTimeMs = System.currentTimeMillis() val seconds = (endTimeMs - startTimeMs.get()).toDouble() / 1000.0 - val name = "${project.path}:muzzle" - val dirname = name.replaceFirst("^:".toRegex(), "").replace(":", "_") - val dir = project.rootProject.layout.buildDirectory.dir("${MUZZLE_TEST_RESULTS}/$dirname/results.xml") - with(project.file(dir)) { + val dirname = "${project.pathSlug}_muzzle" + val resultsFile = project.rootProject.layout.buildDirectory.dir("${MUZZLE_TEST_RESULTS}/$dirname/results.xml") + with(project.file(resultsFile)) { parentFile.mkdirs() writeText( """ - - + """.trimIndent() ) From 43f36d839f6d6548ddb2bf9a1a2a91e450e06b4f Mon Sep 17 00:00:00 2001 From: Brice Dutheil Date: Tue, 23 Sep 2025 16:58:34 +0200 Subject: [PATCH 08/15] chore: Declare reports as inout / output --- .../muzzle/tasks/AbstractMuzzleReportTask.kt | 17 ++++++++++++----- .../muzzle/tasks/MuzzleGenerateReportTask.kt | 9 ++++++--- 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/tasks/AbstractMuzzleReportTask.kt b/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/tasks/AbstractMuzzleReportTask.kt index 91f16ee89c6..8f0e26fbfff 100644 --- a/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/tasks/AbstractMuzzleReportTask.kt +++ b/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/tasks/AbstractMuzzleReportTask.kt @@ -1,14 +1,21 @@ package datadog.gradle.plugin.muzzle.tasks -import datadog.gradle.plugin.muzzle.pathSlug import datadog.gradle.plugin.muzzle.TestedArtifact -import java.util.SortedMap +import datadog.gradle.plugin.muzzle.pathSlug +import org.gradle.api.file.RegularFile +import org.gradle.api.provider.Property +import org.gradle.api.provider.Provider +import org.gradle.api.tasks.OutputFile +import java.util.* abstract class AbstractMuzzleReportTask : AbstractMuzzleTask() { + @get:OutputFile + val versionsFile: Provider = project.rootProject + .layout + .buildDirectory + .file("$MUZZLE_DEPS_RESULTS/${project.pathSlug}.csv") + internal fun dumpVersionsToCsv(versions: SortedMap) { - val filename = "${project.pathSlug}.csv" - val resultsDir = project.rootProject.layout.buildDirectory - val versionsFile = resultsDir.file("${MUZZLE_DEPS_RESULTS}/$filename") with(project.file(versionsFile)) { parentFile.mkdirs() writeText("instrumentation,jarGroupId,jarArtifactId,lowestVersion,highestVersion\n") diff --git a/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/tasks/MuzzleGenerateReportTask.kt b/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/tasks/MuzzleGenerateReportTask.kt index b209622b24d..f87653632ca 100644 --- a/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/tasks/MuzzleGenerateReportTask.kt +++ b/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/tasks/MuzzleGenerateReportTask.kt @@ -3,6 +3,7 @@ package datadog.gradle.plugin.muzzle.tasks import datadog.gradle.plugin.muzzle.MuzzleMavenRepoUtils import datadog.gradle.plugin.muzzle.TestedArtifact import org.eclipse.aether.util.version.GenericVersionScheme +import org.gradle.api.tasks.InputFiles import org.gradle.api.tasks.TaskAction import java.util.TreeMap @@ -11,14 +12,16 @@ abstract class MuzzleGenerateReportTask : AbstractMuzzleReportTask() { description = "Print instrumentation version report" } + @InputFiles + val versionReports = project.fileTree(project.rootProject.layout.buildDirectory.dir(MUZZLE_DEPS_RESULTS)) { + include("*.csv") + } + /** * Merges all muzzle report CSVs in the build directory into a single map and writes the merged results to a CSV. */ @TaskAction fun mergeReports() { - val versionReports = project.fileTree(project.rootProject.layout.buildDirectory.dir(MUZZLE_DEPS_RESULTS)) { - include("*.csv") - } val map = TreeMap() val versionScheme = GenericVersionScheme() versionReports.forEach { From 0ef3a352e1a8786e2990296fd4f5c4a83088df65 Mon Sep 17 00:00:00 2001 From: Brice Dutheil Date: Tue, 23 Sep 2025 17:17:46 +0200 Subject: [PATCH 09/15] chore: Use BuildEventsListenerRegistry to print task output even when cached --- .../gradle/plugin/muzzle/MuzzlePlugin.kt | 7 ----- .../gradle/plugin/muzzle/MuzzlePluginUtils.kt | 7 ++++- .../muzzle/tasks/MuzzleGetReferencesTask.kt | 27 +++++++++++++++++++ 3 files changed, 33 insertions(+), 8 deletions(-) diff --git a/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/MuzzlePlugin.kt b/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/MuzzlePlugin.kt index e593be6b9c4..c661d109771 100644 --- a/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/MuzzlePlugin.kt +++ b/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/MuzzlePlugin.kt @@ -87,13 +87,6 @@ class MuzzlePlugin : Plugin { project.tasks.register("printReferences") { dependsOn(compileMuzzle) - }.also { - val printReferencesTask = project.tasks.register("actuallyPrintReferences") { - doLast { - project.logger.quiet(it.get().outputFile.get().asFile.readText()) - } - } - it.configure { finalizedBy(printReferencesTask) } } project.tasks.register("generateMuzzleReport") { diff --git a/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/MuzzlePluginUtils.kt b/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/MuzzlePluginUtils.kt index 60e790e79bd..80051244788 100644 --- a/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/MuzzlePluginUtils.kt +++ b/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/MuzzlePluginUtils.kt @@ -5,8 +5,13 @@ import org.gradle.api.file.FileCollection import org.gradle.api.tasks.SourceSet import org.gradle.api.tasks.SourceSet.MAIN_SOURCE_SET_NAME import org.gradle.api.tasks.SourceSetContainer +import org.gradle.build.event.BuildEventsListenerRegistry import org.gradle.kotlin.dsl.findByType import org.gradle.kotlin.dsl.getByType +import org.gradle.tooling.events.FinishEvent +import org.gradle.tooling.events.OperationCompletionListener +import org.gradle.tooling.events.task.TaskFinishEvent +import org.gradle.tooling.events.task.TaskSuccessResult internal val Project.mainSourceSet: SourceSet get() = extensions.findByType() @@ -19,4 +24,4 @@ internal val Project.allMainSourceSet: List .orEmpty() internal val Project.pathSlug: String - get() = path.removePrefix(":").replace(':', '_') \ No newline at end of file + get() = path.removePrefix(":").replace(':', '_') diff --git a/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/tasks/MuzzleGetReferencesTask.kt b/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/tasks/MuzzleGetReferencesTask.kt index ca5cda83a7d..1f27066edd3 100644 --- a/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/tasks/MuzzleGetReferencesTask.kt +++ b/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/tasks/MuzzleGetReferencesTask.kt @@ -8,6 +8,11 @@ import org.gradle.api.tasks.Classpath import org.gradle.api.tasks.InputFiles import org.gradle.api.tasks.OutputFile import org.gradle.api.tasks.TaskAction +import org.gradle.build.event.BuildEventsListenerRegistry +import org.gradle.tooling.events.FinishEvent +import org.gradle.tooling.events.OperationCompletionListener +import org.gradle.tooling.events.task.TaskFinishEvent +import org.gradle.tooling.events.task.TaskSuccessResult import java.io.PrintWriter import java.io.StringWriter import java.lang.reflect.Method @@ -19,8 +24,16 @@ abstract class MuzzleGetReferencesTask @Inject constructor( providers: ProviderFactory, objects: ObjectFactory, ) : AbstractMuzzleTask() { + + @get:Inject + abstract val buildEventsListenerRegistry: BuildEventsListenerRegistry + init { description = "Print references created by instrumentation muzzle" + outputs.upToDateWhen { true } + buildEventsListenerRegistry.doOnSuccess(providers) { + project.logger.quiet(outputFile.get().asFile.readText()) + } } @get:InputFiles @@ -47,4 +60,18 @@ abstract class MuzzleGetReferencesTask @Inject constructor( outputFile.get().asFile.writeText(stringWriter.toString()) } + + private fun BuildEventsListenerRegistry.doOnSuccess(providers: ProviderFactory, block: () -> Unit) { + onTaskCompletion( + providers.provider { + object : OperationCompletionListener { + override fun onFinish(event: FinishEvent) { + if ((event is TaskFinishEvent) && (event.descriptor.taskPath == path) && (event.result is TaskSuccessResult)) { + block() + } + } + } + } + ) + } } From 024e0098611f7a277aaffc6be796be56118009fd Mon Sep 17 00:00:00 2001 From: Brice Dutheil Date: Tue, 23 Sep 2025 17:34:49 +0200 Subject: [PATCH 10/15] chore: Extract end task output file --- .../datadog/gradle/plugin/muzzle/tasks/MuzzleEndTask.kt | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/tasks/MuzzleEndTask.kt b/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/tasks/MuzzleEndTask.kt index edd36cf843d..daf0ce44b06 100644 --- a/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/tasks/MuzzleEndTask.kt +++ b/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/tasks/MuzzleEndTask.kt @@ -3,18 +3,23 @@ package datadog.gradle.plugin.muzzle.tasks import datadog.gradle.plugin.muzzle.pathSlug import org.gradle.api.provider.Property import org.gradle.api.tasks.Input +import org.gradle.api.tasks.OutputFile import org.gradle.api.tasks.TaskAction abstract class MuzzleEndTask : AbstractMuzzleTask() { @get:Input abstract val startTimeMs: Property + @get:OutputFile + val resultsFile = project.rootProject + .layout + .buildDirectory + .file("${MUZZLE_TEST_RESULTS}/${project.pathSlug}_muzzle/results.xml") + @TaskAction fun generatesResultFile() { val endTimeMs = System.currentTimeMillis() val seconds = (endTimeMs - startTimeMs.get()).toDouble() / 1000.0 - val dirname = "${project.pathSlug}_muzzle" - val resultsFile = project.rootProject.layout.buildDirectory.dir("${MUZZLE_TEST_RESULTS}/$dirname/results.xml") with(project.file(resultsFile)) { parentFile.mkdirs() writeText( From 586eb412504e661573eb173e2d9b71005c7680d7 Mon Sep 17 00:00:00 2001 From: Brice Dutheil Date: Tue, 23 Sep 2025 18:22:14 +0200 Subject: [PATCH 11/15] chore: Use kotlin dsl extension function for newInstance --- .../kotlin/datadog/gradle/plugin/muzzle/MuzzleExtension.kt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/MuzzleExtension.kt b/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/MuzzleExtension.kt index 43ed5c4950a..2bb88e8d69d 100644 --- a/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/MuzzleExtension.kt +++ b/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/MuzzleExtension.kt @@ -2,6 +2,7 @@ package datadog.gradle.plugin.muzzle import org.gradle.api.Action import org.gradle.api.model.ObjectFactory +import org.gradle.kotlin.dsl.newInstance import javax.inject.Inject import java.util.Locale @@ -13,7 +14,7 @@ abstract class MuzzleExtension @Inject constructor(private val objectFactory: Ob private val additionalRepositories: MutableList> = ArrayList() fun pass(action: Action) { - val pass = objectFactory.newInstance(MuzzleDirective::class.java) + val pass = objectFactory.newInstance() action.execute(pass) postConstruct(pass) pass.assertPass = true @@ -21,7 +22,7 @@ abstract class MuzzleExtension @Inject constructor(private val objectFactory: Ob } fun fail(action: Action) { - val fail = objectFactory.newInstance(MuzzleDirective::class.java) + val fail = objectFactory.newInstance() action.execute(fail) postConstruct(fail) fail.assertPass = false From 890c4692ebd720471a611143eb1eae039c2132c0 Mon Sep 17 00:00:00 2001 From: Brice Dutheil Date: Tue, 23 Sep 2025 21:12:32 +0200 Subject: [PATCH 12/15] chore: Use same single instance for the provider --- .../muzzle/tasks/MuzzleGetReferencesTask.kt | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/tasks/MuzzleGetReferencesTask.kt b/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/tasks/MuzzleGetReferencesTask.kt index 1f27066edd3..6832d1737e1 100644 --- a/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/tasks/MuzzleGetReferencesTask.kt +++ b/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/tasks/MuzzleGetReferencesTask.kt @@ -31,6 +31,7 @@ abstract class MuzzleGetReferencesTask @Inject constructor( init { description = "Print references created by instrumentation muzzle" outputs.upToDateWhen { true } + buildEventsListenerRegistry.doOnSuccess(providers) { project.logger.quiet(outputFile.get().asFile.readText()) } @@ -62,16 +63,15 @@ abstract class MuzzleGetReferencesTask @Inject constructor( } private fun BuildEventsListenerRegistry.doOnSuccess(providers: ProviderFactory, block: () -> Unit) { - onTaskCompletion( - providers.provider { - object : OperationCompletionListener { - override fun onFinish(event: FinishEvent) { - if ((event is TaskFinishEvent) && (event.descriptor.taskPath == path) && (event.result is TaskSuccessResult)) { - block() - } - } + val onTaskFinished = object : OperationCompletionListener { + override fun onFinish(event: FinishEvent) { + if ((event is TaskFinishEvent) && (event.descriptor.taskPath == path) && (event.result is TaskSuccessResult)) { + block() } } + } + onTaskCompletion( + providers.provider { onTaskFinished } ) } } From af4902e9bde9289e44eb4d15e93d4150919e4101 Mon Sep 17 00:00:00 2001 From: Brice Dutheil Date: Tue, 23 Sep 2025 22:00:39 +0200 Subject: [PATCH 13/15] chore: Revert the BuildEventsListenerRegistry approach --- .../gradle/plugin/muzzle/MuzzlePlugin.kt | 7 +++++++ .../muzzle/tasks/AbstractMuzzleReportTask.kt | 2 +- .../muzzle/tasks/MuzzleGetReferencesTask.kt | 17 ----------------- 3 files changed, 8 insertions(+), 18 deletions(-) diff --git a/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/MuzzlePlugin.kt b/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/MuzzlePlugin.kt index c661d109771..b791f1f9a45 100644 --- a/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/MuzzlePlugin.kt +++ b/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/MuzzlePlugin.kt @@ -87,6 +87,13 @@ class MuzzlePlugin : Plugin { project.tasks.register("printReferences") { dependsOn(compileMuzzle) + }.also { + val printReferencesTask = project.tasks.register("actuallyPrintReferences") { + doLast { + println(it.get().outputFile.get().asFile.readText()) + } + } + it.configure { finalizedBy(printReferencesTask) } } project.tasks.register("generateMuzzleReport") { diff --git a/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/tasks/AbstractMuzzleReportTask.kt b/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/tasks/AbstractMuzzleReportTask.kt index 8f0e26fbfff..c697e1c083d 100644 --- a/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/tasks/AbstractMuzzleReportTask.kt +++ b/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/tasks/AbstractMuzzleReportTask.kt @@ -6,7 +6,7 @@ import org.gradle.api.file.RegularFile import org.gradle.api.provider.Property import org.gradle.api.provider.Provider import org.gradle.api.tasks.OutputFile -import java.util.* +import java.util.SortedMap abstract class AbstractMuzzleReportTask : AbstractMuzzleTask() { @get:OutputFile diff --git a/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/tasks/MuzzleGetReferencesTask.kt b/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/tasks/MuzzleGetReferencesTask.kt index 6832d1737e1..bc79797558e 100644 --- a/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/tasks/MuzzleGetReferencesTask.kt +++ b/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/tasks/MuzzleGetReferencesTask.kt @@ -31,10 +31,6 @@ abstract class MuzzleGetReferencesTask @Inject constructor( init { description = "Print references created by instrumentation muzzle" outputs.upToDateWhen { true } - - buildEventsListenerRegistry.doOnSuccess(providers) { - project.logger.quiet(outputFile.get().asFile.readText()) - } } @get:InputFiles @@ -61,17 +57,4 @@ abstract class MuzzleGetReferencesTask @Inject constructor( outputFile.get().asFile.writeText(stringWriter.toString()) } - - private fun BuildEventsListenerRegistry.doOnSuccess(providers: ProviderFactory, block: () -> Unit) { - val onTaskFinished = object : OperationCompletionListener { - override fun onFinish(event: FinishEvent) { - if ((event is TaskFinishEvent) && (event.descriptor.taskPath == path) && (event.result is TaskSuccessResult)) { - block() - } - } - } - onTaskCompletion( - providers.provider { onTaskFinished } - ) - } } From f349cc3e23c04946bda7dbee4285c6c528ae19aa Mon Sep 17 00:00:00 2001 From: Brice Dutheil Date: Tue, 23 Sep 2025 23:15:14 +0200 Subject: [PATCH 14/15] chore: Revert the declaration of versionReports as input files --- .../gradle/plugin/muzzle/tasks/MuzzleGenerateReportTask.kt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/tasks/MuzzleGenerateReportTask.kt b/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/tasks/MuzzleGenerateReportTask.kt index f87653632ca..dce408ef247 100644 --- a/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/tasks/MuzzleGenerateReportTask.kt +++ b/buildSrc/src/main/kotlin/datadog/gradle/plugin/muzzle/tasks/MuzzleGenerateReportTask.kt @@ -12,8 +12,7 @@ abstract class MuzzleGenerateReportTask : AbstractMuzzleReportTask() { description = "Print instrumentation version report" } - @InputFiles - val versionReports = project.fileTree(project.rootProject.layout.buildDirectory.dir(MUZZLE_DEPS_RESULTS)) { + private val versionReports = project.fileTree(project.rootProject.layout.buildDirectory.dir(MUZZLE_DEPS_RESULTS)) { include("*.csv") } From 72344a0080f6dd70041aa0e4baf69deb7852cb8c Mon Sep 17 00:00:00 2001 From: Brice Dutheil Date: Wed, 24 Sep 2025 15:54:32 +0200 Subject: [PATCH 15/15] chore: touch