From 72991c0f4b57c08a2e2d10679d03029a2c47d493 Mon Sep 17 00:00:00 2001 From: Brice Dutheil Date: Mon, 11 May 2026 18:25:42 +0200 Subject: [PATCH 1/4] build: Refactor `version.gradle` to `dd-trace-java.version-file` plugin * `Project.exec {}` is removed in Gradle 9. It is also incompatible with the configuration cache. * `gradle/version.gradle` is a Groovy script plugin, migrating to a convention plugin is the way to go. --- buildSrc/build.gradle.kts | 5 + .../plugin/version/TracerVersionPlugin.kt | 4 +- .../gradle/plugin/version/WriteVersionFile.kt | 46 +++ .../plugin/version/WriteVersionFilePlugin.kt | 19 + .../version/TracerVersionIntegrationTest.kt | 339 ++++-------------- .../plugin/version/VersionPluginsFixture.kt | 70 ++++ .../version/WriteVersionFilePluginTest.kt | 92 +++++ dd-java-agent/agent-aiguard/build.gradle | 2 +- .../agent-ci-visibility/build.gradle | 2 +- .../build.gradle | 5 +- .../civisibility-test-fixtures/build.gradle | 5 +- dd-java-agent/agent-debugger/build.gradle | 3 +- .../debugger-bootstrap/build.gradle | 6 +- .../agent-debugger/debugger-el/build.gradle | 6 +- dd-java-agent/agent-iast/build.gradle | 2 +- .../iast-test-fixtures/build.gradle | 5 +- dd-java-agent/agent-llmobs/build.gradle | 2 +- dd-java-agent/agent-logs-intake/build.gradle | 2 +- .../appsec/appsec-test-fixtures/build.gradle | 5 +- dd-java-agent/appsec/build.gradle | 2 +- dd-java-agent/cws-tls/build.gradle | 3 +- dd-trace-core/build.gradle | 2 +- gradle/publish.gradle | 2 +- gradle/version.gradle | 34 -- .../feature-flagging-agent/build.gradle.kts | 2 +- .../build.gradle.kts | 2 +- .../feature-flagging-lib/build.gradle.kts | 2 +- utils/version-utils/build.gradle.kts | 3 +- 28 files changed, 345 insertions(+), 327 deletions(-) create mode 100644 buildSrc/src/main/kotlin/datadog/gradle/plugin/version/WriteVersionFile.kt create mode 100644 buildSrc/src/main/kotlin/datadog/gradle/plugin/version/WriteVersionFilePlugin.kt create mode 100644 buildSrc/src/test/kotlin/datadog/gradle/plugin/version/VersionPluginsFixture.kt create mode 100644 buildSrc/src/test/kotlin/datadog/gradle/plugin/version/WriteVersionFilePluginTest.kt delete mode 100644 gradle/version.gradle diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index 8083b423297..b1be2144929 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -39,6 +39,11 @@ gradlePlugin { implementationClass = "datadog.gradle.plugin.version.TracerVersionPlugin" } + create("version-file-plugin") { + id = "dd-trace-java.version-file" + implementationClass = "datadog.gradle.plugin.version.WriteVersionFilePlugin" + } + create("dump-hanged-test-plugin") { id = "dd-trace-java.dump-hanged-test" implementationClass = "datadog.gradle.plugin.dump.DumpHangedTestPlugin" diff --git a/buildSrc/src/main/kotlin/datadog/gradle/plugin/version/TracerVersionPlugin.kt b/buildSrc/src/main/kotlin/datadog/gradle/plugin/version/TracerVersionPlugin.kt index 1250e96d907..5255cbf5328 100644 --- a/buildSrc/src/main/kotlin/datadog/gradle/plugin/version/TracerVersionPlugin.kt +++ b/buildSrc/src/main/kotlin/datadog/gradle/plugin/version/TracerVersionPlugin.kt @@ -32,9 +32,9 @@ class TracerVersionPlugin @Inject constructor( providerFactory.gradleProperty("tracerVersion.qualifier") ) - val versionProvider = versionProvider(targetProject, extension) + val theVersion = versionProvider(targetProject, extension) targetProject.allprojects { - version = versionProvider + version = theVersion } } diff --git a/buildSrc/src/main/kotlin/datadog/gradle/plugin/version/WriteVersionFile.kt b/buildSrc/src/main/kotlin/datadog/gradle/plugin/version/WriteVersionFile.kt new file mode 100644 index 00000000000..b581ba7dd14 --- /dev/null +++ b/buildSrc/src/main/kotlin/datadog/gradle/plugin/version/WriteVersionFile.kt @@ -0,0 +1,46 @@ +package datadog.gradle.plugin.version + +import org.gradle.api.DefaultTask +import org.gradle.api.file.DirectoryProperty +import org.gradle.api.file.ProjectLayout +import org.gradle.api.model.ObjectFactory +import org.gradle.api.provider.Property +import org.gradle.api.provider.ProviderFactory +import org.gradle.api.tasks.Input +import org.gradle.api.tasks.OutputDirectory +import org.gradle.api.tasks.TaskAction +import org.gradle.kotlin.dsl.property +import javax.inject.Inject + +abstract class WriteVersionFile @Inject constructor( + providerFactory: ProviderFactory, + layout: ProjectLayout, + objects: ObjectFactory, +) : DefaultTask() { + + @get:Input + val version: Property = objects.property() + .convention(providerFactory.provider { project.version.toString() }) + + @get:Input + val gitHash: Property = objects.property() + .convention( + providerFactory.of(GitCommandValueSource::class.java) { + parameters { + gitCommand.addAll("git", "rev-parse", "--short", "HEAD") + workingDirectory.set(layout.projectDirectory) + } + } + ) + + @get:OutputDirectory + val outputDirectory: DirectoryProperty = objects.directoryProperty() + .convention(layout.buildDirectory.dir("generated/version")) + + @TaskAction + fun writeVersionFile() { + val versionFile = outputDirectory.file("${project.name}.version").get().asFile + versionFile.parentFile.mkdirs() + versionFile.writeText("${version.get()}~${gitHash.get()}") + } +} diff --git a/buildSrc/src/main/kotlin/datadog/gradle/plugin/version/WriteVersionFilePlugin.kt b/buildSrc/src/main/kotlin/datadog/gradle/plugin/version/WriteVersionFilePlugin.kt new file mode 100644 index 00000000000..84b7b9a3ade --- /dev/null +++ b/buildSrc/src/main/kotlin/datadog/gradle/plugin/version/WriteVersionFilePlugin.kt @@ -0,0 +1,19 @@ +package datadog.gradle.plugin.version + +import org.gradle.api.Plugin +import org.gradle.api.Project +import org.gradle.api.plugins.JavaPluginExtension +import org.gradle.kotlin.dsl.register +import org.gradle.kotlin.dsl.the + +class WriteVersionFilePlugin : Plugin { + override fun apply(target: Project) { + target.pluginManager.apply("java") + + val writeVersionFile = target.tasks.register("writeVersionNumberFile") + + target.the().sourceSets.named("main") { + resources.srcDir(writeVersionFile) + } + } +} diff --git a/buildSrc/src/test/kotlin/datadog/gradle/plugin/version/TracerVersionIntegrationTest.kt b/buildSrc/src/test/kotlin/datadog/gradle/plugin/version/TracerVersionIntegrationTest.kt index ac65bdf0910..ecba619e4af 100644 --- a/buildSrc/src/test/kotlin/datadog/gradle/plugin/version/TracerVersionIntegrationTest.kt +++ b/buildSrc/src/test/kotlin/datadog/gradle/plugin/version/TracerVersionIntegrationTest.kt @@ -1,319 +1,126 @@ package datadog.gradle.plugin.version -import org.gradle.testkit.runner.GradleRunner -import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Test import org.junit.jupiter.api.io.TempDir import java.io.File -import java.io.IOException class TracerVersionIntegrationTest { @Test fun `should use default version when not under a git clone`(@TempDir projectDir: File) { - assertTracerVersion(projectDir, "0.1.0-SNAPSHOT") + val fixture = VersionPluginsFixture(projectDir) + fixture.assertTracerVersion("0.1.0-SNAPSHOT") } @Test fun `should use default version when no git tags`(@TempDir projectDir: File) { - assertTracerVersion( - projectDir, - "0.1.0-SNAPSHOT", - beforeGradle = { - exec(projectDir, "git", "init", "--initial-branch", "main") - exec(projectDir, "git", "config", "user.email", "test@datadoghq.com") - exec(projectDir, "git", "config", "user.name", "Test") - exec(projectDir, "git", "add", "-A") - exec(projectDir, "git", "commit", "-m", "A commit") - } - ) + val fixture = VersionPluginsFixture(projectDir) + fixture.assertTracerVersion("0.1.0-SNAPSHOT") { + fixture.initGitRepo() + } } @Test fun `should ignore dirtiness when no git tags`(@TempDir projectDir: File) { - assertTracerVersion( - projectDir, - "0.1.0-SNAPSHOT", - beforeGradle = { - exec(projectDir, "git", "init", "--initial-branch", "main") - exec(projectDir, "git", "config", "user.email", "test@datadoghq.com") - exec(projectDir, "git", "config", "user.name", "Test") - exec(projectDir, "git", "add", "-A") - exec(projectDir, "git", "commit", "-m", "A commit") - - File(projectDir, "settings.gradle.kts").appendText( - """ - - // uncommitted change this file, - """.trimIndent() - ) - } - ) + val fixture = VersionPluginsFixture(projectDir) + fixture.assertTracerVersion("0.1.0-SNAPSHOT") { + fixture.initGitRepo() + File(projectDir, "settings.gradle.kts").appendText("\n// uncommitted change this file, ") + } } @Test fun `should use default version when unmatching git tags`(@TempDir projectDir: File) { - assertTracerVersion( - projectDir, - "0.1.0-SNAPSHOT", - beforeGradle = { - exec(projectDir, "git", "init", "--initial-branch", "main") - exec(projectDir, "git", "config", "user.email", "test@datadoghq.com") - exec(projectDir, "git", "config", "user.name", "Test") - exec(projectDir, "git", "add", "-A") - exec(projectDir, "git", "commit", "-m", "A commit") - exec(projectDir, "git", "tag", "something1.40.1", "-m", "Not our tag") - } - ) + val fixture = VersionPluginsFixture(projectDir) + fixture.assertTracerVersion("0.1.0-SNAPSHOT") { + fixture.initGitRepo() + fixture.exec("git", "tag", "something1.40.1", "-m", "Not our tag") + } } @Test fun `should use exact version when on tag`(@TempDir projectDir: File) { - assertTracerVersion( - projectDir, - "1.52.0", - beforeGradle = { - exec(projectDir, "git", "init", "--initial-branch", "main") - exec(projectDir, "git", "config", "user.email", "test@datadoghq.com") - exec(projectDir, "git", "config", "user.name", "Test") - exec(projectDir, "git", "add", "-A") - exec(projectDir, "git", "commit", "-m", "A commit") - exec(projectDir, "git", "tag", "v1.52.0", "-m", "") - } - ) + val fixture = VersionPluginsFixture(projectDir) + fixture.assertTracerVersion("1.52.0") { + fixture.initGitRepo() + fixture.exec("git", "tag", "v1.52.0", "-m", "") + } } @Test fun `should increment minor and mark dirtiness`(@TempDir projectDir: File) { - assertTracerVersion( - projectDir, - "1.53.0-SNAPSHOT-DIRTY", - beforeGradle = { - println("Setting up git repository in $projectDir") - File(projectDir, "gradle.properties").writeText( - """ - tracerVersion.dirtiness=true - """.trimIndent() - ) - - exec(projectDir, "git", "init", "--initial-branch", "main") - exec(projectDir, "git", "config", "user.email", "test@datadoghq.com") - exec(projectDir, "git", "config", "user.name", "Test") - exec(projectDir, "git", "add", "-A") - exec(projectDir, "git", "commit", "-m", "A commit") - exec(projectDir, "git", "tag", "v1.52.0", "-m", "") - - File(projectDir, "settings.gradle.kts").appendText( - """ - - // uncommitted change this file, - """.trimIndent() - ) - } - ) + val fixture = VersionPluginsFixture(projectDir) + fixture.assertTracerVersion("1.53.0-SNAPSHOT-DIRTY") { + File(projectDir, "gradle.properties").writeText("tracerVersion.dirtiness=true") + fixture.initGitRepo() + fixture.exec("git", "tag", "v1.52.0", "-m", "") + File(projectDir, "settings.gradle.kts").appendText("\n// uncommitted change this file, ") + } } @Test fun `should increment minor with added commits after version tag`(@TempDir projectDir: File) { - assertTracerVersion( - projectDir, - "1.53.0-SNAPSHOT", - beforeGradle = { - exec(projectDir, "git", "init", "--initial-branch", "main") - exec(projectDir, "git", "config", "user.email", "test@datadoghq.com") - exec(projectDir, "git", "config", "user.name", "Test") - exec(projectDir, "git", "add", "-A") - exec(projectDir, "git", "commit", "-m", "A commit") - exec(projectDir, "git", "tag", "v1.52.0", "-m", "") - - File(projectDir, "settings.gradle.kts").appendText( - """ - - // Committed change this file, - """.trimIndent() - ) - exec(projectDir, "git", "commit", "-am", "Another commit") - } - ) + val fixture = VersionPluginsFixture(projectDir) + fixture.assertTracerVersion("1.53.0-SNAPSHOT") { + fixture.initGitRepo() + fixture.exec("git", "tag", "v1.52.0", "-m", "") + File(projectDir, "settings.gradle.kts").appendText("\n// Committed change this file, ") + fixture.exec("git", "commit", "-am", "Another commit") + } } @Test fun `should increment minor with snapshot and dirtiness with added commits after version tag and dirty`(@TempDir projectDir: File) { - assertTracerVersion( - projectDir, - "1.53.0-SNAPSHOT-DIRTY", - beforeGradle = { - File(projectDir, "gradle.properties").writeText( - """ - tracerVersion.dirtiness=true - """.trimIndent() - ) - - exec(projectDir, "git", "init", "--initial-branch", "main") - exec(projectDir, "git", "config", "user.email", "test@datadoghq.com") - exec(projectDir, "git", "config", "user.name", "Test") - exec(projectDir, "git", "add", "-A") - exec(projectDir, "git", "commit", "-m", "A commit") - exec(projectDir, "git", "tag", "v1.52.0", "-m", "") - - val settingsFile = File(projectDir, "settings.gradle.kts") - settingsFile.appendText( - """ - - // uncommitted change - """.trimIndent() - ) - - exec(projectDir, "git", "commit", "-am", "Another commit") - - settingsFile.appendText( - """ - // An uncommitted modification - """.trimIndent() - ) - } - ) + val fixture = VersionPluginsFixture(projectDir) + fixture.assertTracerVersion("1.53.0-SNAPSHOT-DIRTY") { + File(projectDir, "gradle.properties").writeText("tracerVersion.dirtiness=true") + fixture.initGitRepo() + fixture.exec("git", "tag", "v1.52.0", "-m", "") + val settingsFile = File(projectDir, "settings.gradle.kts") + settingsFile.appendText("\n// uncommitted change ") + fixture.exec("git", "commit", "-am", "Another commit") + settingsFile.appendText("\n// An uncommitted modification") + } } @Test fun `should increment patch on release branch and no patch release tag`(@TempDir projectDir: File) { - assertTracerVersion( - projectDir, - "1.52.1-SNAPSHOT", - beforeGradle = { - exec(projectDir, "git", "init", "--initial-branch", "main") - exec(projectDir, "git", "config", "user.email", "test@datadoghq.com") - exec(projectDir, "git", "config", "user.name", "Test") - exec(projectDir, "git", "add", "-A") - exec(projectDir, "git", "commit", "-m", "A commit") - exec(projectDir, "git", "tag", "v1.52.0", "-m", "") - - val settingsFile = File(projectDir, "settings.gradle.kts") - settingsFile.appendText( - """ - - // Committed change - """.trimIndent() - ) - - exec(projectDir, "git", "commit", "-am", "Another commit") - exec(projectDir, "git", "switch", "-c", "release/v1.52.x") - } - ) + val fixture = VersionPluginsFixture(projectDir) + fixture.assertTracerVersion("1.52.1-SNAPSHOT") { + fixture.initGitRepo() + fixture.exec("git", "tag", "v1.52.0", "-m", "") + File(projectDir, "settings.gradle.kts").appendText("\n// Committed change ") + fixture.exec("git", "commit", "-am", "Another commit") + fixture.exec("git", "switch", "-c", "release/v1.52.x") + } } @Test fun `should increment patch on release branch and with previous patch release tag`(@TempDir projectDir: File) { - assertTracerVersion( - projectDir, - "1.52.2-SNAPSHOT", - beforeGradle = { - exec(projectDir, "git", "init", "--initial-branch", "main") - exec(projectDir, "git", "config", "user.email", "test@datadoghq.com") - exec(projectDir, "git", "config", "user.name", "Test") - exec(projectDir, "git", "add", "-A") - exec(projectDir, "git", "commit", "-m", "A commit") - exec(projectDir, "git", "tag", "v1.52.0", "-m", "") - exec(projectDir, "git", "switch", "-c", "release/v1.52.x") - - val settingsFile = File(projectDir, "settings.gradle.kts") - settingsFile.appendText( - """ - - // Committed change - """.trimIndent() - ) - exec(projectDir, "git", "commit", "-am", "Another commit") - exec(projectDir, "git", "tag", "v1.52.1", "-m", "") - - settingsFile.appendText( - """ - - // Another committed change - """.trimIndent() - ) - exec(projectDir, "git", "commit", "-am", "Another commit") - } - ) + val fixture = VersionPluginsFixture(projectDir) + fixture.assertTracerVersion("1.52.2-SNAPSHOT") { + fixture.initGitRepo() + fixture.exec("git", "tag", "v1.52.0", "-m", "") + fixture.exec("git", "switch", "-c", "release/v1.52.x") + val settingsFile = File(projectDir, "settings.gradle.kts") + settingsFile.appendText("\n// Committed change ") + fixture.exec("git", "commit", "-am", "Another commit") + fixture.exec("git", "tag", "v1.52.1", "-m", "") + settingsFile.appendText("\n// Another committed change ") + fixture.exec("git", "commit", "-am", "Another commit") + } } @Test fun `should compute version on worktrees`(@TempDir projectDir: File, @TempDir workTreeDir: File) { - assertTracerVersion( - projectDir, - "1.53.0-SNAPSHOT", - beforeGradle = { - exec(projectDir, "git", "init", "--initial-branch", "main") - exec(projectDir, "git", "config", "user.email", "test@datadoghq.com") - exec(projectDir, "git", "config", "user.name", "Test") - exec(projectDir, "git", "add", "-A") - exec(projectDir, "git", "commit", "-m", "A commit") - exec(projectDir, "git", "tag", "v1.52.0", "-m", "") - - exec(projectDir, "git", "commit", "-m", "Initial commit", "--allow-empty") - exec(projectDir, "git", "worktree", "add", workTreeDir.absolutePath) - // happening on the worktree - File(workTreeDir, "settings.gradle.kts").appendText( - """ - - // Committed change this file, - """.trimIndent() - ) - exec(workTreeDir, "git", "commit", "-am", "Another commit") - }, - workingDirectory = workTreeDir - ) - } - - private fun assertTracerVersion( - projectDir: File, - expectedVersion: String, - beforeGradle: () -> Unit = {}, - workingDirectory: File = projectDir, - ) { - File(projectDir, "settings.gradle.kts").writeText( - """ - rootProject.name = "test-project" - """.trimIndent() - ) - File(projectDir, "build.gradle.kts").writeText( - """ - plugins { - id("dd-trace-java.tracer-version") - } - - tasks.register("printVersion") { - logger.quiet(project.version.toString()) - } - - group = "datadog.tracer.version.test" - """.trimIndent() - ) - - beforeGradle() - - val buildResult = GradleRunner.create() - .forwardOutput() - // .withGradleVersion(gradleVersion) // Use current gradle version - .withPluginClasspath() - .withArguments("printVersion", "--quiet") - .withProjectDir(workingDirectory) - // .withDebug(true) - .build() - - assertEquals(expectedVersion, buildResult.output.lines().first()) - } - - private fun exec(workingDirectory: File, vararg args: String) { - val exitCode = ProcessBuilder() - .command(*args) - .directory(workingDirectory) - .inheritIO() - .start() - .waitFor() - - if (exitCode != 0) { - throw IOException(String.format("Process failed: %s Exit code %d", args.joinToString(" "), exitCode)) + val fixture = VersionPluginsFixture(projectDir) + fixture.assertTracerVersion("1.53.0-SNAPSHOT", workingDirectory = workTreeDir) { + fixture.initGitRepo() + fixture.exec("git", "tag", "v1.52.0", "-m", "") + fixture.exec("git", "commit", "-m", "Initial commit", "--allow-empty") + fixture.exec("git", "worktree", "add", workTreeDir.absolutePath) + File(workTreeDir, "settings.gradle.kts").appendText("\n// Committed change this file, ") + fixture.exec(workTreeDir, "git", "commit", "-am", "Another commit") } } } diff --git a/buildSrc/src/test/kotlin/datadog/gradle/plugin/version/VersionPluginsFixture.kt b/buildSrc/src/test/kotlin/datadog/gradle/plugin/version/VersionPluginsFixture.kt new file mode 100644 index 00000000000..866d3f2b39c --- /dev/null +++ b/buildSrc/src/test/kotlin/datadog/gradle/plugin/version/VersionPluginsFixture.kt @@ -0,0 +1,70 @@ +package datadog.gradle.plugin.version + +import datadog.gradle.plugin.GradleFixture +import org.gradle.testkit.runner.GradleRunner +import org.junit.jupiter.api.Assertions.assertEquals +import java.io.File +import java.io.IOException + +internal class VersionPluginsFixture(projectDir: File) : GradleFixture(projectDir) { + + fun exec(workingDirectory: File, vararg args: String) { + val exitCode = ProcessBuilder() + .command(*args) + .directory(workingDirectory) + .inheritIO() + .start() + .waitFor() + if (exitCode != 0) { + throw IOException("Process failed: ${args.joinToString(" ")} (exit code $exitCode)") + } + } + + fun exec(vararg args: String) = exec(projectDir, *args) + + fun initGitRepo(workingDirectory: File = projectDir) { + exec(workingDirectory, "git", "init", "--initial-branch", "main") + exec(workingDirectory, "git", "config", "user.email", "test@datadoghq.com") + exec(workingDirectory, "git", "config", "user.name", "Test") + exec(workingDirectory, "git", "add", "-A") + exec(workingDirectory, "git", "commit", "-m", "A commit") + } + + fun assertTracerVersion( + expectedVersion: String, + workingDirectory: File = projectDir, + beforeGradle: () -> Unit = {}, + ) { + file("settings.gradle.kts").writeText("""rootProject.name = "test-project"""") + file("build.gradle.kts").writeText( + """ + plugins { + id("dd-trace-java.tracer-version") + } + + tasks.register("printVersion") { + logger.quiet(project.version.toString()) + } + + group = "datadog.tracer.version.test" + """.trimIndent() + ) + + beforeGradle() + + val buildResult = if (workingDirectory == projectDir) { + run("printVersion", "--quiet") + } else { + // Worktree: Gradle must run from a directory other than projectDir, + // so use GradleRunner directly instead of GradleFixture.run(). + GradleRunner.create() + .forwardOutput() + .withPluginClasspath() + .withArguments("printVersion", "--quiet") + .withProjectDir(workingDirectory) + .build() + } + + assertEquals(expectedVersion, buildResult.output.lines().first()) + } +} diff --git a/buildSrc/src/test/kotlin/datadog/gradle/plugin/version/WriteVersionFilePluginTest.kt b/buildSrc/src/test/kotlin/datadog/gradle/plugin/version/WriteVersionFilePluginTest.kt new file mode 100644 index 00000000000..390a94a77e1 --- /dev/null +++ b/buildSrc/src/test/kotlin/datadog/gradle/plugin/version/WriteVersionFilePluginTest.kt @@ -0,0 +1,92 @@ +package datadog.gradle.plugin.version + +import org.assertj.core.api.Assertions.assertThat +import org.gradle.testkit.runner.TaskOutcome +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.io.TempDir +import java.io.File + +class WriteVersionFilePluginTest { + + @Test + fun `writes version file in version~hash format`(@TempDir projectDir: File) { + val fixture = VersionPluginsFixture(projectDir) + setupProject(projectDir) + fixture.initGitRepo() + + val result = fixture.run("writeVersionNumberFile") + + assertThat(result.task(":writeVersionNumberFile")?.outcome).isEqualTo(TaskOutcome.SUCCESS) + assertThat(File(projectDir, "build/generated/version/my-lib.version")) + .exists() + .content().matches("""1\.2\.3~[0-9a-f]+""") + } + + @Test + fun `version and gitHash properties can be overridden`(@TempDir projectDir: File) { + val fixture = VersionPluginsFixture(projectDir) + setupProject( + projectDir, + extraBuildScript = """ + tasks.named("writeVersionNumberFile").configure { + version.set("9.9.9") + gitHash.set("deadbeef") + } + """, + ) + + val result = fixture.run("writeVersionNumberFile") + + assertThat(result.task(":writeVersionNumberFile")?.outcome).isEqualTo(TaskOutcome.SUCCESS) + assertThat(File(projectDir, "build/generated/version/my-lib.version")) + .content().isEqualTo("9.9.9~deadbeef") + } + + @Test + fun `version file is wired into main source set resources`(@TempDir projectDir: File) { + val fixture = VersionPluginsFixture(projectDir) + setupProject( + projectDir, + extraBuildScript = """ + tasks.named("writeVersionNumberFile").configure { + gitHash.set("abc12345") + } + """, + ) + + fixture.run("processResources") + + assertThat(File(projectDir, "build/resources/main/my-lib.version")).exists() + } + + @Test + fun `task is up-to-date on second run`(@TempDir projectDir: File) { + val fixture = VersionPluginsFixture(projectDir) + setupProject( + projectDir, + extraBuildScript = """ + tasks.named("writeVersionNumberFile").configure { + gitHash.set("abc12345") + } + """, + ) + fixture.run("writeVersionNumberFile") + + val result = fixture.run("writeVersionNumberFile") + + assertThat(result.task(":writeVersionNumberFile")?.outcome).isEqualTo(TaskOutcome.UP_TO_DATE) + } + + private fun setupProject(projectDir: File, extraBuildScript: String = "") { + File(projectDir, "settings.gradle").writeText("rootProject.name = 'my-lib'") + File(projectDir, "build.gradle").writeText( + """ + plugins { + id 'dd-trace-java.version-file' + } + version = '1.2.3' + $extraBuildScript + """.trimIndent() + ) + } +} diff --git a/dd-java-agent/agent-aiguard/build.gradle b/dd-java-agent/agent-aiguard/build.gradle index 5e4841dbf3c..70aab194be4 100644 --- a/dd-java-agent/agent-aiguard/build.gradle +++ b/dd-java-agent/agent-aiguard/build.gradle @@ -2,10 +2,10 @@ import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar plugins { id 'com.gradleup.shadow' + id 'dd-trace-java.version-file' } apply from: "$rootDir/gradle/java.gradle" -apply from: "$rootDir/gradle/version.gradle" java { sourceCompatibility = JavaVersion.VERSION_1_8 diff --git a/dd-java-agent/agent-ci-visibility/build.gradle b/dd-java-agent/agent-ci-visibility/build.gradle index 323553b8c03..7dc7b558df3 100644 --- a/dd-java-agent/agent-ci-visibility/build.gradle +++ b/dd-java-agent/agent-ci-visibility/build.gradle @@ -5,10 +5,10 @@ import org.jetbrains.kotlin.gradle.dsl.KotlinVersion plugins { id 'com.gradleup.shadow' id 'org.jetbrains.kotlin.jvm' + id 'dd-trace-java.version-file' } apply from: "$rootDir/gradle/java.gradle" -apply from: "$rootDir/gradle/version.gradle" apply from: "$rootDir/gradle/test-with-kotlin.gradle" apply from: "$rootDir/gradle/test-with-scala.gradle" diff --git a/dd-java-agent/agent-ci-visibility/civisibility-instrumentation-test-fixtures/build.gradle b/dd-java-agent/agent-ci-visibility/civisibility-instrumentation-test-fixtures/build.gradle index 01f83345bfe..51b7b0ecfdc 100644 --- a/dd-java-agent/agent-ci-visibility/civisibility-instrumentation-test-fixtures/build.gradle +++ b/dd-java-agent/agent-ci-visibility/civisibility-instrumentation-test-fixtures/build.gradle @@ -1,5 +1,8 @@ +plugins { + id 'dd-trace-java.version-file' +} + apply from: "$rootDir/gradle/java.gradle" -apply from: "$rootDir/gradle/version.gradle" dependencies { api project(':dd-java-agent:instrumentation-testing') diff --git a/dd-java-agent/agent-ci-visibility/civisibility-test-fixtures/build.gradle b/dd-java-agent/agent-ci-visibility/civisibility-test-fixtures/build.gradle index 2e2d7a6c16a..641a93a44bc 100644 --- a/dd-java-agent/agent-ci-visibility/civisibility-test-fixtures/build.gradle +++ b/dd-java-agent/agent-ci-visibility/civisibility-test-fixtures/build.gradle @@ -1,5 +1,8 @@ +plugins { + id 'dd-trace-java.version-file' +} + apply from: "$rootDir/gradle/java.gradle" -apply from: "$rootDir/gradle/version.gradle" dependencies { api project(':dd-java-agent:agent-ci-visibility') diff --git a/dd-java-agent/agent-debugger/build.gradle b/dd-java-agent/agent-debugger/build.gradle index 3d26d031024..9eac038bfd8 100644 --- a/dd-java-agent/agent-debugger/build.gradle +++ b/dd-java-agent/agent-debugger/build.gradle @@ -2,11 +2,10 @@ import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar plugins { id 'com.gradleup.shadow' + id 'dd-trace-java.version-file' } apply from: "$rootDir/gradle/java.gradle" -// We do not publish separate jar, but having version file is useful -apply from: "$rootDir/gradle/version.gradle" minimumInstructionCoverage = 0.1 minimumBranchCoverage = 0.6 diff --git a/dd-java-agent/agent-debugger/debugger-bootstrap/build.gradle b/dd-java-agent/agent-debugger/debugger-bootstrap/build.gradle index 265b35de54c..3968a161e35 100644 --- a/dd-java-agent/agent-debugger/debugger-bootstrap/build.gradle +++ b/dd-java-agent/agent-debugger/debugger-bootstrap/build.gradle @@ -1,6 +1,8 @@ +plugins { + id 'dd-trace-java.version-file' +} + apply from: "$rootDir/gradle/java.gradle" -// We do not publish separate jar, but having version file is useful -apply from: "$rootDir/gradle/version.gradle" // Most of the classes are just object model // Those which needs test coverage, test classes are in agent-debugger project diff --git a/dd-java-agent/agent-debugger/debugger-el/build.gradle b/dd-java-agent/agent-debugger/debugger-el/build.gradle index ff9d5d44187..e1b92a20af9 100644 --- a/dd-java-agent/agent-debugger/debugger-el/build.gradle +++ b/dd-java-agent/agent-debugger/debugger-el/build.gradle @@ -1,6 +1,8 @@ +plugins { + id 'dd-trace-java.version-file' +} + apply from: "$rootDir/gradle/java.gradle" -// We do not publish separate jar, but having version file is useful -apply from: "$rootDir/gradle/version.gradle" minimumInstructionCoverage = 0.1 minimumBranchCoverage = 0.6 diff --git a/dd-java-agent/agent-iast/build.gradle b/dd-java-agent/agent-iast/build.gradle index 70eabe4b74d..55d0fbbe9e8 100644 --- a/dd-java-agent/agent-iast/build.gradle +++ b/dd-java-agent/agent-iast/build.gradle @@ -6,10 +6,10 @@ plugins { id 'me.champeau.jmh' id 'com.google.protobuf' version '0.10.0' id 'net.ltgt.errorprone' version '3.1.0' + id 'dd-trace-java.version-file' } apply from: "$rootDir/gradle/java.gradle" -apply from: "$rootDir/gradle/version.gradle" tasks.withType(AbstractCompile).configureEach { configureCompiler(it, 11, JavaVersion.VERSION_1_8, "Ensure no APIs beyond JDK8 are used") diff --git a/dd-java-agent/agent-iast/iast-test-fixtures/build.gradle b/dd-java-agent/agent-iast/iast-test-fixtures/build.gradle index 248d7a9e008..bf1a59d1b83 100644 --- a/dd-java-agent/agent-iast/iast-test-fixtures/build.gradle +++ b/dd-java-agent/agent-iast/iast-test-fixtures/build.gradle @@ -1,5 +1,8 @@ +plugins { + id 'dd-trace-java.version-file' +} + apply from: "$rootDir/gradle/java.gradle" -apply from: "$rootDir/gradle/version.gradle" dependencies { api project(':dd-java-agent:agent-iast') diff --git a/dd-java-agent/agent-llmobs/build.gradle b/dd-java-agent/agent-llmobs/build.gradle index faea293da33..55d3258fa0c 100644 --- a/dd-java-agent/agent-llmobs/build.gradle +++ b/dd-java-agent/agent-llmobs/build.gradle @@ -2,10 +2,10 @@ import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar plugins { id 'com.gradleup.shadow' + id 'dd-trace-java.version-file' } apply from: "$rootDir/gradle/java.gradle" -apply from: "$rootDir/gradle/version.gradle" minimumBranchCoverage = 0.0 minimumInstructionCoverage = 0.0 diff --git a/dd-java-agent/agent-logs-intake/build.gradle b/dd-java-agent/agent-logs-intake/build.gradle index 6d3fd48da68..20d4f3d3ee1 100644 --- a/dd-java-agent/agent-logs-intake/build.gradle +++ b/dd-java-agent/agent-logs-intake/build.gradle @@ -2,10 +2,10 @@ import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar plugins { id 'com.gradleup.shadow' + id 'dd-trace-java.version-file' } apply from: "$rootDir/gradle/java.gradle" -apply from: "$rootDir/gradle/version.gradle" excludedClassesCoverage += [ "datadog.trace.logging.intake.LogsWriterImpl", diff --git a/dd-java-agent/appsec/appsec-test-fixtures/build.gradle b/dd-java-agent/appsec/appsec-test-fixtures/build.gradle index a7f64623b36..f053f31b066 100644 --- a/dd-java-agent/appsec/appsec-test-fixtures/build.gradle +++ b/dd-java-agent/appsec/appsec-test-fixtures/build.gradle @@ -1,5 +1,8 @@ +plugins { + id 'dd-trace-java.version-file' +} + apply from: "$rootDir/gradle/java.gradle" -apply from: "$rootDir/gradle/version.gradle" dependencies { api project(':dd-java-agent:appsec') diff --git a/dd-java-agent/appsec/build.gradle b/dd-java-agent/appsec/build.gradle index 2d1fb0abffc..b98f2422897 100644 --- a/dd-java-agent/appsec/build.gradle +++ b/dd-java-agent/appsec/build.gradle @@ -5,10 +5,10 @@ import groovy.json.JsonSlurper plugins { id 'com.gradleup.shadow' id 'me.champeau.jmh' + id 'dd-trace-java.version-file' } apply from: "$rootDir/gradle/java.gradle" -apply from: "$rootDir/gradle/version.gradle" apply from: "$rootDir/gradle/tries.gradle" dependencies { diff --git a/dd-java-agent/cws-tls/build.gradle b/dd-java-agent/cws-tls/build.gradle index df9efdd2608..199340693e6 100644 --- a/dd-java-agent/cws-tls/build.gradle +++ b/dd-java-agent/cws-tls/build.gradle @@ -3,11 +3,10 @@ import org.apache.maven.model.License plugins { id 'com.gradleup.shadow' + id 'dd-trace-java.version-file' } apply from: "$rootDir/gradle/java.gradle" -// We do not publish a separate jar, but having a version file is useful for checking if cws is included -apply from: "$rootDir/gradle/version.gradle" excludedClassesCoverage += ['datadog.cws.erpc.*', 'datadog.cws.tls.*',] diff --git a/dd-trace-core/build.gradle b/dd-trace-core/build.gradle index 48544e2984f..47199dab774 100644 --- a/dd-trace-core/build.gradle +++ b/dd-trace-core/build.gradle @@ -1,11 +1,11 @@ plugins { id 'me.champeau.jmh' + id 'dd-trace-java.version-file' } description = 'dd-trace-core' apply from: "$rootDir/gradle/java.gradle" -apply from: "$rootDir/gradle/version.gradle" minimumBranchCoverage = 0.5 minimumInstructionCoverage = 0.6 diff --git a/gradle/publish.gradle b/gradle/publish.gradle index 699e130ed22..a5cf2126f48 100644 --- a/gradle/publish.gradle +++ b/gradle/publish.gradle @@ -1,5 +1,6 @@ apply plugin: 'maven-publish' apply plugin: 'signing' +apply plugin: 'dd-trace-java.version-file' /** * Proper publishing requires the following environment variables: @@ -9,7 +10,6 @@ apply plugin: 'signing' * GPG_PASSWORD */ -apply from: "$rootDir/gradle/version.gradle" apply from: "$rootDir/gradle/maven-pom.gradle" def isGitlabCI = providers.environmentVariable("GITLAB_CI").isPresent() diff --git a/gradle/version.gradle b/gradle/version.gradle deleted file mode 100644 index 977f0ae3716..00000000000 --- a/gradle/version.gradle +++ /dev/null @@ -1,34 +0,0 @@ -abstract class WriteVersionNumberFile extends DefaultTask { - @Input - abstract Property getVersion() - - @Input - abstract Property getGitHash() - - @OutputDirectory - abstract DirectoryProperty getOutputDirectory() - - WriteVersionNumberFile() { - // Set conventions (defaults) - this.version.convention(project.provider { project.version.toString() }) - this.gitHash.convention(project.provider { - def stdout = new ByteArrayOutputStream() - project.exec { - commandLine 'git', 'rev-parse', '--short', 'HEAD' - standardOutput = stdout - } - return stdout.toString().trim() - }) - this.outputDirectory.convention(project.layout.buildDirectory.dir("generated/version")) - } - - @TaskAction - void writeVersionFile() { - def versionFile = outputDirectory.file("${project.name}.version").get().asFile - versionFile.parentFile.mkdirs() - versionFile.text = "${version.get()}~${gitHash.get()}" - } -} - -def versionTask = tasks.register("writeVersionNumberFile", WriteVersionNumberFile) -sourceSets.main.resources.srcDir(versionTask) diff --git a/products/feature-flagging/feature-flagging-agent/build.gradle.kts b/products/feature-flagging/feature-flagging-agent/build.gradle.kts index bdf439bd9e4..902ae5a6023 100644 --- a/products/feature-flagging/feature-flagging-agent/build.gradle.kts +++ b/products/feature-flagging/feature-flagging-agent/build.gradle.kts @@ -4,10 +4,10 @@ import org.gradle.kotlin.dsl.project plugins { `java-library` id("com.gradleup.shadow") + id("dd-trace-java.version-file") } apply(from = "$rootDir/gradle/java.gradle") -apply(from = "$rootDir/gradle/version.gradle") description = "Feature flagging agent system" diff --git a/products/feature-flagging/feature-flagging-bootstrap/build.gradle.kts b/products/feature-flagging/feature-flagging-bootstrap/build.gradle.kts index d3edc149637..7d3266eb01f 100644 --- a/products/feature-flagging/feature-flagging-bootstrap/build.gradle.kts +++ b/products/feature-flagging/feature-flagging-bootstrap/build.gradle.kts @@ -1,9 +1,9 @@ plugins { `java-library` + id("dd-trace-java.version-file") } apply(from = "$rootDir/gradle/java.gradle") -apply(from = "$rootDir/gradle/version.gradle") description = "Feature flagging remote common module (bootstrap classloader)" diff --git a/products/feature-flagging/feature-flagging-lib/build.gradle.kts b/products/feature-flagging/feature-flagging-lib/build.gradle.kts index 4bb9a77a9a7..5381a9708ac 100644 --- a/products/feature-flagging/feature-flagging-lib/build.gradle.kts +++ b/products/feature-flagging/feature-flagging-lib/build.gradle.kts @@ -1,9 +1,9 @@ plugins { `java-library` + id("dd-trace-java.version-file") } apply(from = "$rootDir/gradle/java.gradle") -apply(from = "$rootDir/gradle/version.gradle") description = "Feature flagging remote config and exposure handling" diff --git a/utils/version-utils/build.gradle.kts b/utils/version-utils/build.gradle.kts index 6eb07efff46..ff6517cc687 100644 --- a/utils/version-utils/build.gradle.kts +++ b/utils/version-utils/build.gradle.kts @@ -1,10 +1,9 @@ plugins { `java-library` + id("dd-trace-java.version-file") } apply(from = "$rootDir/gradle/java.gradle") -// We do not publish separate jar, but having version file is useful -apply(from = "$rootDir/gradle/version.gradle") dependencies { implementation(libs.slf4j) From 814e6436ed0e99eb63542781809c63fcd3ebf24f Mon Sep 17 00:00:00 2001 From: Brice Dutheil Date: Tue, 12 May 2026 10:45:55 +0200 Subject: [PATCH 2/4] build: Add new plugin tests --- .../version/WriteVersionFilePluginTest.kt | 47 ++++++++++++++++++- 1 file changed, 46 insertions(+), 1 deletion(-) diff --git a/buildSrc/src/test/kotlin/datadog/gradle/plugin/version/WriteVersionFilePluginTest.kt b/buildSrc/src/test/kotlin/datadog/gradle/plugin/version/WriteVersionFilePluginTest.kt index 390a94a77e1..9b2e4e594b1 100644 --- a/buildSrc/src/test/kotlin/datadog/gradle/plugin/version/WriteVersionFilePluginTest.kt +++ b/buildSrc/src/test/kotlin/datadog/gradle/plugin/version/WriteVersionFilePluginTest.kt @@ -43,7 +43,28 @@ class WriteVersionFilePluginTest { } @Test - fun `version file is wired into main source set resources`(@TempDir projectDir: File) { + fun `task overwrites existing version file`(@TempDir projectDir: File) { + val fixture = VersionPluginsFixture(projectDir) + setupProject( + projectDir, + extraBuildScript = """ + tasks.named("writeVersionNumberFile").configure { + gitHash.set("abc12345") + } + """, + ) + val versionFile = versionFile(projectDir) + versionFile.parentFile.mkdirs() + versionFile.writeText("stale-version") + + val result = fixture.run("writeVersionNumberFile") + + assertThat(result.task(":writeVersionNumberFile")?.outcome).isEqualTo(TaskOutcome.SUCCESS) + assertThat(versionFile).content().isEqualTo("1.2.3~abc12345") + } + + @Test + fun `version file generation is wired into main resources`(@TempDir projectDir: File) { val fixture = VersionPluginsFixture(projectDir) setupProject( projectDir, @@ -77,6 +98,30 @@ class WriteVersionFilePluginTest { assertThat(result.task(":writeVersionNumberFile")?.outcome).isEqualTo(TaskOutcome.UP_TO_DATE) } + @Test + fun `clean deletes version file`(@TempDir projectDir: File) { + val fixture = VersionPluginsFixture(projectDir) + setupProject( + projectDir, + extraBuildScript = """ + tasks.named("writeVersionNumberFile").configure { + gitHash.set("abc12345") + } + """, + ) + val versionFile = versionFile(projectDir) + fixture.run("writeVersionNumberFile") + assertThat(versionFile).exists() + + val result = fixture.run("clean") + + assertThat(result.task(":clean")?.outcome).isEqualTo(TaskOutcome.SUCCESS) + assertThat(versionFile).doesNotExist() + } + + private fun versionFile(projectDir: File): File = + File(projectDir, "build/generated/version/my-lib.version") + private fun setupProject(projectDir: File, extraBuildScript: String = "") { File(projectDir, "settings.gradle").writeText("rootProject.name = 'my-lib'") File(projectDir, "build.gradle").writeText( From bfe9587ba7709f0484ab9a27bfe540dbbe6c0bef Mon Sep 17 00:00:00 2001 From: Brice Dutheil Date: Tue, 12 May 2026 14:09:03 +0200 Subject: [PATCH 3/4] build: Refactor the tests with a better fixture for version plugins --- .../datadog/gradle/plugin/GradleFixture.kt | 6 +- .../version/TracerVersionIntegrationTest.kt | 195 ++++++++++++------ .../plugin/version/VersionPluginsFixture.kt | 40 +--- .../version/WriteVersionFilePluginTest.kt | 166 ++++++++------- 4 files changed, 234 insertions(+), 173 deletions(-) diff --git a/buildSrc/src/test/kotlin/datadog/gradle/plugin/GradleFixture.kt b/buildSrc/src/test/kotlin/datadog/gradle/plugin/GradleFixture.kt index 5d6ca45b6fd..c0fd6077ded 100644 --- a/buildSrc/src/test/kotlin/datadog/gradle/plugin/GradleFixture.kt +++ b/buildSrc/src/test/kotlin/datadog/gradle/plugin/GradleFixture.kt @@ -151,8 +151,10 @@ internal open class GradleFixture(protected val projectDir: File) { /** * Creates or gets a file in the project directory, ensuring parent directories exist. */ - protected fun file(path: String): File = + protected fun file(path: String, mkdirs: Boolean = true): File = File(projectDir, path).also { file -> - file.parentFile?.mkdirs() + if (mkdirs) { + file.parentFile?.mkdirs() + } } } diff --git a/buildSrc/src/test/kotlin/datadog/gradle/plugin/version/TracerVersionIntegrationTest.kt b/buildSrc/src/test/kotlin/datadog/gradle/plugin/version/TracerVersionIntegrationTest.kt index ecba619e4af..4f253b41633 100644 --- a/buildSrc/src/test/kotlin/datadog/gradle/plugin/version/TracerVersionIntegrationTest.kt +++ b/buildSrc/src/test/kotlin/datadog/gradle/plugin/version/TracerVersionIntegrationTest.kt @@ -1,5 +1,7 @@ package datadog.gradle.plugin.version +import org.assertj.core.api.Assertions.assertThat +import org.gradle.testkit.runner.GradleRunner import org.junit.jupiter.api.Test import org.junit.jupiter.api.io.TempDir import java.io.File @@ -9,118 +11,187 @@ class TracerVersionIntegrationTest { @Test fun `should use default version when not under a git clone`(@TempDir projectDir: File) { val fixture = VersionPluginsFixture(projectDir) - fixture.assertTracerVersion("0.1.0-SNAPSHOT") + fixture.assertTracerVersion(expectedVersion = "0.1.0-SNAPSHOT") } @Test fun `should use default version when no git tags`(@TempDir projectDir: File) { val fixture = VersionPluginsFixture(projectDir) - fixture.assertTracerVersion("0.1.0-SNAPSHOT") { - fixture.initGitRepo() - } + fixture.assertTracerVersion( + expectedVersion = "0.1.0-SNAPSHOT", + beforeGradle = { + fixture.initGitRepo() + }, + ) } @Test fun `should ignore dirtiness when no git tags`(@TempDir projectDir: File) { val fixture = VersionPluginsFixture(projectDir) - fixture.assertTracerVersion("0.1.0-SNAPSHOT") { - fixture.initGitRepo() - File(projectDir, "settings.gradle.kts").appendText("\n// uncommitted change this file, ") - } + fixture.assertTracerVersion( + expectedVersion = "0.1.0-SNAPSHOT", + beforeGradle = { + fixture.initGitRepo() + settingsFile.appendText("\n// uncommitted change this file, ") + }, + ) } @Test fun `should use default version when unmatching git tags`(@TempDir projectDir: File) { val fixture = VersionPluginsFixture(projectDir) - fixture.assertTracerVersion("0.1.0-SNAPSHOT") { - fixture.initGitRepo() - fixture.exec("git", "tag", "something1.40.1", "-m", "Not our tag") - } + fixture.assertTracerVersion( + expectedVersion = "0.1.0-SNAPSHOT", + beforeGradle = { + fixture.initGitRepo() + fixture.exec("git", "tag", "something1.40.1", "-m", "Not our tag") + }, + ) } @Test fun `should use exact version when on tag`(@TempDir projectDir: File) { val fixture = VersionPluginsFixture(projectDir) - fixture.assertTracerVersion("1.52.0") { - fixture.initGitRepo() - fixture.exec("git", "tag", "v1.52.0", "-m", "") - } + fixture.assertTracerVersion( + expectedVersion = "1.52.0", + beforeGradle = { + fixture.initGitRepo() + fixture.exec("git", "tag", "v1.52.0", "-m", "") + }, + ) } @Test fun `should increment minor and mark dirtiness`(@TempDir projectDir: File) { val fixture = VersionPluginsFixture(projectDir) - fixture.assertTracerVersion("1.53.0-SNAPSHOT-DIRTY") { - File(projectDir, "gradle.properties").writeText("tracerVersion.dirtiness=true") - fixture.initGitRepo() - fixture.exec("git", "tag", "v1.52.0", "-m", "") - File(projectDir, "settings.gradle.kts").appendText("\n// uncommitted change this file, ") - } + fixture.assertTracerVersion( + expectedVersion = "1.53.0-SNAPSHOT-DIRTY", + beforeGradle = { + gradlePropertiesFile.writeText("tracerVersion.dirtiness=true") + fixture.initGitRepo() + fixture.exec("git", "tag", "v1.52.0", "-m", "") + settingsFile.appendText("\n// uncommitted change this file, ") + }, + ) } @Test fun `should increment minor with added commits after version tag`(@TempDir projectDir: File) { val fixture = VersionPluginsFixture(projectDir) - fixture.assertTracerVersion("1.53.0-SNAPSHOT") { - fixture.initGitRepo() - fixture.exec("git", "tag", "v1.52.0", "-m", "") - File(projectDir, "settings.gradle.kts").appendText("\n// Committed change this file, ") - fixture.exec("git", "commit", "-am", "Another commit") - } + fixture.assertTracerVersion( + expectedVersion = "1.53.0-SNAPSHOT", + beforeGradle = { + fixture.initGitRepo() + fixture.exec("git", "tag", "v1.52.0", "-m", "") + settingsFile.appendText("\n// Committed change this file, ") + fixture.exec("git", "commit", "-am", "Another commit") + }, + ) } @Test fun `should increment minor with snapshot and dirtiness with added commits after version tag and dirty`(@TempDir projectDir: File) { val fixture = VersionPluginsFixture(projectDir) - fixture.assertTracerVersion("1.53.0-SNAPSHOT-DIRTY") { - File(projectDir, "gradle.properties").writeText("tracerVersion.dirtiness=true") - fixture.initGitRepo() - fixture.exec("git", "tag", "v1.52.0", "-m", "") - val settingsFile = File(projectDir, "settings.gradle.kts") - settingsFile.appendText("\n// uncommitted change ") - fixture.exec("git", "commit", "-am", "Another commit") - settingsFile.appendText("\n// An uncommitted modification") - } + fixture.assertTracerVersion( + expectedVersion = "1.53.0-SNAPSHOT-DIRTY", + beforeGradle = { + gradlePropertiesFile.writeText("tracerVersion.dirtiness=true") + fixture.initGitRepo() + fixture.exec("git", "tag", "v1.52.0", "-m", "") + val settings = settingsFile + settings.appendText("\n// uncommitted change ") + fixture.exec("git", "commit", "-am", "Another commit") + settings.appendText("\n// An uncommitted modification") + }, + ) } @Test fun `should increment patch on release branch and no patch release tag`(@TempDir projectDir: File) { val fixture = VersionPluginsFixture(projectDir) - fixture.assertTracerVersion("1.52.1-SNAPSHOT") { - fixture.initGitRepo() - fixture.exec("git", "tag", "v1.52.0", "-m", "") - File(projectDir, "settings.gradle.kts").appendText("\n// Committed change ") - fixture.exec("git", "commit", "-am", "Another commit") - fixture.exec("git", "switch", "-c", "release/v1.52.x") - } + fixture.assertTracerVersion( + expectedVersion = "1.52.1-SNAPSHOT", + beforeGradle = { + fixture.initGitRepo() + fixture.exec("git", "tag", "v1.52.0", "-m", "") + settingsFile.appendText("\n// Committed change ") + fixture.exec("git", "commit", "-am", "Another commit") + fixture.exec("git", "switch", "-c", "release/v1.52.x") + }, + ) } @Test fun `should increment patch on release branch and with previous patch release tag`(@TempDir projectDir: File) { val fixture = VersionPluginsFixture(projectDir) - fixture.assertTracerVersion("1.52.2-SNAPSHOT") { - fixture.initGitRepo() - fixture.exec("git", "tag", "v1.52.0", "-m", "") - fixture.exec("git", "switch", "-c", "release/v1.52.x") - val settingsFile = File(projectDir, "settings.gradle.kts") - settingsFile.appendText("\n// Committed change ") - fixture.exec("git", "commit", "-am", "Another commit") - fixture.exec("git", "tag", "v1.52.1", "-m", "") - settingsFile.appendText("\n// Another committed change ") - fixture.exec("git", "commit", "-am", "Another commit") - } + fixture.assertTracerVersion( + expectedVersion = "1.52.2-SNAPSHOT", + beforeGradle = { + fixture.initGitRepo() + fixture.exec("git", "tag", "v1.52.0", "-m", "") + fixture.exec("git", "switch", "-c", "release/v1.52.x") + val settings = settingsFile + settings.appendText("\n// Committed change ") + fixture.exec("git", "commit", "-am", "Another commit") + fixture.exec("git", "tag", "v1.52.1", "-m", "") + settings.appendText("\n// Another committed change ") + fixture.exec("git", "commit", "-am", "Another commit") + }, + ) } @Test fun `should compute version on worktrees`(@TempDir projectDir: File, @TempDir workTreeDir: File) { val fixture = VersionPluginsFixture(projectDir) - fixture.assertTracerVersion("1.53.0-SNAPSHOT", workingDirectory = workTreeDir) { - fixture.initGitRepo() - fixture.exec("git", "tag", "v1.52.0", "-m", "") - fixture.exec("git", "commit", "-m", "Initial commit", "--allow-empty") - fixture.exec("git", "worktree", "add", workTreeDir.absolutePath) - File(workTreeDir, "settings.gradle.kts").appendText("\n// Committed change this file, ") - fixture.exec(workTreeDir, "git", "commit", "-am", "Another commit") + fixture.assertTracerVersion( + expectedVersion = "1.53.0-SNAPSHOT", + workingDirectory = workTreeDir, + beforeGradle = { + fixture.initGitRepo() + fixture.exec("git", "tag", "v1.52.0", "-m", "") + fixture.exec("git", "commit", "-m", "Initial commit", "--allow-empty") + fixture.exec("git", "worktree", "add", workTreeDir.absolutePath) + File(workTreeDir, "settings.gradle.kts").appendText("\n// Committed change this file, ") + fixture.exec(workTreeDir, "git", "commit", "-am", "Another commit") + }, + ) + } + + private fun VersionPluginsFixture.assertTracerVersion( + expectedVersion: String, + workingDirectory: File? = null, + beforeGradle: VersionPluginsFixture.() -> Unit = {}, + ) { + settingsFile.writeText("""rootProject.name = "test-project"""") + projectBuildFile.writeText( + """ + plugins { + id("dd-trace-java.tracer-version") + } + + tasks.register("printVersion") { + logger.quiet(project.version.toString()) + } + + group = "datadog.tracer.version.test" + """.trimIndent() + ) + + beforeGradle() + + val buildResult = if (workingDirectory == null) { + run("printVersion", "--quiet") + } else { + // Worktree: Gradle must run from a directory other than projectDir, + // so use GradleRunner directly instead of GradleFixture.run(). + GradleRunner.create() + .forwardOutput() + .withPluginClasspath() + .withArguments("printVersion", "--quiet") + .withProjectDir(workingDirectory) + .build() } + + assertThat(buildResult.output.lines().first()).isEqualTo(expectedVersion) } } diff --git a/buildSrc/src/test/kotlin/datadog/gradle/plugin/version/VersionPluginsFixture.kt b/buildSrc/src/test/kotlin/datadog/gradle/plugin/version/VersionPluginsFixture.kt index 866d3f2b39c..aba9e9fb35b 100644 --- a/buildSrc/src/test/kotlin/datadog/gradle/plugin/version/VersionPluginsFixture.kt +++ b/buildSrc/src/test/kotlin/datadog/gradle/plugin/version/VersionPluginsFixture.kt @@ -1,8 +1,6 @@ package datadog.gradle.plugin.version import datadog.gradle.plugin.GradleFixture -import org.gradle.testkit.runner.GradleRunner -import org.junit.jupiter.api.Assertions.assertEquals import java.io.File import java.io.IOException @@ -30,41 +28,13 @@ internal class VersionPluginsFixture(projectDir: File) : GradleFixture(projectDi exec(workingDirectory, "git", "commit", "-m", "A commit") } - fun assertTracerVersion( - expectedVersion: String, - workingDirectory: File = projectDir, - beforeGradle: () -> Unit = {}, - ) { - file("settings.gradle.kts").writeText("""rootProject.name = "test-project"""") - file("build.gradle.kts").writeText( - """ - plugins { - id("dd-trace-java.tracer-version") - } + val projectBuildFile = file("build.gradle.kts") - tasks.register("printVersion") { - logger.quiet(project.version.toString()) - } + val gradlePropertiesFile = file("gradle.properties") - group = "datadog.tracer.version.test" - """.trimIndent() - ) + val settingsFile = file("settings.gradle.kts") - beforeGradle() + val generatedVersionFile = file("build/generated/version/my-lib.version", false) - val buildResult = if (workingDirectory == projectDir) { - run("printVersion", "--quiet") - } else { - // Worktree: Gradle must run from a directory other than projectDir, - // so use GradleRunner directly instead of GradleFixture.run(). - GradleRunner.create() - .forwardOutput() - .withPluginClasspath() - .withArguments("printVersion", "--quiet") - .withProjectDir(workingDirectory) - .build() - } - - assertEquals(expectedVersion, buildResult.output.lines().first()) - } + val builtResourceVersionFile = file("build/resources/main/my-lib.version", false) } diff --git a/buildSrc/src/test/kotlin/datadog/gradle/plugin/version/WriteVersionFilePluginTest.kt b/buildSrc/src/test/kotlin/datadog/gradle/plugin/version/WriteVersionFilePluginTest.kt index 9b2e4e594b1..efd47380ad1 100644 --- a/buildSrc/src/test/kotlin/datadog/gradle/plugin/version/WriteVersionFilePluginTest.kt +++ b/buildSrc/src/test/kotlin/datadog/gradle/plugin/version/WriteVersionFilePluginTest.kt @@ -1,6 +1,7 @@ package datadog.gradle.plugin.version import org.assertj.core.api.Assertions.assertThat +import org.gradle.testkit.runner.BuildResult import org.gradle.testkit.runner.TaskOutcome import org.junit.jupiter.api.Test import org.junit.jupiter.api.io.TempDir @@ -11,87 +12,92 @@ class WriteVersionFilePluginTest { @Test fun `writes version file in version~hash format`(@TempDir projectDir: File) { val fixture = VersionPluginsFixture(projectDir) - setupProject(projectDir) - fixture.initGitRepo() - - val result = fixture.run("writeVersionNumberFile") - - assertThat(result.task(":writeVersionNumberFile")?.outcome).isEqualTo(TaskOutcome.SUCCESS) - assertThat(File(projectDir, "build/generated/version/my-lib.version")) - .exists() - .content().matches("""1\.2\.3~[0-9a-f]+""") + fixture.assertVersionFile( + expectedContentRegex = "1\\.2\\.3~[0-9a-f]+", + beforeGradle = { + initGitRepo() + }, + ) } @Test fun `version and gitHash properties can be overridden`(@TempDir projectDir: File) { val fixture = VersionPluginsFixture(projectDir) - setupProject( - projectDir, - extraBuildScript = """ - tasks.named("writeVersionNumberFile").configure { - version.set("9.9.9") - gitHash.set("deadbeef") - } - """, + fixture.assertVersionFile( + expectedContentRegex = "9.9.9~deadbeef", + beforeGradle = { + projectBuildFile.appendText( + """ + + tasks.named("writeVersionNumberFile").configure { + version.set("9.9.9") + gitHash.set("deadbeef") + } + """.trimIndent() + ) + }, ) - - val result = fixture.run("writeVersionNumberFile") - - assertThat(result.task(":writeVersionNumberFile")?.outcome).isEqualTo(TaskOutcome.SUCCESS) - assertThat(File(projectDir, "build/generated/version/my-lib.version")) - .content().isEqualTo("9.9.9~deadbeef") } @Test fun `task overwrites existing version file`(@TempDir projectDir: File) { val fixture = VersionPluginsFixture(projectDir) - setupProject( - projectDir, - extraBuildScript = """ - tasks.named("writeVersionNumberFile").configure { - gitHash.set("abc12345") + fixture.assertVersionFile( + expectedContentRegex = "1.2.3~abc12345", + beforeGradle = { + projectBuildFile.appendText( + """ + + tasks.named("writeVersionNumberFile").configure { + gitHash.set("abc12345") + } + """.trimIndent() + ) + generatedVersionFile.run { + parentFile.mkdirs() + writeText("stale-version") } - """, + }, ) - val versionFile = versionFile(projectDir) - versionFile.parentFile.mkdirs() - versionFile.writeText("stale-version") - - val result = fixture.run("writeVersionNumberFile") - - assertThat(result.task(":writeVersionNumberFile")?.outcome).isEqualTo(TaskOutcome.SUCCESS) - assertThat(versionFile).content().isEqualTo("1.2.3~abc12345") } @Test fun `version file generation is wired into main resources`(@TempDir projectDir: File) { val fixture = VersionPluginsFixture(projectDir) - setupProject( - projectDir, - extraBuildScript = """ - tasks.named("writeVersionNumberFile").configure { - gitHash.set("abc12345") - } - """, + fixture.assertVersionFile( + expectedContentRegex = "1.2.3~abc12345", + task = "processResources", + beforeGradle = { + projectBuildFile.appendText( + """ + + tasks.named("writeVersionNumberFile").configure { + gitHash.set("abc12345") + } + """.trimIndent() + ) + }, ) - fixture.run("processResources") - - assertThat(File(projectDir, "build/resources/main/my-lib.version")).exists() + assertThat(fixture.builtResourceVersionFile).exists() } @Test fun `task is up-to-date on second run`(@TempDir projectDir: File) { val fixture = VersionPluginsFixture(projectDir) - setupProject( - projectDir, - extraBuildScript = """ - tasks.named("writeVersionNumberFile").configure { - gitHash.set("abc12345") - } - """, + fixture.assertVersionFile( + expectedContentRegex = "1.2.3~abc12345", + beforeGradle = { + projectBuildFile.appendText( + """ + + tasks.named("writeVersionNumberFile").configure { + gitHash.set("abc12345") + } + """.trimIndent() + ) + }, ) - fixture.run("writeVersionNumberFile") val result = fixture.run("writeVersionNumberFile") @@ -101,17 +107,20 @@ class WriteVersionFilePluginTest { @Test fun `clean deletes version file`(@TempDir projectDir: File) { val fixture = VersionPluginsFixture(projectDir) - setupProject( - projectDir, - extraBuildScript = """ - tasks.named("writeVersionNumberFile").configure { - gitHash.set("abc12345") - } - """, + fixture.assertVersionFile( + expectedContentRegex = "1.2.3~abc12345", + beforeGradle = { + projectBuildFile.appendText( + """ + + tasks.named("writeVersionNumberFile").configure { + gitHash.set("abc12345") + } + """.trimIndent() + ) + }, ) - val versionFile = versionFile(projectDir) - fixture.run("writeVersionNumberFile") - assertThat(versionFile).exists() + val versionFile = fixture.generatedVersionFile val result = fixture.run("clean") @@ -119,19 +128,28 @@ class WriteVersionFilePluginTest { assertThat(versionFile).doesNotExist() } - private fun versionFile(projectDir: File): File = - File(projectDir, "build/generated/version/my-lib.version") - - private fun setupProject(projectDir: File, extraBuildScript: String = "") { - File(projectDir, "settings.gradle").writeText("rootProject.name = 'my-lib'") - File(projectDir, "build.gradle").writeText( + private fun VersionPluginsFixture.assertVersionFile( + expectedContentRegex: String, + task: String = ":writeVersionNumberFile", + beforeGradle: VersionPluginsFixture.() -> Unit = {}, + ): BuildResult { + settingsFile.writeText("""rootProject.name = "my-lib"""") + projectBuildFile.writeText( """ plugins { - id 'dd-trace-java.version-file' + id("dd-trace-java.version-file") } - version = '1.2.3' - $extraBuildScript + + version = "1.2.3" """.trimIndent() ) + beforeGradle() + + val buildResult = run(task) + + assertThat(buildResult.task(task)?.outcome).isEqualTo(TaskOutcome.SUCCESS) + assertThat(generatedVersionFile).exists().isFile() + assertThat(generatedVersionFile.readText()).matches(expectedContentRegex) + return buildResult } } From d368de46810c44e1d8cf35b2b75749366336d4f6 Mon Sep 17 00:00:00 2001 From: Brice Dutheil Date: Tue, 12 May 2026 15:04:52 +0200 Subject: [PATCH 4/4] fix: task need to be experessed as task path, in the build result --- .../gradle/plugin/version/WriteVersionFilePluginTest.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/buildSrc/src/test/kotlin/datadog/gradle/plugin/version/WriteVersionFilePluginTest.kt b/buildSrc/src/test/kotlin/datadog/gradle/plugin/version/WriteVersionFilePluginTest.kt index efd47380ad1..8aa49a86ae8 100644 --- a/buildSrc/src/test/kotlin/datadog/gradle/plugin/version/WriteVersionFilePluginTest.kt +++ b/buildSrc/src/test/kotlin/datadog/gradle/plugin/version/WriteVersionFilePluginTest.kt @@ -146,8 +146,9 @@ class WriteVersionFilePluginTest { beforeGradle() val buildResult = run(task) + val taskPath = if (task.startsWith(":")) task else ":$task" - assertThat(buildResult.task(task)?.outcome).isEqualTo(TaskOutcome.SUCCESS) + assertThat(buildResult.task(taskPath)?.outcome).isEqualTo(TaskOutcome.SUCCESS) assertThat(generatedVersionFile).exists().isFile() assertThat(generatedVersionFile.readText()).matches(expectedContentRegex) return buildResult