Skip to content

Commit 4d41075

Browse files
committed
Merge remote-tracking branch 'origin/master' into mcculls/context-continuations
2 parents f8d0935 + cc3000e commit 4d41075

877 files changed

Lines changed: 7831 additions & 3951 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
issuer: https://gitlab.ddbuild.io
22

3-
subject_pattern: "project_path:DataDog/apm-reliability/dd-trace-java:ref_type:tag:ref:v.*"
3+
subject_pattern: 'project_path:DataDog/apm-reliability/dd-trace-java:ref_type:tag:ref:v\d+\.\d+\.\d+'
44

55
claim_pattern:
66
project_path: "DataDog/apm-reliability/dd-trace-java"
77
ref_type: "tag"
8-
ref: "v.*"
8+
ref: 'v\d+\.\d+\.\d+'
99

1010
permissions:
1111
contents: "write"

.github/scripts/dependency_age.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -551,6 +551,8 @@ def build_validation_summary(
551551
blocks.append(
552552
"### :warning: Cannot verify age, reverted\n\n"
553553
"The age of these dependencies could not be verified, so the lockfiles were reverted. "
554+
"This likely means that the following dependencies are published to a repo not yet configured in the workflow. "
555+
"If this is the case, add the missing repository as a `--repo-url` in the `Validate changed lock files` step of `.github/workflows/update-gradle-dependencies.yaml`. "
554556
"**This needs to be resolved manually.**\n\n"
555557
+ "\n".join(sorted(unverified))
556558
)

.github/workflows/update-gradle-dependencies.yaml

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,14 +68,22 @@ jobs:
6868
--min-age-hours "${MIN_DEPENDENCY_AGE_HOURS}" \
6969
--repo-url "https://repo1.maven.org/maven2" \
7070
--repo-url "https://repo.akka.io/${AKKA_REPO_TOKEN}/secure" \
71+
--repo-url "https://packages.confluent.io/maven" \
72+
--repo-url "https://repository.mulesoft.org/releases" \
73+
--repo-url "https://repository.mulesoft.org/nexus/content/repositories/public" \
7174
--github-output "$GITHUB_OUTPUT"
7275
7376
- name: Save instrumentation lock files
7477
run: |
7578
mkdir -p /tmp/instrumentation-lockfiles
7679
find dd-smoke-tests dd-java-agent/instrumentation -name 'gradle.lockfile' -exec cp --parents {} /tmp/instrumentation-lockfiles/ \;
77-
# Restore instrumentation dirs to original state (keep only core changes)
80+
# Restore instrumentation dirs to original state (keep only core changes).
81+
# git restore only reverts tracked files; brand-new lock files are untracked
82+
# and would otherwise leak into the core PR, so delete the untracked ones too.
7883
git restore -- 'dd-smoke-tests/' 'dd-java-agent/instrumentation/'
84+
git ls-files --others --exclude-standard -- \
85+
'dd-smoke-tests/*gradle.lockfile' 'dd-java-agent/instrumentation/*gradle.lockfile' \
86+
| xargs -r rm -f
7987
8088
# ==================== Core modules PR ====================
8189
- name: Check if core changes exist

.github/workflows/update-smoke-test-latest-versions.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,8 @@ jobs:
6868
--artifact-id maven-surefire-plugin \
6969
--prerelease-pattern alpha \
7070
--prerelease-pattern beta \
71+
--prerelease-pattern rc \
72+
--prerelease-pattern '-m\d' \
7173
--min-age-hours "${MIN_DEPENDENCY_AGE_HOURS}" \
7274
--current-version "${{ steps.current.outputs.surefire_version }}" \
7375
--github-output "$GITHUB_OUTPUT"

.gitlab-ci.yml

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ variables:
4949
BUILD_JOB_NAME: "build"
5050
DEPENDENCY_CACHE_POLICY: pull
5151
BUILD_CACHE_POLICY: pull
52-
GRADLE_VERSION: "9.5.1" # must match gradle-wrapper.properties
52+
GRADLE_VERSION: "9.6.0" # must match gradle-wrapper.properties
5353
MASS_READ_URL: "https://mass-read.us1.ddbuild.io"
5454
MAVEN_REPOSITORY_PROXY: "https://depot-read-api-java.us1.ddbuild.io/magicmirror/magicmirror/@current/"
5555
GRADLE_PLUGIN_PROXY: "https://depot-read-api-java.us1.ddbuild.io/magicmirror/magicmirror/@current/"
@@ -242,8 +242,9 @@ default:
242242
EOF
243243
- mkdir -p .gradle
244244
- export GRADLE_USER_HOME=$(pwd)/.gradle
245-
# replace maven central part by MAVEN_REPOSITORY_PROXY in .mvn/wrapper/maven-wrapper.properties
246-
- sed -i "s|https://repo.maven.apache.org/maven2/|$MAVEN_REPOSITORY_PROXY|g" .mvn/wrapper/maven-wrapper.properties
245+
# Apache Maven Wrapper supports MVNW_REPOURL for repository-manager downloads:
246+
# https://maven.apache.org/tools/wrapper/#Using_a_Maven_Repository_Manager
247+
- export MVNW_REPOURL=${MAVEN_REPOSITORY_PROXY%/}
247248
# Route Gradle distribution download through MASS pull-through cache
248249
- |
249250
mass_read_host="${MASS_READ_URL#https://}"
@@ -336,7 +337,7 @@ build:
336337
script:
337338
- if [ $CI_PIPELINE_SOURCE == "schedule" ] ; then ./gradlew resolveAndLockAll --write-locks $GRADLE_ARGS; fi
338339
- ./gradlew --version
339-
- ./gradlew clean :dd-java-agent:shadowJar :dd-trace-api:jar :dd-trace-ot:shadowJar -PskipTests $GRADLE_ARGS
340+
- ./gradlew clean :dd-java-agent:shadowJar :dd-java-agent:check :dd-trace-api:jar :dd-trace-ot:shadowJar -PskipTests -x spotlessCheck $GRADLE_ARGS
340341
- echo UPSTREAM_TRACER_VERSION=$(java -jar workspace/dd-java-agent/build/libs/*.jar) >> upstream.env
341342
- echo "BUILD_JOB_NAME=$CI_JOB_NAME" >> build.env
342343
- echo "BUILD_JOB_ID=$CI_JOB_ID" >> build.env
@@ -784,7 +785,9 @@ muzzle-dep-report:
784785
# and Gradle does `chmod 700 .gradle` on startup which requires user ownership.
785786
- sudo chown -R 1001:1001 .gradle
786787
- export GRADLE_USER_HOME=$(pwd)/.gradle
787-
- sed -i "s|https://repo.maven.apache.org/maven2/|$MAVEN_REPOSITORY_PROXY|g" .mvn/wrapper/maven-wrapper.properties
788+
# Apache Maven Wrapper supports MVNW_REPOURL for repository-manager downloads:
789+
# https://maven.apache.org/tools/wrapper/#Using_a_Maven_Repository_Manager
790+
- export MVNW_REPOURL=${MAVEN_REPOSITORY_PROXY%/}
788791
- *normalize_node_index
789792
- *prepare_test_env
790793
# Disable CDS in forked JVMs to avoid SIGSEGVs on Linux arm64.

.gitlab/java-benchmark-configs.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,10 @@ linux-java-spring-petclinic-load-parallel:
5050
needs: ["publish-artifacts-to-s3"]
5151
rules: *parallel_benchmark_rules
5252

53+
linux-java-spring-petclinic-sca-load-parallel:
54+
needs: ["publish-artifacts-to-s3"]
55+
rules: *parallel_benchmark_rules
56+
5357
linux-java-insecure-bank-startup-parallel:
5458
needs: ["publish-artifacts-to-s3"]
5559
rules: *parallel_startup_benchmark_rules

build-logic/smoke-test/build.gradle.kts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ gradlePlugin {
3232
@Suppress("UnstableApiUsage")
3333
testing {
3434
suites {
35-
val test by getting(JvmTestSuite::class) {
35+
named<JvmTestSuite>("test") {
3636
useJUnitJupiter(libs.versions.junit5)
3737
dependencies {
3838
implementation(libs.junit.jupiter)

build-logic/smoke-test/src/main/kotlin/datadog/buildlogic/smoketest/NestedGradleBuild.kt

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,11 @@ abstract class NestedGradleBuild @Inject constructor(
113113
@get:Input
114114
abstract val buildCacheEnabled: Property<Boolean>
115115

116+
/** Timeout, in seconds, for stopping the nested Gradle daemon after the build. */
117+
@get:Input
118+
@get:Optional
119+
abstract val stopTimeoutSeconds: Property<Long>
120+
116121
/**
117122
* Extra environment variables for the nested Gradle daemon. Merged on top of the outer process
118123
* environment; Gradle launcher variables are reserved by this task so nested builds do not
@@ -236,9 +241,17 @@ abstract class NestedGradleBuild @Inject constructor(
236241
}
237242

238243
val process = processBuilder.start()
239-
if (!process.waitFor(GRADLE_STOP_TIMEOUT_SECONDS, TimeUnit.SECONDS)) {
244+
val timeoutSeconds = stopTimeoutSeconds.orNull
245+
val completed =
246+
if (timeoutSeconds == null) {
247+
process.waitFor()
248+
true
249+
} else {
250+
process.waitFor(timeoutSeconds, TimeUnit.SECONDS)
251+
}
252+
if (!completed) {
240253
process.destroyForcibly()
241-
logger.warn("Timed out while stopping nested Gradle daemon")
254+
logger.warn("Timed out after {} seconds while stopping nested Gradle daemon", timeoutSeconds)
242255
return
243256
}
244257
val exitCode = process.exitValue()
@@ -270,13 +283,6 @@ abstract class NestedGradleBuild @Inject constructor(
270283
file.parentFile?.name == "bin"
271284
}
272285

273-
private fun gradleExecutableName(): String =
274-
if (System.getProperty("os.name").lowercase().contains("windows")) {
275-
"gradle.bat"
276-
} else {
277-
"gradle"
278-
}
279-
280286
private fun createGradleUserHome(): File {
281287
val directory = temporaryDir.resolve("gradle-user-home")
282288
deleteGradleUserHome(directory)
@@ -294,8 +300,13 @@ abstract class NestedGradleBuild @Inject constructor(
294300
}
295301
}
296302

297-
private companion object {
298-
const val GRADLE_STOP_TIMEOUT_SECONDS = 30L
303+
companion object {
304+
internal fun gradleExecutableName(osName: String = System.getProperty("os.name")): String =
305+
if (isWindows(osName)) {
306+
"gradle.bat"
307+
} else {
308+
"gradle"
309+
}
299310
}
300311
}
301312

Lines changed: 201 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,201 @@
1+
package datadog.buildlogic.smoketest
2+
3+
import org.gradle.api.DefaultTask
4+
import org.gradle.api.GradleException
5+
import org.gradle.api.file.DirectoryProperty
6+
import org.gradle.api.file.FileTree
7+
import org.gradle.api.file.RegularFileProperty
8+
import org.gradle.api.model.ObjectFactory
9+
import org.gradle.api.provider.ListProperty
10+
import org.gradle.api.provider.MapProperty
11+
import org.gradle.api.provider.Property
12+
import org.gradle.api.tasks.CacheableTask
13+
import org.gradle.api.tasks.IgnoreEmptyDirectories
14+
import org.gradle.api.tasks.Input
15+
import org.gradle.api.tasks.InputFile
16+
import org.gradle.api.tasks.InputFiles
17+
import org.gradle.api.tasks.Internal
18+
import org.gradle.api.tasks.Nested
19+
import org.gradle.api.tasks.Optional
20+
import org.gradle.api.tasks.OutputDirectory
21+
import org.gradle.api.tasks.PathSensitive
22+
import org.gradle.api.tasks.PathSensitivity
23+
import org.gradle.api.tasks.TaskAction
24+
import org.gradle.jvm.toolchain.JavaLanguageVersion
25+
import org.gradle.jvm.toolchain.JavaLauncher
26+
import org.gradle.jvm.toolchain.JavaToolchainService
27+
import java.io.File
28+
import java.util.concurrent.TimeUnit
29+
import javax.inject.Inject
30+
31+
/**
32+
* Runs a nested Maven build inside [applicationDir] via the root Maven wrapper.
33+
*
34+
* The nested build is expected to honour `-Dtarget.dir=<path>` and write outputs under that
35+
* directory so Gradle can track the artifact under [applicationBuildDir].
36+
*/
37+
@CacheableTask
38+
abstract class NestedMavenBuild @Inject constructor(
39+
private val objects: ObjectFactory,
40+
javaToolchains: JavaToolchainService,
41+
) : DefaultTask() {
42+
43+
init {
44+
javaLauncher.convention(
45+
javaToolchains.launcherFor {
46+
languageVersion.set(JavaLanguageVersion.of(DEFAULT_NESTED_JAVA_VERSION))
47+
},
48+
)
49+
goals.convention(listOf("package"))
50+
arguments.convention(emptyList())
51+
environment.convention(emptyMap())
52+
mavenOpts.convention("")
53+
useMavenLocalRepository.convention(false)
54+
}
55+
56+
@get:Internal
57+
abstract val applicationDir: DirectoryProperty
58+
59+
@get:InputFiles
60+
@get:IgnoreEmptyDirectories
61+
@get:PathSensitive(PathSensitivity.RELATIVE)
62+
val applicationSources: FileTree =
63+
objects.fileTree().from(applicationDir).matching {
64+
exclude("target/**")
65+
}
66+
67+
@get:OutputDirectory
68+
abstract val applicationBuildDir: DirectoryProperty
69+
70+
@get:InputFile
71+
@get:PathSensitive(PathSensitivity.RELATIVE)
72+
abstract val mavenExecutable: RegularFileProperty
73+
74+
@get:InputFiles
75+
@get:IgnoreEmptyDirectories
76+
@get:PathSensitive(PathSensitivity.RELATIVE)
77+
val mavenWrapperFiles: FileTree =
78+
objects.fileTree().from(project.rootProject.layout.projectDirectory.dir(".mvn/wrapper")).matching {
79+
include("maven-wrapper.properties", "maven-wrapper.jar")
80+
}
81+
82+
@get:Nested
83+
abstract val javaLauncher: Property<JavaLauncher>
84+
85+
@get:Input
86+
abstract val goals: ListProperty<String>
87+
88+
@get:Input
89+
abstract val arguments: ListProperty<String>
90+
91+
@get:Input
92+
abstract val environment: MapProperty<String, String>
93+
94+
@get:Input
95+
@get:Optional
96+
abstract val mavenOpts: Property<String>
97+
98+
@get:Input
99+
@get:Optional
100+
abstract val mavenRepositoryProxy: Property<String>
101+
102+
@get:Input
103+
abstract val useMavenLocalRepository: Property<Boolean>
104+
105+
/** Timeout, in seconds, for the nested Maven build process. */
106+
@get:Input
107+
@get:Optional
108+
abstract val buildTimeoutSeconds: Property<Long>
109+
110+
@get:Internal
111+
abstract val mavenLocalRepository: DirectoryProperty
112+
113+
@TaskAction
114+
fun runNestedBuild() {
115+
val appDir = applicationDir.get().asFile
116+
val appBuildDirFile = applicationBuildDir.get().asFile
117+
val targetDir = appBuildDirFile.resolve("target")
118+
val daemonJavaHome = javaLauncher.get().metadata.installationPath.asFile
119+
val command = mavenCommand(mavenExecutable.get().asFile).apply {
120+
add("-Dtarget.dir=${targetDir.absolutePath}")
121+
if (useMavenLocalRepository.get()) {
122+
add("-Dmaven.repo.local=${mavenLocalRepository.get().asFile.absolutePath}")
123+
}
124+
addAll(arguments.get())
125+
addAll(goals.get())
126+
}
127+
128+
val process = ProcessBuilder(command)
129+
.directory(appDir)
130+
.redirectOutput(ProcessBuilder.Redirect.INHERIT)
131+
.redirectError(ProcessBuilder.Redirect.INHERIT)
132+
.apply {
133+
environment().apply {
134+
clear()
135+
putAll(nestedEnvironment(daemonJavaHome))
136+
}
137+
}
138+
.start()
139+
140+
try {
141+
val timeoutSeconds = buildTimeoutSeconds.orNull
142+
val completed =
143+
if (timeoutSeconds == null) {
144+
process.waitFor()
145+
true
146+
} else {
147+
process.waitFor(timeoutSeconds, TimeUnit.SECONDS)
148+
}
149+
if (!completed) {
150+
process.destroyForcibly()
151+
throw GradleException(
152+
"Nested Maven build timed out after $timeoutSeconds seconds: " +
153+
command.joinToString(" "),
154+
)
155+
}
156+
} catch (e: InterruptedException) {
157+
process.destroyForcibly()
158+
Thread.currentThread().interrupt()
159+
throw GradleException("Interrupted while running nested Maven build", e)
160+
}
161+
val exitCode = process.exitValue()
162+
if (exitCode != 0) {
163+
throw GradleException(
164+
"Nested Maven build failed with exit code $exitCode: ${command.joinToString(" ")}",
165+
)
166+
}
167+
}
168+
169+
private fun nestedEnvironment(daemonJavaHome: File): Map<String, String> {
170+
val env = System.getenv().toMutableMap()
171+
val repositoryProxy = mavenRepositoryProxy.orNull?.takeIf { it.isNotBlank() }
172+
if (repositoryProxy != null) {
173+
env["MAVEN_REPOSITORY_PROXY"] = repositoryProxy
174+
env.putIfAbsent("MVNW_REPOURL", repositoryProxy.trimEnd('/'))
175+
}
176+
val opts = mavenOpts.orNull
177+
if (!opts.isNullOrBlank()) {
178+
env["MAVEN_OPTS"] = opts
179+
}
180+
env["JAVA_HOME"] = daemonJavaHome.absolutePath
181+
env.putAll(environment.get())
182+
return env
183+
}
184+
185+
private fun mavenCommand(executable: File): MutableList<String> =
186+
if (isWindows()) {
187+
mutableListOf("cmd", "/c", executable.absolutePath)
188+
} else {
189+
mutableListOf(executable.absolutePath)
190+
}
191+
192+
companion object {
193+
internal fun mavenWrapperName(osName: String = System.getProperty("os.name")): String =
194+
if (isWindows(osName)) {
195+
"mvnw.cmd"
196+
} else {
197+
"mvnw"
198+
}
199+
200+
}
201+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package datadog.buildlogic.smoketest
2+
3+
import java.util.Locale
4+
5+
internal fun isWindows(osName: String = System.getProperty("os.name")): Boolean =
6+
osName.lowercase(Locale.ROOT).contains("windows")
7+

0 commit comments

Comments
 (0)