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..a21079e1336 --- /dev/null +++ b/build-logic/src/main/kotlin/io.sentry.systemtest.gradle.kts @@ -0,0 +1,38 @@ +import io.sentry.gradle.SystemTestExtension +import org.gradle.api.tasks.ClasspathNormalizer + +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 } + ?: 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) + + 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-console-opentelemetry-noagent/build.gradle.kts b/sentry-samples/sentry-samples-console-opentelemetry-noagent/build.gradle.kts index f5d14dc2c38..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") } @@ -71,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-console-otlp/build.gradle.kts b/sentry-samples/sentry-samples-console-otlp/build.gradle.kts index 483f6bea799..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") } @@ -74,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-console/build.gradle.kts b/sentry-samples/sentry-samples-console/build.gradle.kts index 79878ab9a08..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") } @@ -75,8 +76,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..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") } @@ -66,8 +67,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..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") } @@ -72,8 +73,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..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") } @@ -66,8 +67,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..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") } @@ -77,8 +78,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..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" @@ -90,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-opentelemetry/build.gradle.kts b/sentry-samples/sentry-samples-spring-boot-4-opentelemetry/build.gradle.kts index e12b960e0fd..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 @@ -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" @@ -110,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" @@ -118,8 +122,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..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" @@ -91,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-4-webflux/build.gradle.kts b/sentry-samples/sentry-samples-spring-boot-4-webflux/build.gradle.kts index a311b8a972e..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" @@ -70,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-spring-boot-4/build.gradle.kts b/sentry-samples/sentry-samples-spring-boot-4/build.gradle.kts index cdb33ecc675..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" @@ -92,8 +93,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..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" @@ -95,8 +96,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..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 @@ -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" @@ -120,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" @@ -128,8 +132,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..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" @@ -98,8 +99,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..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") } @@ -140,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-boot-opentelemetry/build.gradle.kts b/sentry-samples/sentry-samples-spring-boot-opentelemetry/build.gradle.kts index b78f1f01881..085d6e362af 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") } @@ -154,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" @@ -162,8 +166,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..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" @@ -72,8 +73,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..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") } @@ -107,8 +108,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..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") } @@ -141,8 +142,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..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") } @@ -77,8 +78,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..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") } @@ -78,8 +79,6 @@ tasks.register("systemTest").configure { testClassesDirs = test.output.classesDirs classpath = test.runtimeClasspath - outputs.upToDateWhen { false } - maxParallelForks = 1 // Cap JVM args per test