Skip to content

Build smoke-test apps via Gradle Tooling API for Gradle 9 readiness#11404

Closed
bric3 wants to merge 15 commits into
masterfrom
bdu/smoke-test-tooling-api-build
Closed

Build smoke-test apps via Gradle Tooling API for Gradle 9 readiness#11404
bric3 wants to merge 15 commits into
masterfrom
bdu/smoke-test-tooling-api-build

Conversation

@bric3
Copy link
Copy Markdown
Contributor

@bric3 bric3 commented May 18, 2026

For easier review see

New Smoke test Plugin

Smoke tests fixes

What Does This Do

Introduces a new build-logic/ included build hosting the dd-trace-java.smoke-test-app plugin, which builds smoke-test applications via the Gradle Tooling API in a nested daemon with a pinned Gradle version and Java toolchain — without committing per-application gradlew wrappers.

Fourteen smoke-test modules that pin Spring Boot 2.x are converted to this new plugin so the root build can move to Gradle 9 (the Spring Boot Gradle plugin <3.5.0 calls Configuration.getUploadTaskName(), which is removed in Gradle 9).

Module SB version Notes
apm-tracing-disabled 2.7.18 forwards dd-trace-api jar
kafka-2 2.7.15 forwards iast-util jar
openfeature 2.7.15 Java 11; forwards feature-flagging-api jar
spring-boot-2.7-webflux 2.7.4 task renamed webfluxBuild
springboot-freemarker 2.7.15 + copyAppResources for FS templates
springboot-java-11 2.7.15 Java 11; forwards iast-util-11
springboot-java-17 2.7.15 Java 17; forwards iast-util-17
springboot-jetty-jsp 2.7.15
springboot-jpa 2.6.0 Lombok
springboot-thymeleaf 2.7.15
springboot-tomcat 2.5.12 Ivy Tomcat download stays in inner build
springboot-tomcat-jsp 2.7.15
springboot-velocity 2.7.15 + copyAppResources for FS templates
datastreams/kafkaschemaregistry 2.6.3 Spring Boot plugin removed (unused)

Motivation

Gradle 9.5 readiness requires every direct subproject of the root build to be compatible with Gradle 9. The Spring Boot Gradle plugin pinned by some smoke tests can't run on Gradle 9, so those apps have to be built out-of-process.

This is an alternative path to #11379, which solved the same problem by committing 22 per-application Gradle 8.14.5 wrappers and shelling out via Exec. In #11379 this created many gradle wrappers, also some Exec tasks forwarded project jars without declaring them as task inputs (stale-cache risk). The approach here addresses both: no wrappers, and forwarded jars are modelled as resolvable Configurations that Gradle wires as task inputs / task dependencies automatically.

Effort part of #10402, #11272

Additional Notes

There's a new included build build-logic/ with one subproject (smoke-test) for a single plugin id (dd-trace-java.smoke-test-app). The reason for this are

  • If dd-trace-java.smoke-test-app was in buildSrc it would add its dependencies in anything that consumes buildSrc plugins. Given this is very specific to some smoke tests, it is preferable to isolate it.
  • Included builds are the Gradle recommended way, so it's where buildSrc/ will be. They are some issue with the (legacy) buildSrc/ way, more details here, in Gradle best practices. Initiating this project now makes sense.

Structurally this new plugin consists of

  • A NestedGradleBuild task type wraps the GradleConnector from the Gradle Tooling API. It pins the nested Gradle distribution and JDK and declares the application directory as @InputFiles and the produced artifact tree as @OutputDirectory.
  • A smokeTestApp { application { ... } } project extension that will be used to configure the task and wiring. If a consumer does not use application { ... }, the plugin is a no-op and the task type can be registered manually.
  • Forwarded root-build jars are exposed via projectJar(name, project), which creates a resolvable Configuration with isTransitive = false — no evaluationDependsOn and no afterEvaluate.
  • The freemarker and velocity modules also need a small Copy task to mirror the nested build's resources/main into the outer build dir, because their controller resolves templates via filesystem paths rather than the classpath.

Noteworthy as well this PR took another route than #11272, in there Spring Boot Gradle plugin is sidestepped, the smoke build emits a flat shadowJar. THis results in jars that have different layout from Spring Boot jars (Spring Boot Class Loader to accommodate the boot jar, BOOT-INF, layered jar). While this approach keeps "thinner" impact, it somewhat makes smoke test not testing exactly the same thing.

Contributor Checklist

Jira ticket: [PROJ-IDENT]

Note: Once your PR is ready to merge, add it to the merge queue by commenting /merge. /merge -c cancels the queue request. /merge -f --reason "reason" skips all merge queue checks; please use this judiciously, as some checks do not run at the PR-level. For more information, see this doc.

bric3 and others added 12 commits May 18, 2026 15:50
Adds a new included build `build-logic/` hosting a single subproject
`smoke-test` that exposes the `dd-trace-java.smoke-test-app` plugin and
its `NestedGradleBuild` task type.

The task runs a nested Gradle build via the Tooling API:
- pins the nested Gradle version (no committed per-application wrappers),
- uses the configured Java toolchain for the nested daemon,
- forwards artifact paths from the root build as `-P<name>=<path>`,
- redirects the nested `buildDir` via `-PappBuildDir=<path>` so outputs
  land under the outer project's build directory.

Smoke-test modules with Spring Boot plugin versions incompatible with
Gradle 9 will use this plugin instead of a committed Gradle 8 wrapper
(see PR #11379 for the wrapper-based alternative).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The Spring Boot Gradle plugin 2.x calls `Configuration.getUploadTaskName()`,
removed in Gradle 9, so springboot-jpa (Spring Boot 2.6.0) cannot stay as a
direct subproject of the Gradle 9 root build.

Extract the application source into a self-contained `application/` Gradle
project pinned to Spring Boot 2.6.0 and built via the new
`dd-trace-java.smoke-test-app` plugin from `build-logic/`. The plugin uses
the Gradle Tooling API to run the nested build with a pinned Gradle version
(8.14.5) and the Java 8 toolchain — no committed `gradlew` wrapper.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…registry

The Spring Boot Gradle plugin was applied but the module never produced a
bootJar/bootWar — it ships a shadow jar instead. Removing the plugin
eliminates a Gradle-9 blocker (the plugin's pre-3.5.0 versions call
`Configuration.getUploadTaskName()`, removed in Gradle 9) with no
behavioural change.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
… Gradle build

These three Spring Boot 2.7.15 smoke tests fail under Gradle 9 because the
Spring Boot plugin (pre-3.5.0) calls `Configuration.getUploadTaskName()`,
removed in Gradle 9. Extract the application source into self-contained
`application/` Gradle projects built via the nested-build plugin from
`build-logic/`, which pins Gradle 8.14.5 and the Java 8 toolchain for the
inner build.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Extract Spring Boot 2.7.15 application sources into self-contained
`application/` Gradle projects built via the nested-build plugin from
`build-logic/`, so the root build can run on Gradle 9 without the Spring
Boot plugin's `Configuration.getUploadTaskName()` regression.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Spring Boot 2.5.12 with the Ivy-downloaded Tomcat server. Move the inline
plugin + Ivy repo + unzip task into a self-contained `application/` Gradle
project built via the nested-build plugin (Gradle 8.14.5, Java 8). The
outer build keeps the test source and forwards the produced war path plus
the Tomcat install directory as system properties.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The Spring Boot 2.7.15 app depends on the iast-util jar produced by the
root build. Extract the application into a self-contained `application/`
project and forward `iast-util.jar` via `-PiastUtilJar=<path>` (tracked
as a task input so the nested build re-runs when the upstream jar changes).

`spring-kafka-test` is pinned to 2.8.11 (the version the Spring Boot BOM
previously resolved); the test module no longer applies the BOM.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Spring Boot 2.7.15, Java 11. Extract the application into a self-contained
`application/` project; forward the `feature-flagging-api` jar from the
root build via `-PfeatureFlaggingApiJar=<path>` (tracked as a task input).

The inner build pins the OpenFeature SDK explicitly because the dependency
is `api`-scoped in feature-flagging-api but is not transitively resolved
when its jar is passed as a `files()` dependency.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Spring Boot 2.7.15 wrapping starter-web 2.2.0, Java 11. Extract the
application into a self-contained `application/` project and forward
`iast-util-11.jar` from the root build via `-PiastUtil11Jar=<path>`.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Same shape as springboot-java-11: Spring Boot 2.7.15 plugin wrapping
starter-web 2.2.0, Java 17, with `iast-util-17.jar` forwarded from the
root build via `-PiastUtil17Jar=<path>`.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Spring Boot 2.7.18, Java 8. Extract the application into a self-contained
`application/` project and forward `dd-trace-api.jar` from the root build
via `-PapiJar=<path>`.

The non-flaky tests pass locally; the `@Flaky`-marked
`ApmTracingDisabledSamplingSmoke{V04,V1}Test` variants remain skipped in
CI as today.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…lugin

This module already had its application source in `application/`, built
via an `Exec` task invoking the root `gradlew`. With the root build moving
to Gradle 9 (incompatible with Spring Boot plugin 2.x), the nested build
must instead pin its own Gradle version. Swap the `Exec` task for the
`NestedGradleBuild` task type from the `build-logic:smoke-test` plugin.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@bric3 bric3 added type: enhancement Enhancements and improvements tag: no release notes Changes to exclude from release notes comp: tooling Build & Tooling tag: ibm IBM JVM related tag: ai generated Largely based on code generated by an AI or LLM tag: do not merge Do not merge changes and removed tag: ibm IBM JVM related labels May 18, 2026
@datadog-prod-us1-3
Copy link
Copy Markdown

datadog-prod-us1-3 Bot commented May 19, 2026

Pipelines

Fix all issues with BitsAI

⚠️ Warnings

🚦 5 Pipeline jobs failed

DataDog/apm-reliability/dd-trace-java | build_tests: [:smokeTest, smoke, -Xms256M -Xmx1024M]   View in Datadog   GitLab

🔧 Fix in code (Fix with Cursor). IncompatibleSpockVersionException: Spock 2.4.0-groovy-3.0 is not compatible with Groovy 4.0.29 during task ':dd-smoke-tests:gradle:compileTestGroovy'.

DataDog/apm-reliability/dd-trace-java | check_smoke 1/4   View in Datadog   GitLab

🔧 Fix in code (Fix with Cursor). Execution failed for task ':dd-smoke-tests:spring-boot-3.0-webflux:webfluxBuild30' due to failed dependency resolution: 'java.util.Set org.gradle.api.artifacts.LenientConfiguration.getArtifacts(org.gradle.api.specs.Spec)'

DataDog/apm-reliability/dd-trace-java | check_smoke 3/4   View in Datadog   GitLab

🔄 Retry job. This looks flaky and may succeed on retry. Execution failed for task ':compileJava'. Error: Failed to notify dependency resolution listener.

View all 5 failed jobs.

Useful? React with 👍 / 👎

This comment will be updated automatically if new data arrives.
🔗 Commit SHA: 922ab43 | Docs | Datadog PR Page | Give us feedback!

bric3 and others added 2 commits May 19, 2026 14:51
Gradle 9.5 added a `DependencyHandler.project(String)` overload that
returns a `ProjectDependency`. Inside a `dependencies { }` block, that
overload now shadows the `Project.project(String)` accessor that
previously resolved via Groovy fallback. Result:
`project(':foo').sourceSets` no longer reaches the producing project's
source sets — it hits a `DefaultProjectDependency` and fails with
"unknown property 'sourceSets'".

`dd-smoke-tests/debugger-integration-tests/build.gradle:21` used
`project(':dd-java-agent:agent-debugger').sourceSets.test.output` to
pull two helper classes (`LogProbeTestHelper`, `MoshiSnapshotTestHelper`)
from `agent-debugger`'s test sources.

Apply the canonical Gradle 9.5 fix (see #11367): expose the helpers via
the `java-test-fixtures` plugin on `agent-debugger`. The helpers move
from `src/test/java/com/datadog/debugger/util/` to
`src/testFixtures/java/com/datadog/debugger/util/` (same package), and
the consumer pulls them in via
`testImplementation testFixtures(project(':dd-java-agent:agent-debugger'))`.

The 15 existing in-project consumers (test classes inside agent-debugger)
keep working because the testFixtures source set is automatically on the
`test` source set's classpath.

This unblocks running the root build on Gradle 9.5.1.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Combined with the smoke-test plugin work earlier on this branch (Spring
Boot 2.x extracted into nested-build subprojects running under a Gradle
8.14.5 daemon via the Tooling API) and the agent-debugger
java-test-fixtures migration, this unblocks the root build on
Gradle 9.5.1.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@bric3 bric3 force-pushed the bdu/smoke-test-tooling-api-build branch from fe8cd93 to 132c13d Compare May 19, 2026 12:51
…plugin

The wildfly and rum:wildfly-15 smoke tests built their EAR via an `Exec`
task invoking the root `gradlew` with `JAVA_HOME=8` (or whatever the
parent shell had). Once the root wrapper moved to Gradle 9, that pattern
broke — Gradle 9 requires a JDK 17 daemon, which then can't load the
JDK 8-targeted application.

Swap both `earBuild` tasks for the `NestedGradleBuild` task type from
the `build-logic:smoke-test` plugin so the nested EAR build runs on a
Gradle 8.14.5 daemon with the Java 8 toolchain. `dd-trace-api.jar` is
forwarded through the plugin's `projectJar(...)` helper.

The surrounding wildfly orchestration (unzip the server zip, copy the
EAR into `standalone/deployments`, `Test.dependsOn 'deploy'`) is
unchanged.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@pr-commenter
Copy link
Copy Markdown

pr-commenter Bot commented May 19, 2026

Debugger benchmarks

Parameters

Baseline Candidate
baseline_or_candidate baseline candidate
ci_job_date 1779196650 1779196997
end_time 2026-05-19T13:18:55 2026-05-19T13:24:43
git_branch master bdu/smoke-test-tooling-api-build
git_commit_sha 198a35d 922ab43
start_time 2026-05-19T13:17:31 2026-05-19T13:23:18
See matching parameters
Baseline Candidate
ci_job_id 1694470017 1694470017
ci_pipeline_id 113952583 113952583
cpu_model Intel(R) Xeon(R) Platinum 8259CL CPU @ 2.50GHz Intel(R) Xeon(R) Platinum 8259CL CPU @ 2.50GHz
git_commit_date 1779195804 1779195804

Summary

Found 0 performance improvements and 0 performance regressions! Performance is the same for 9 metrics, 6 unstable metrics.

See unchanged results
scenario Δ mean agg_http_req_duration_min Δ mean agg_http_req_duration_p50 Δ mean agg_http_req_duration_p75 Δ mean agg_http_req_duration_p99 Δ mean throughput
scenario:noprobe unstable
[-31.250µs; +24.224µs] or [-10.490%; +8.132%]
unstable
[-48.386µs; +33.533µs] or [-14.095%; +9.769%]
unstable
[-62.100µs; +42.265µs] or [-17.195%; +11.703%]
unstable
[+51.983µs; +277.080µs] or [+4.274%; +22.781%]
same
scenario:basic same same same unstable
[-4.081µs; +268.086µs] or [-0.370%; +24.321%]
unstable
[-99.231op/s; +221.182op/s] or [-4.068%; +9.068%]
scenario:loop same unsure
[+2.146µs; +14.012µs] or [+0.024%; +0.156%]
unsure
[+0.428µs; +9.998µs] or [+0.005%; +0.110%]
same same
Request duration reports for reports
gantt
    title reports - request duration [CI 0.99] : candidate=None, baseline=None
    dateFormat X
    axisFormat %s
section baseline
noprobe (343.272 µs) : 295, 392
.   : milestone, 343,
basic (297.507 µs) : 291, 304
.   : milestone, 298,
loop (8.976 ms) : 8970, 8982
.   : milestone, 8976,
section candidate
noprobe (335.846 µs) : 310, 362
.   : milestone, 336,
basic (296.371 µs) : 290, 303
.   : milestone, 296,
loop (8.984 ms) : 8979, 8990
.   : milestone, 8984,
Loading
  • baseline results
Scenario Request median duration [CI 0.99]
noprobe 343.272 µs [294.683 µs, 391.861 µs]
basic 297.507 µs [290.738 µs, 304.276 µs]
loop 8.976 ms [8.97 ms, 8.982 ms]
  • candidate results
Scenario Request median duration [CI 0.99]
noprobe 335.846 µs [309.914 µs, 361.779 µs]
basic 296.371 µs [289.697 µs, 303.046 µs]
loop 8.984 ms [8.979 ms, 8.99 ms]

@bric3
Copy link
Copy Markdown
Contributor Author

bric3 commented May 19, 2026

superseded by smaller prs

@bric3 bric3 closed this May 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp: tooling Build & Tooling tag: ai generated Largely based on code generated by an AI or LLM tag: do not merge Do not merge changes tag: no release notes Changes to exclude from release notes type: enhancement Enhancements and improvements

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant