From 44084faf0ee92b23376b9be75e9604f76e86a068 Mon Sep 17 00:00:00 2001 From: Nelson Osacky Date: Wed, 10 Jun 2026 10:43:58 +0200 Subject: [PATCH 1/3] build(samples): Remove outputs.upToDateWhen { false } from systemTest tasks The systemTest tasks in the sample modules forced Gradle to always treat their outputs as out of date, disabling up-to-date checks and build cache reuse. Removing this lets Gradle rely on its normal input/output tracking for the Test tasks. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../build.gradle.kts | 2 -- sentry-samples/sentry-samples-console-otlp/build.gradle.kts | 2 -- sentry-samples/sentry-samples-console/build.gradle.kts | 2 -- sentry-samples/sentry-samples-jul/build.gradle.kts | 2 -- sentry-samples/sentry-samples-log4j2/build.gradle.kts | 2 -- sentry-samples/sentry-samples-logback/build.gradle.kts | 2 -- sentry-samples/sentry-samples-spring-7/build.gradle.kts | 2 -- .../build.gradle.kts | 2 -- .../sentry-samples-spring-boot-4-opentelemetry/build.gradle.kts | 2 -- .../sentry-samples-spring-boot-4-otlp/build.gradle.kts | 2 -- .../sentry-samples-spring-boot-4-webflux/build.gradle.kts | 2 -- sentry-samples/sentry-samples-spring-boot-4/build.gradle.kts | 2 -- .../build.gradle.kts | 2 -- .../build.gradle.kts | 2 -- .../sentry-samples-spring-boot-jakarta/build.gradle.kts | 2 -- .../build.gradle.kts | 2 -- .../sentry-samples-spring-boot-opentelemetry/build.gradle.kts | 2 -- .../sentry-samples-spring-boot-webflux-jakarta/build.gradle.kts | 2 -- .../sentry-samples-spring-boot-webflux/build.gradle.kts | 2 -- sentry-samples/sentry-samples-spring-boot/build.gradle.kts | 2 -- sentry-samples/sentry-samples-spring-jakarta/build.gradle.kts | 2 -- sentry-samples/sentry-samples-spring/build.gradle.kts | 2 -- 22 files changed, 44 deletions(-) diff --git a/sentry-samples/sentry-samples-console-opentelemetry-noagent/build.gradle.kts b/sentry-samples/sentry-samples-console-opentelemetry-noagent/build.gradle.kts index f5d14dc2c38..3d957d47d70 100644 --- a/sentry-samples/sentry-samples-console-opentelemetry-noagent/build.gradle.kts +++ b/sentry-samples/sentry-samples-console-opentelemetry-noagent/build.gradle.kts @@ -71,8 +71,6 @@ tasks.register("systemTest").configure { testClassesDirs = test.output.classesDirs classpath = test.runtimeClasspath - outputs.upToDateWhen { false } - maxParallelForks = 1 // Cap JVM args per test diff --git a/sentry-samples/sentry-samples-console-otlp/build.gradle.kts b/sentry-samples/sentry-samples-console-otlp/build.gradle.kts index 483f6bea799..b15095d34fa 100644 --- a/sentry-samples/sentry-samples-console-otlp/build.gradle.kts +++ b/sentry-samples/sentry-samples-console-otlp/build.gradle.kts @@ -74,8 +74,6 @@ tasks.register("systemTest").configure { testClassesDirs = test.output.classesDirs classpath = test.runtimeClasspath - outputs.upToDateWhen { false } - maxParallelForks = 1 // Cap JVM args per test diff --git a/sentry-samples/sentry-samples-console/build.gradle.kts b/sentry-samples/sentry-samples-console/build.gradle.kts index 79878ab9a08..ca4cef0e1fe 100644 --- a/sentry-samples/sentry-samples-console/build.gradle.kts +++ b/sentry-samples/sentry-samples-console/build.gradle.kts @@ -75,8 +75,6 @@ tasks.register("systemTest").configure { testClassesDirs = test.output.classesDirs classpath = test.runtimeClasspath - outputs.upToDateWhen { false } - maxParallelForks = 1 // Cap JVM args per test diff --git a/sentry-samples/sentry-samples-jul/build.gradle.kts b/sentry-samples/sentry-samples-jul/build.gradle.kts index 01e6a95f13d..8dda92fec68 100644 --- a/sentry-samples/sentry-samples-jul/build.gradle.kts +++ b/sentry-samples/sentry-samples-jul/build.gradle.kts @@ -66,8 +66,6 @@ tasks.register("systemTest").configure { testClassesDirs = test.output.classesDirs classpath = test.runtimeClasspath - outputs.upToDateWhen { false } - maxParallelForks = 1 // Cap JVM args per test diff --git a/sentry-samples/sentry-samples-log4j2/build.gradle.kts b/sentry-samples/sentry-samples-log4j2/build.gradle.kts index 005e1116528..eeb5e28c136 100644 --- a/sentry-samples/sentry-samples-log4j2/build.gradle.kts +++ b/sentry-samples/sentry-samples-log4j2/build.gradle.kts @@ -72,8 +72,6 @@ tasks.register("systemTest").configure { testClassesDirs = test.output.classesDirs classpath = test.runtimeClasspath - outputs.upToDateWhen { false } - maxParallelForks = 1 // Cap JVM args per test diff --git a/sentry-samples/sentry-samples-logback/build.gradle.kts b/sentry-samples/sentry-samples-logback/build.gradle.kts index 05f96c346a8..ec94c75f111 100644 --- a/sentry-samples/sentry-samples-logback/build.gradle.kts +++ b/sentry-samples/sentry-samples-logback/build.gradle.kts @@ -66,8 +66,6 @@ tasks.register("systemTest").configure { testClassesDirs = test.output.classesDirs classpath = test.runtimeClasspath - outputs.upToDateWhen { false } - maxParallelForks = 1 // Cap JVM args per test diff --git a/sentry-samples/sentry-samples-spring-7/build.gradle.kts b/sentry-samples/sentry-samples-spring-7/build.gradle.kts index e3300cd2841..87e130ab89b 100644 --- a/sentry-samples/sentry-samples-spring-7/build.gradle.kts +++ b/sentry-samples/sentry-samples-spring-7/build.gradle.kts @@ -77,8 +77,6 @@ tasks.register("systemTest").configure { testClassesDirs = test.output.classesDirs classpath = test.runtimeClasspath - outputs.upToDateWhen { false } - maxParallelForks = 1 // Cap JVM args per test diff --git a/sentry-samples/sentry-samples-spring-boot-4-opentelemetry-noagent/build.gradle.kts b/sentry-samples/sentry-samples-spring-boot-4-opentelemetry-noagent/build.gradle.kts index 64ef57692c3..7be3ca89465 100644 --- a/sentry-samples/sentry-samples-spring-boot-4-opentelemetry-noagent/build.gradle.kts +++ b/sentry-samples/sentry-samples-spring-boot-4-opentelemetry-noagent/build.gradle.kts @@ -90,8 +90,6 @@ tasks.register("systemTest").configure { testClassesDirs = test.output.classesDirs classpath = test.runtimeClasspath - outputs.upToDateWhen { false } - maxParallelForks = 1 // Cap JVM args per test diff --git a/sentry-samples/sentry-samples-spring-boot-4-opentelemetry/build.gradle.kts b/sentry-samples/sentry-samples-spring-boot-4-opentelemetry/build.gradle.kts index e12b960e0fd..fea36cf4109 100644 --- a/sentry-samples/sentry-samples-spring-boot-4-opentelemetry/build.gradle.kts +++ b/sentry-samples/sentry-samples-spring-boot-4-opentelemetry/build.gradle.kts @@ -118,8 +118,6 @@ tasks.register("systemTest").configure { testClassesDirs = test.output.classesDirs classpath = test.runtimeClasspath - outputs.upToDateWhen { false } - maxParallelForks = 1 // Cap JVM args per test diff --git a/sentry-samples/sentry-samples-spring-boot-4-otlp/build.gradle.kts b/sentry-samples/sentry-samples-spring-boot-4-otlp/build.gradle.kts index 7329d5cc0ea..2281fc03d49 100644 --- a/sentry-samples/sentry-samples-spring-boot-4-otlp/build.gradle.kts +++ b/sentry-samples/sentry-samples-spring-boot-4-otlp/build.gradle.kts @@ -91,8 +91,6 @@ tasks.register("systemTest").configure { testClassesDirs = test.output.classesDirs classpath = test.runtimeClasspath - outputs.upToDateWhen { false } - maxParallelForks = 1 // Cap JVM args per test diff --git a/sentry-samples/sentry-samples-spring-boot-4-webflux/build.gradle.kts b/sentry-samples/sentry-samples-spring-boot-4-webflux/build.gradle.kts index a311b8a972e..2557b551dc1 100644 --- a/sentry-samples/sentry-samples-spring-boot-4-webflux/build.gradle.kts +++ b/sentry-samples/sentry-samples-spring-boot-4-webflux/build.gradle.kts @@ -70,8 +70,6 @@ tasks.register("systemTest").configure { testClassesDirs = test.output.classesDirs classpath = test.runtimeClasspath - outputs.upToDateWhen { false } - maxParallelForks = 1 // Cap JVM args per test diff --git a/sentry-samples/sentry-samples-spring-boot-4/build.gradle.kts b/sentry-samples/sentry-samples-spring-boot-4/build.gradle.kts index cdb33ecc675..3d494b9567b 100644 --- a/sentry-samples/sentry-samples-spring-boot-4/build.gradle.kts +++ b/sentry-samples/sentry-samples-spring-boot-4/build.gradle.kts @@ -92,8 +92,6 @@ tasks.register("systemTest").configure { testClassesDirs = test.output.classesDirs classpath = test.runtimeClasspath - outputs.upToDateWhen { false } - maxParallelForks = 1 // Cap JVM args per test diff --git a/sentry-samples/sentry-samples-spring-boot-jakarta-opentelemetry-noagent/build.gradle.kts b/sentry-samples/sentry-samples-spring-boot-jakarta-opentelemetry-noagent/build.gradle.kts index 7966e621ebd..e75f4b5f2c5 100644 --- a/sentry-samples/sentry-samples-spring-boot-jakarta-opentelemetry-noagent/build.gradle.kts +++ b/sentry-samples/sentry-samples-spring-boot-jakarta-opentelemetry-noagent/build.gradle.kts @@ -95,8 +95,6 @@ tasks.register("systemTest").configure { testClassesDirs = test.output.classesDirs classpath = test.runtimeClasspath - outputs.upToDateWhen { false } - maxParallelForks = 1 // Cap JVM args per test diff --git a/sentry-samples/sentry-samples-spring-boot-jakarta-opentelemetry/build.gradle.kts b/sentry-samples/sentry-samples-spring-boot-jakarta-opentelemetry/build.gradle.kts index 3c7e00ae552..97c2437567f 100644 --- a/sentry-samples/sentry-samples-spring-boot-jakarta-opentelemetry/build.gradle.kts +++ b/sentry-samples/sentry-samples-spring-boot-jakarta-opentelemetry/build.gradle.kts @@ -128,8 +128,6 @@ tasks.register("systemTest").configure { testClassesDirs = test.output.classesDirs classpath = test.runtimeClasspath - outputs.upToDateWhen { false } - maxParallelForks = 1 // Cap JVM args per test diff --git a/sentry-samples/sentry-samples-spring-boot-jakarta/build.gradle.kts b/sentry-samples/sentry-samples-spring-boot-jakarta/build.gradle.kts index d5e4caa595d..0e054a25fd4 100644 --- a/sentry-samples/sentry-samples-spring-boot-jakarta/build.gradle.kts +++ b/sentry-samples/sentry-samples-spring-boot-jakarta/build.gradle.kts @@ -98,8 +98,6 @@ tasks.register("systemTest").configure { testClassesDirs = test.output.classesDirs classpath = test.runtimeClasspath - outputs.upToDateWhen { false } - maxParallelForks = 1 // Cap JVM args per test diff --git a/sentry-samples/sentry-samples-spring-boot-opentelemetry-noagent/build.gradle.kts b/sentry-samples/sentry-samples-spring-boot-opentelemetry-noagent/build.gradle.kts index 0b8c5a181e7..762c78964c5 100644 --- a/sentry-samples/sentry-samples-spring-boot-opentelemetry-noagent/build.gradle.kts +++ b/sentry-samples/sentry-samples-spring-boot-opentelemetry-noagent/build.gradle.kts @@ -140,8 +140,6 @@ tasks.register("systemTest").configure { testClassesDirs = test.output.classesDirs classpath = test.runtimeClasspath - outputs.upToDateWhen { false } - maxParallelForks = 1 // Cap JVM args per test diff --git a/sentry-samples/sentry-samples-spring-boot-opentelemetry/build.gradle.kts b/sentry-samples/sentry-samples-spring-boot-opentelemetry/build.gradle.kts index b78f1f01881..b2a5bb5353c 100644 --- a/sentry-samples/sentry-samples-spring-boot-opentelemetry/build.gradle.kts +++ b/sentry-samples/sentry-samples-spring-boot-opentelemetry/build.gradle.kts @@ -162,8 +162,6 @@ tasks.register("systemTest").configure { testClassesDirs = test.output.classesDirs classpath = test.runtimeClasspath - outputs.upToDateWhen { false } - maxParallelForks = 1 // Cap JVM args per test diff --git a/sentry-samples/sentry-samples-spring-boot-webflux-jakarta/build.gradle.kts b/sentry-samples/sentry-samples-spring-boot-webflux-jakarta/build.gradle.kts index 8b2079ddd9c..dd9946196d5 100644 --- a/sentry-samples/sentry-samples-spring-boot-webflux-jakarta/build.gradle.kts +++ b/sentry-samples/sentry-samples-spring-boot-webflux-jakarta/build.gradle.kts @@ -72,8 +72,6 @@ tasks.register("systemTest").configure { testClassesDirs = test.output.classesDirs classpath = test.runtimeClasspath - outputs.upToDateWhen { false } - maxParallelForks = 1 // Cap JVM args per test diff --git a/sentry-samples/sentry-samples-spring-boot-webflux/build.gradle.kts b/sentry-samples/sentry-samples-spring-boot-webflux/build.gradle.kts index 2127dbfd79f..4d29e0daac2 100644 --- a/sentry-samples/sentry-samples-spring-boot-webflux/build.gradle.kts +++ b/sentry-samples/sentry-samples-spring-boot-webflux/build.gradle.kts @@ -107,8 +107,6 @@ tasks.register("systemTest").configure { testClassesDirs = test.output.classesDirs classpath = test.runtimeClasspath - outputs.upToDateWhen { false } - maxParallelForks = 1 // Cap JVM args per test diff --git a/sentry-samples/sentry-samples-spring-boot/build.gradle.kts b/sentry-samples/sentry-samples-spring-boot/build.gradle.kts index 0a2a6f2da57..9bd1a4f70bd 100644 --- a/sentry-samples/sentry-samples-spring-boot/build.gradle.kts +++ b/sentry-samples/sentry-samples-spring-boot/build.gradle.kts @@ -141,8 +141,6 @@ tasks.register("systemTest").configure { testClassesDirs = test.output.classesDirs classpath = test.runtimeClasspath - outputs.upToDateWhen { false } - maxParallelForks = 1 // Cap JVM args per test diff --git a/sentry-samples/sentry-samples-spring-jakarta/build.gradle.kts b/sentry-samples/sentry-samples-spring-jakarta/build.gradle.kts index 3dec793e5c9..9c1f4fd523b 100644 --- a/sentry-samples/sentry-samples-spring-jakarta/build.gradle.kts +++ b/sentry-samples/sentry-samples-spring-jakarta/build.gradle.kts @@ -77,8 +77,6 @@ tasks.register("systemTest").configure { testClassesDirs = test.output.classesDirs classpath = test.runtimeClasspath - outputs.upToDateWhen { false } - maxParallelForks = 1 // Cap JVM args per test diff --git a/sentry-samples/sentry-samples-spring/build.gradle.kts b/sentry-samples/sentry-samples-spring/build.gradle.kts index 02e7f632450..aa289186c9f 100644 --- a/sentry-samples/sentry-samples-spring/build.gradle.kts +++ b/sentry-samples/sentry-samples-spring/build.gradle.kts @@ -78,8 +78,6 @@ tasks.register("systemTest").configure { testClassesDirs = test.output.classesDirs classpath = test.runtimeClasspath - outputs.upToDateWhen { false } - maxParallelForks = 1 // Cap JVM args per test From 1357435668ee079835d7784e53638bfed9bb01ae Mon Sep 17 00:00:00 2001 From: Nelson Osacky Date: Mon, 22 Jun 2026 17:03:50 +0200 Subject: [PATCH 2/3] build(samples): Track systemTest app archive via convention plugin The system tests launch the packaged sample (war/shadowJar/bootJar) from build/libs as a separate process, so the archive is a real input to the systemTest task even though it is not on the test classpath. Without it, removing outputs.upToDateWhen { false } would let Gradle mark systemTest up-to-date while a separate jar build refreshed the artifact, skipping verification against the rebuilt sample. Move that wiring into a single io.sentry.systemtest convention plugin in build-logic instead of repeating it in every sample build file. The plugin auto-detects the packaging task (war, else shadowJar, else bootJar), mirroring the selection in test/system-test-runner.py, and declares its archive as an input and dependency. Each sample just applies the plugin. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../kotlin/io.sentry.systemtest.gradle.kts | 18 ++++++++++++++++++ .../build.gradle.kts | 1 + .../build.gradle.kts | 1 + .../sentry-samples-console/build.gradle.kts | 1 + .../sentry-samples-jul/build.gradle.kts | 1 + .../sentry-samples-log4j2/build.gradle.kts | 1 + .../sentry-samples-logback/build.gradle.kts | 1 + .../sentry-samples-spring-7/build.gradle.kts | 1 + .../build.gradle.kts | 1 + .../build.gradle.kts | 1 + .../build.gradle.kts | 1 + .../build.gradle.kts | 1 + .../build.gradle.kts | 1 + .../build.gradle.kts | 1 + .../build.gradle.kts | 1 + .../build.gradle.kts | 1 + .../build.gradle.kts | 1 + .../build.gradle.kts | 1 + .../build.gradle.kts | 1 + .../build.gradle.kts | 1 + .../build.gradle.kts | 1 + .../build.gradle.kts | 1 + .../sentry-samples-spring/build.gradle.kts | 1 + 23 files changed, 40 insertions(+) create mode 100644 build-logic/src/main/kotlin/io.sentry.systemtest.gradle.kts diff --git a/build-logic/src/main/kotlin/io.sentry.systemtest.gradle.kts b/build-logic/src/main/kotlin/io.sentry.systemtest.gradle.kts new file mode 100644 index 00000000000..dc8ec16e43f --- /dev/null +++ b/build-logic/src/main/kotlin/io.sentry.systemtest.gradle.kts @@ -0,0 +1,18 @@ +import org.gradle.api.tasks.ClasspathNormalizer + +// The sample system tests launch the packaged app (war/shadowJar/bootJar) from +// build/libs as a separate process, so the archive is a real input even though it +// is not on the test classpath. See test/system-test-runner.py. +tasks.matching { it.name == "systemTest" }.configureEach { + val archiveTask = + listOf("war", "shadowJar", "bootJar").firstOrNull { it in tasks.names } + ?: throw GradleException( + "io.sentry.systemtest is applied to $path but none of war/shadowJar/bootJar " + + "exist to provide the launched app archive for the systemTest task" + ) + // Declaring the archive as an input also wires the dependency on its producing task. + inputs + .files(tasks.named(archiveTask)) + .withPropertyName("appArchive") + .withNormalizer(ClasspathNormalizer::class.java) +} diff --git a/sentry-samples/sentry-samples-console-opentelemetry-noagent/build.gradle.kts b/sentry-samples/sentry-samples-console-opentelemetry-noagent/build.gradle.kts index 3d957d47d70..9db90129958 100644 --- a/sentry-samples/sentry-samples-console-opentelemetry-noagent/build.gradle.kts +++ b/sentry-samples/sentry-samples-console-opentelemetry-noagent/build.gradle.kts @@ -6,6 +6,7 @@ plugins { alias(libs.plugins.kotlin.jvm) alias(libs.plugins.gradle.versions) alias(libs.plugins.shadow) + id("io.sentry.systemtest") } application { mainClass.set("io.sentry.samples.console.Main") } diff --git a/sentry-samples/sentry-samples-console-otlp/build.gradle.kts b/sentry-samples/sentry-samples-console-otlp/build.gradle.kts index b15095d34fa..261894baaa0 100644 --- a/sentry-samples/sentry-samples-console-otlp/build.gradle.kts +++ b/sentry-samples/sentry-samples-console-otlp/build.gradle.kts @@ -6,6 +6,7 @@ plugins { alias(libs.plugins.kotlin.jvm) alias(libs.plugins.gradle.versions) alias(libs.plugins.shadow) + id("io.sentry.systemtest") } application { mainClass.set("io.sentry.samples.console.Main") } diff --git a/sentry-samples/sentry-samples-console/build.gradle.kts b/sentry-samples/sentry-samples-console/build.gradle.kts index ca4cef0e1fe..3e70e79ae71 100644 --- a/sentry-samples/sentry-samples-console/build.gradle.kts +++ b/sentry-samples/sentry-samples-console/build.gradle.kts @@ -6,6 +6,7 @@ plugins { alias(libs.plugins.kotlin.jvm) alias(libs.plugins.gradle.versions) alias(libs.plugins.shadow) + id("io.sentry.systemtest") } application { mainClass.set("io.sentry.samples.console.Main") } diff --git a/sentry-samples/sentry-samples-jul/build.gradle.kts b/sentry-samples/sentry-samples-jul/build.gradle.kts index 8dda92fec68..310af1e7bce 100644 --- a/sentry-samples/sentry-samples-jul/build.gradle.kts +++ b/sentry-samples/sentry-samples-jul/build.gradle.kts @@ -6,6 +6,7 @@ plugins { alias(libs.plugins.kotlin.jvm) alias(libs.plugins.gradle.versions) alias(libs.plugins.shadow) + id("io.sentry.systemtest") } application { mainClass.set("io.sentry.samples.jul.Main") } diff --git a/sentry-samples/sentry-samples-log4j2/build.gradle.kts b/sentry-samples/sentry-samples-log4j2/build.gradle.kts index eeb5e28c136..962fd56a839 100644 --- a/sentry-samples/sentry-samples-log4j2/build.gradle.kts +++ b/sentry-samples/sentry-samples-log4j2/build.gradle.kts @@ -6,6 +6,7 @@ plugins { alias(libs.plugins.kotlin.jvm) alias(libs.plugins.gradle.versions) alias(libs.plugins.shadow) + id("io.sentry.systemtest") } application { mainClass.set("io.sentry.samples.log4j2.Main") } diff --git a/sentry-samples/sentry-samples-logback/build.gradle.kts b/sentry-samples/sentry-samples-logback/build.gradle.kts index ec94c75f111..1a7f3a23875 100644 --- a/sentry-samples/sentry-samples-logback/build.gradle.kts +++ b/sentry-samples/sentry-samples-logback/build.gradle.kts @@ -6,6 +6,7 @@ plugins { alias(libs.plugins.kotlin.jvm) alias(libs.plugins.gradle.versions) alias(libs.plugins.shadow) + id("io.sentry.systemtest") } application { mainClass.set("io.sentry.samples.logback.Main") } diff --git a/sentry-samples/sentry-samples-spring-7/build.gradle.kts b/sentry-samples/sentry-samples-spring-7/build.gradle.kts index 87e130ab89b..3e108aabd1e 100644 --- a/sentry-samples/sentry-samples-spring-7/build.gradle.kts +++ b/sentry-samples/sentry-samples-spring-7/build.gradle.kts @@ -10,6 +10,7 @@ plugins { alias(libs.plugins.kotlin.spring) id("war") alias(libs.plugins.gretty) + id("io.sentry.systemtest") } application { mainClass.set("io.sentry.samples.spring7.Main") } diff --git a/sentry-samples/sentry-samples-spring-boot-4-opentelemetry-noagent/build.gradle.kts b/sentry-samples/sentry-samples-spring-boot-4-opentelemetry-noagent/build.gradle.kts index 7be3ca89465..722788830f1 100644 --- a/sentry-samples/sentry-samples-spring-boot-4-opentelemetry-noagent/build.gradle.kts +++ b/sentry-samples/sentry-samples-spring-boot-4-opentelemetry-noagent/build.gradle.kts @@ -6,6 +6,7 @@ plugins { alias(libs.plugins.spring.dependency.management) alias(libs.plugins.kotlin.jvm) alias(libs.plugins.kotlin.spring) + id("io.sentry.systemtest") } group = "io.sentry.sample.spring-boot-4" diff --git a/sentry-samples/sentry-samples-spring-boot-4-opentelemetry/build.gradle.kts b/sentry-samples/sentry-samples-spring-boot-4-opentelemetry/build.gradle.kts index fea36cf4109..1dc90decf5e 100644 --- a/sentry-samples/sentry-samples-spring-boot-4-opentelemetry/build.gradle.kts +++ b/sentry-samples/sentry-samples-spring-boot-4-opentelemetry/build.gradle.kts @@ -7,6 +7,7 @@ plugins { alias(libs.plugins.spring.dependency.management) alias(libs.plugins.kotlin.jvm) alias(libs.plugins.kotlin.spring) + id("io.sentry.systemtest") } group = "io.sentry.sample.spring-boot-4" diff --git a/sentry-samples/sentry-samples-spring-boot-4-otlp/build.gradle.kts b/sentry-samples/sentry-samples-spring-boot-4-otlp/build.gradle.kts index 2281fc03d49..d793201d4c0 100644 --- a/sentry-samples/sentry-samples-spring-boot-4-otlp/build.gradle.kts +++ b/sentry-samples/sentry-samples-spring-boot-4-otlp/build.gradle.kts @@ -6,6 +6,7 @@ plugins { alias(libs.plugins.spring.dependency.management) alias(libs.plugins.kotlin.jvm) alias(libs.plugins.kotlin.spring) + id("io.sentry.systemtest") } group = "io.sentry.sample.spring-boot-4-otlp" diff --git a/sentry-samples/sentry-samples-spring-boot-4-webflux/build.gradle.kts b/sentry-samples/sentry-samples-spring-boot-4-webflux/build.gradle.kts index 2557b551dc1..6d8d3c81e09 100644 --- a/sentry-samples/sentry-samples-spring-boot-4-webflux/build.gradle.kts +++ b/sentry-samples/sentry-samples-spring-boot-4-webflux/build.gradle.kts @@ -6,6 +6,7 @@ plugins { alias(libs.plugins.spring.dependency.management) alias(libs.plugins.kotlin.jvm) alias(libs.plugins.kotlin.spring) + id("io.sentry.systemtest") } group = "io.sentry.sample.spring-boot-4-webflux" diff --git a/sentry-samples/sentry-samples-spring-boot-4/build.gradle.kts b/sentry-samples/sentry-samples-spring-boot-4/build.gradle.kts index 3d494b9567b..4e463671a78 100644 --- a/sentry-samples/sentry-samples-spring-boot-4/build.gradle.kts +++ b/sentry-samples/sentry-samples-spring-boot-4/build.gradle.kts @@ -6,6 +6,7 @@ plugins { alias(libs.plugins.spring.dependency.management) alias(libs.plugins.kotlin.jvm) alias(libs.plugins.kotlin.spring) + id("io.sentry.systemtest") } group = "io.sentry.sample.spring-boot-4" diff --git a/sentry-samples/sentry-samples-spring-boot-jakarta-opentelemetry-noagent/build.gradle.kts b/sentry-samples/sentry-samples-spring-boot-jakarta-opentelemetry-noagent/build.gradle.kts index e75f4b5f2c5..553affc3620 100644 --- a/sentry-samples/sentry-samples-spring-boot-jakarta-opentelemetry-noagent/build.gradle.kts +++ b/sentry-samples/sentry-samples-spring-boot-jakarta-opentelemetry-noagent/build.gradle.kts @@ -7,6 +7,7 @@ plugins { alias(libs.plugins.spring.dependency.management) alias(libs.plugins.kotlin.jvm) alias(libs.plugins.kotlin.spring) + id("io.sentry.systemtest") } group = "io.sentry.sample.spring-boot-jakarta" diff --git a/sentry-samples/sentry-samples-spring-boot-jakarta-opentelemetry/build.gradle.kts b/sentry-samples/sentry-samples-spring-boot-jakarta-opentelemetry/build.gradle.kts index 97c2437567f..29de465c478 100644 --- a/sentry-samples/sentry-samples-spring-boot-jakarta-opentelemetry/build.gradle.kts +++ b/sentry-samples/sentry-samples-spring-boot-jakarta-opentelemetry/build.gradle.kts @@ -8,6 +8,7 @@ plugins { alias(libs.plugins.spring.dependency.management) alias(libs.plugins.kotlin.jvm) alias(libs.plugins.kotlin.spring) + id("io.sentry.systemtest") } group = "io.sentry.sample.spring-boot-jakarta" diff --git a/sentry-samples/sentry-samples-spring-boot-jakarta/build.gradle.kts b/sentry-samples/sentry-samples-spring-boot-jakarta/build.gradle.kts index 0e054a25fd4..65850a6f2bd 100644 --- a/sentry-samples/sentry-samples-spring-boot-jakarta/build.gradle.kts +++ b/sentry-samples/sentry-samples-spring-boot-jakarta/build.gradle.kts @@ -7,6 +7,7 @@ plugins { alias(libs.plugins.spring.dependency.management) alias(libs.plugins.kotlin.jvm) alias(libs.plugins.kotlin.spring) + id("io.sentry.systemtest") } group = "io.sentry.sample.spring-boot-jakarta" diff --git a/sentry-samples/sentry-samples-spring-boot-opentelemetry-noagent/build.gradle.kts b/sentry-samples/sentry-samples-spring-boot-opentelemetry-noagent/build.gradle.kts index 762c78964c5..e32eec82ac8 100644 --- a/sentry-samples/sentry-samples-spring-boot-opentelemetry-noagent/build.gradle.kts +++ b/sentry-samples/sentry-samples-spring-boot-opentelemetry-noagent/build.gradle.kts @@ -8,6 +8,7 @@ plugins { alias(libs.plugins.shadow) alias(libs.plugins.kotlin.jvm) alias(libs.plugins.kotlin.spring) + id("io.sentry.systemtest") } application { mainClass.set("io.sentry.samples.spring.boot.SentryDemoApplication") } diff --git a/sentry-samples/sentry-samples-spring-boot-opentelemetry/build.gradle.kts b/sentry-samples/sentry-samples-spring-boot-opentelemetry/build.gradle.kts index b2a5bb5353c..0bb0d0d09f6 100644 --- a/sentry-samples/sentry-samples-spring-boot-opentelemetry/build.gradle.kts +++ b/sentry-samples/sentry-samples-spring-boot-opentelemetry/build.gradle.kts @@ -8,6 +8,7 @@ plugins { alias(libs.plugins.shadow) alias(libs.plugins.kotlin.jvm) alias(libs.plugins.kotlin.spring) + id("io.sentry.systemtest") } application { mainClass.set("io.sentry.samples.spring.boot.SentryDemoApplication") } diff --git a/sentry-samples/sentry-samples-spring-boot-webflux-jakarta/build.gradle.kts b/sentry-samples/sentry-samples-spring-boot-webflux-jakarta/build.gradle.kts index dd9946196d5..3e462517ded 100644 --- a/sentry-samples/sentry-samples-spring-boot-webflux-jakarta/build.gradle.kts +++ b/sentry-samples/sentry-samples-spring-boot-webflux-jakarta/build.gradle.kts @@ -7,6 +7,7 @@ plugins { alias(libs.plugins.spring.dependency.management) alias(libs.plugins.kotlin.jvm) alias(libs.plugins.kotlin.spring) + id("io.sentry.systemtest") } group = "io.sentry.sample.spring-boot-webflux-jakarta" diff --git a/sentry-samples/sentry-samples-spring-boot-webflux/build.gradle.kts b/sentry-samples/sentry-samples-spring-boot-webflux/build.gradle.kts index 4d29e0daac2..8dc51e07a53 100644 --- a/sentry-samples/sentry-samples-spring-boot-webflux/build.gradle.kts +++ b/sentry-samples/sentry-samples-spring-boot-webflux/build.gradle.kts @@ -8,6 +8,7 @@ plugins { alias(libs.plugins.shadow) alias(libs.plugins.kotlin.jvm) alias(libs.plugins.kotlin.spring) + id("io.sentry.systemtest") } application { mainClass.set("io.sentry.samples.spring.boot.SentryDemoApplication") } diff --git a/sentry-samples/sentry-samples-spring-boot/build.gradle.kts b/sentry-samples/sentry-samples-spring-boot/build.gradle.kts index 9bd1a4f70bd..54fe99d56d4 100644 --- a/sentry-samples/sentry-samples-spring-boot/build.gradle.kts +++ b/sentry-samples/sentry-samples-spring-boot/build.gradle.kts @@ -8,6 +8,7 @@ plugins { alias(libs.plugins.shadow) alias(libs.plugins.kotlin.jvm) alias(libs.plugins.kotlin.spring) + id("io.sentry.systemtest") } application { mainClass.set("io.sentry.samples.spring.boot.SentryDemoApplication") } diff --git a/sentry-samples/sentry-samples-spring-jakarta/build.gradle.kts b/sentry-samples/sentry-samples-spring-jakarta/build.gradle.kts index 9c1f4fd523b..5fe0334a629 100644 --- a/sentry-samples/sentry-samples-spring-jakarta/build.gradle.kts +++ b/sentry-samples/sentry-samples-spring-jakarta/build.gradle.kts @@ -8,6 +8,7 @@ plugins { alias(libs.plugins.kotlin.spring) id("war") alias(libs.plugins.gretty) + id("io.sentry.systemtest") } application { mainClass.set("io.sentry.samples.spring.jakarta.Main") } diff --git a/sentry-samples/sentry-samples-spring/build.gradle.kts b/sentry-samples/sentry-samples-spring/build.gradle.kts index aa289186c9f..3ab6610d96d 100644 --- a/sentry-samples/sentry-samples-spring/build.gradle.kts +++ b/sentry-samples/sentry-samples-spring/build.gradle.kts @@ -8,6 +8,7 @@ plugins { alias(libs.plugins.kotlin.spring) id("war") alias(libs.plugins.gretty) + id("io.sentry.systemtest") } application { mainClass.set("io.sentry.samples.spring.Main") } From 06b56f26ce6f4df8b5878f50db246ea89d597b05 Mon Sep 17 00:00:00 2001 From: Nelson Osacky Date: Tue, 23 Jun 2026 09:46:27 +0200 Subject: [PATCH 3/3] build(samples): Track OpenTelemetry agent jar as systemTest input The agent-based OpenTelemetry samples are launched by the runner with -javaagent:, started outside the test JVM. That jar is not on the test classpath nor one of the app archives, so without tracking it systemTest could stay up-to-date and be skipped while the runner launches a newer agent. Add a usesOpenTelemetryAgent opt-in to the io.sentry.systemtest plugin; the three agent samples enable it and the agent jar is then tracked as a content input. The runner already builds and launches the agent before invoking the task, so it is tracked by path without a cross-project task dependency, which keeps it configuration-on-demand and configuration cache compatible. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../kotlin/io.sentry.systemtest.gradle.kts | 26 ++++++++++++++++--- .../io/sentry/gradle/SystemTestExtension.kt | 17 ++++++++++++ .../build.gradle.kts | 3 +++ .../build.gradle.kts | 3 +++ .../build.gradle.kts | 3 +++ 5 files changed, 49 insertions(+), 3 deletions(-) create mode 100644 build-logic/src/main/kotlin/io/sentry/gradle/SystemTestExtension.kt diff --git a/build-logic/src/main/kotlin/io.sentry.systemtest.gradle.kts b/build-logic/src/main/kotlin/io.sentry.systemtest.gradle.kts index dc8ec16e43f..a21079e1336 100644 --- a/build-logic/src/main/kotlin/io.sentry.systemtest.gradle.kts +++ b/build-logic/src/main/kotlin/io.sentry.systemtest.gradle.kts @@ -1,8 +1,12 @@ +import io.sentry.gradle.SystemTestExtension import org.gradle.api.tasks.ClasspathNormalizer -// The sample system tests launch the packaged app (war/shadowJar/bootJar) from -// build/libs as a separate process, so the archive is a real input even though it -// is not on the test classpath. See test/system-test-runner.py. +val systemTest = extensions.create("sentrySystemTest") + +// The sample system tests launch the packaged app (war/shadowJar/bootJar) from build/libs as a +// separate process, so the archive is a real input even though it is not on the test classpath. +// Agent-based samples are additionally launched with -javaagent:, another runtime +// input not on the classpath. See test/system-test-runner.py. tasks.matching { it.name == "systemTest" }.configureEach { val archiveTask = listOf("war", "shadowJar", "bootJar").firstOrNull { it in tasks.names } @@ -15,4 +19,20 @@ tasks.matching { it.name == "systemTest" }.configureEach { .files(tasks.named(archiveTask)) .withPropertyName("appArchive") .withNormalizer(ClasspathNormalizer::class.java) + + if (systemTest.usesOpenTelemetryAgent.get()) { + // The runner builds the agent and launches the app with -javaagent before invoking this task, + // so the agent jar is tracked for content only (by path, no cross-project task dependency): a + // change to it makes systemTest out of date even though it runs outside the test JVM. + val version = providers.gradleProperty("versionName").get() + inputs + .files( + rootProject.layout.projectDirectory.file( + "sentry-opentelemetry/sentry-opentelemetry-agent/build/libs/" + + "sentry-opentelemetry-agent-$version.jar" + ) + ) + .withPropertyName("openTelemetryAgent") + .withNormalizer(ClasspathNormalizer::class.java) + } } diff --git a/build-logic/src/main/kotlin/io/sentry/gradle/SystemTestExtension.kt b/build-logic/src/main/kotlin/io/sentry/gradle/SystemTestExtension.kt new file mode 100644 index 00000000000..9111ce17b1f --- /dev/null +++ b/build-logic/src/main/kotlin/io/sentry/gradle/SystemTestExtension.kt @@ -0,0 +1,17 @@ +package io.sentry.gradle + +import org.gradle.api.provider.Property + +/** Configuration for the `io.sentry.systemtest` convention plugin. */ +abstract class SystemTestExtension { + /** + * Set to `true` for samples that the system-test runner launches with the Sentry OpenTelemetry + * Java agent (`-javaagent`). The agent jar is then tracked as a `systemTest` input so the task + * re-runs when the agent changes, even though it is started outside the test JVM. + */ + abstract val usesOpenTelemetryAgent: Property + + init { + usesOpenTelemetryAgent.convention(false) + } +} diff --git a/sentry-samples/sentry-samples-spring-boot-4-opentelemetry/build.gradle.kts b/sentry-samples/sentry-samples-spring-boot-4-opentelemetry/build.gradle.kts index 1dc90decf5e..b9551ffcf74 100644 --- a/sentry-samples/sentry-samples-spring-boot-4-opentelemetry/build.gradle.kts +++ b/sentry-samples/sentry-samples-spring-boot-4-opentelemetry/build.gradle.kts @@ -111,6 +111,9 @@ tasks.register("bootRunWithAgent").configure { jvmArgs = listOf("-Dotel.javaagent.debug=true", "-javaagent:$agentJarPath") } +// The runner launches this sample with -javaagent, so track the agent jar as a systemTest input. +sentrySystemTest { usesOpenTelemetryAgent = true } + tasks.register("systemTest").configure { group = "verification" description = "Runs the System tests" diff --git a/sentry-samples/sentry-samples-spring-boot-jakarta-opentelemetry/build.gradle.kts b/sentry-samples/sentry-samples-spring-boot-jakarta-opentelemetry/build.gradle.kts index 29de465c478..e4fefab7de7 100644 --- a/sentry-samples/sentry-samples-spring-boot-jakarta-opentelemetry/build.gradle.kts +++ b/sentry-samples/sentry-samples-spring-boot-jakarta-opentelemetry/build.gradle.kts @@ -121,6 +121,9 @@ tasks.register("bootRunWithAgent").configure { jvmArgs = listOf("-Dotel.javaagent.debug=true", "-javaagent:$agentJarPath") } +// The runner launches this sample with -javaagent, so track the agent jar as a systemTest input. +sentrySystemTest { usesOpenTelemetryAgent = true } + tasks.register("systemTest").configure { group = "verification" description = "Runs the System tests" diff --git a/sentry-samples/sentry-samples-spring-boot-opentelemetry/build.gradle.kts b/sentry-samples/sentry-samples-spring-boot-opentelemetry/build.gradle.kts index 0bb0d0d09f6..085d6e362af 100644 --- a/sentry-samples/sentry-samples-spring-boot-opentelemetry/build.gradle.kts +++ b/sentry-samples/sentry-samples-spring-boot-opentelemetry/build.gradle.kts @@ -155,6 +155,9 @@ tasks.register("bootRunWithAgent").configure { jvmArgs = listOf("-Dotel.javaagent.debug=true", "-javaagent:$agentJarPath") } +// The runner launches this sample with -javaagent, so track the agent jar as a systemTest input. +sentrySystemTest { usesOpenTelemetryAgent = true } + tasks.register("systemTest").configure { group = "verification" description = "Runs the System tests"