Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
055a019
fix(build): remove Spring Boot 2 Gradle plugin for Gradle 9 compatibiโ€ฆ
adinauer Apr 2, 2026
9dd4f2f
fix: set duplicatesStrategy=INCLUDE for shadow JAR spring.factories mโ€ฆ
adinauer Apr 2, 2026
63aa458
fix: remove duplicate shadow plugin entry in version catalog
adinauer Apr 2, 2026
0e43fc7
Format code
getsentry-bot Apr 2, 2026
da7d400
fix: update system test runner for shadow JAR compatibility
adinauer Apr 2, 2026
c0acbd7
fix(otel): use DuplicatesStrategy.INCLUDE for otel agent shadow JAR
adinauer Apr 2, 2026
c3c8c24
Exclude test-support modules from api validation
romtsn Apr 7, 2026
76eba12
Verbose system test output and wire inputs for them properly
romtsn Apr 7, 2026
5bfc096
align coroutines version to 1.9.0 for system tests
romtsn Apr 7, 2026
5a29bc6
fix(otel): use mergeServiceFiles path instead of include for Shadow 9.x
romtsn Apr 10, 2026
f47be74
fix(otel): add default mergeServiceFiles for bootstrap service relocaโ€ฆ
romtsn Apr 10, 2026
00c8173
fix(spring-boot2): pre-merge Spring metadata for Shadow 9.x compatibiโ€ฆ
romtsn Apr 10, 2026
3bfe40d
Format code
getsentry-bot Apr 10, 2026
0a95998
fix(lint): suppress OldTargetApi for uitest-android module
romtsn Apr 10, 2026
9a388af
fix(spring-boot2): make mergeSpringMetadata configuration-cache compaโ€ฆ
romtsn Apr 10, 2026
8ae3c9c
formatting
romtsn Apr 10, 2026
4a48a27
fix(spring-boot2): replace from() with doLast JAR patching for springโ€ฆ
romtsn Apr 10, 2026
05c5bac
formatting
romtsn Apr 10, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,9 @@ apiValidation {
"test-app-sentry",
"test-app-size",
"sentry-samples-netflix-dgs",
"sentry-samples-console-otlp"
"sentry-samples-console-otlp",
"sentry-test-support",
"sentry-system-test-support"
)
)
}
Expand Down
4 changes: 2 additions & 2 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -61,14 +61,13 @@ detekt = { id = "io.gitlab.arturbosch.detekt", version = "1.23.8" }
jacoco-android = { id = "com.mxalbert.gradle.jacoco-android", version = "0.2.0" }
kover = { id = "org.jetbrains.kotlinx.kover", version = "0.7.3" }
vanniktech-maven-publish = { id = "com.vanniktech.maven.publish", version = "0.30.0" }
springboot2 = { id = "org.springframework.boot", version.ref = "springboot2" }
springboot3 = { id = "org.springframework.boot", version.ref = "springboot3" }
springboot4 = { id = "org.springframework.boot", version.ref = "springboot4" }
spring-dependency-management = { id = "io.spring.dependency-management", version = "1.1.7" }
gretty = { id = "org.gretty", version = "4.0.0" }
animalsniffer = { id = "ru.vyarus.animalsniffer", version = "2.0.1" }
sentry = { id = "io.sentry.android.gradle", version = "6.0.0-alpha.6"}
shadow = { id = "com.gradleup.shadow", version = "8.3.6" }
shadow = { id = "com.gradleup.shadow", version = "9.4.1" }

[libraries]
apache-httpclient = { module = "org.apache.httpcomponents.client5:httpclient5", version = "5.0.4" }
Expand Down Expand Up @@ -159,6 +158,7 @@ slf4j-api = { module = "org.slf4j:slf4j-api", version.ref = "slf4j" }
slf4j-jdk14 = { module = "org.slf4j:slf4j-jdk14", version.ref = "slf4j" }
slf4j2-api = { module = "org.slf4j:slf4j-api", version = "2.0.5" }
spotlessLib = { module = "com.diffplug.spotless:com.diffplug.spotless.gradle.plugin", version.ref = "spotless"}
springboot2-bom = { module = "org.springframework.boot:spring-boot-dependencies", version.ref = "springboot2" }
springboot-starter = { module = "org.springframework.boot:spring-boot-starter", version.ref = "springboot2" }
springboot-starter-graphql = { module = "org.springframework.boot:spring-boot-starter-graphql", version.ref = "springboot2" }
springboot-starter-quartz = { module = "org.springframework.boot:spring-boot-starter-quartz", version.ref = "springboot2" }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,8 @@ android {
lint {
warningsAsErrors = true
checkDependencies = true
// Suppress OldTargetApi: lint 8.13.1 expects API 37 but we target 36
disable += "OldTargetApi"

// We run a full lint analysis as build part in CI, so skip vital checks for assemble tasks.
checkReleaseBuilds = false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -150,9 +150,22 @@ tasks {

archiveClassifier.set("")

duplicatesStrategy = DuplicatesStrategy.FAIL

mergeServiceFiles { include("inst/META-INF/services/*") }
// INCLUDE is required so that mergeServiceFiles can see duplicates from both the
// upstream agent JAR and the isolated distro libs before they are deduplicated.
// Shadow 9.x enforces duplicatesStrategy before transformers run, so FAIL/EXCLUDE
// would prevent service file merging.
duplicatesStrategy = DuplicatesStrategy.INCLUDE

// Shadow 9.x only applies relocations to service files handled by a ServiceFileTransformer.
// We need two mergeServiceFiles calls:
// 1. Default path (META-INF/services) โ€” ensures bootstrap service files get relocated
// (e.g., ContextStorageProvider โ†’ shaded path). Without this, Shadow 9.x skips
// relocation for service file names/contents not claimed by a transformer.
// 2. inst/ path โ€” merges isolated agent service files from both the upstream agent
// and the distro libs. Uses `path` instead of `include` filter because Shadow 9.x's
// include() strips the `inst/` prefix on output.
mergeServiceFiles()
mergeServiceFiles { path = "inst/META-INF/services" }
exclude("**/module-info.class")
relocatePackages(this)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ dependencies {
tasks.shadowJar {
manifest { attributes["Main-Class"] = "io.sentry.samples.console.Main" }
archiveClassifier.set("") // Remove the classifier so it replaces the regular JAR
duplicatesStrategy = DuplicatesStrategy.INCLUDE
mergeServiceFiles()
}

Expand All @@ -66,6 +67,10 @@ tasks.register<Test>("systemTest").configure {
group = "verification"
description = "Runs the System tests"

val test = project.extensions.getByType<SourceSetContainer>()["test"]
testClassesDirs = test.output.classesDirs
classpath = test.runtimeClasspath

outputs.upToDateWhen { false }

maxParallelForks = 1
Expand Down
5 changes: 5 additions & 0 deletions sentry-samples/sentry-samples-console-otlp/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ dependencies {
tasks.shadowJar {
manifest { attributes["Main-Class"] = "io.sentry.samples.console.Main" }
archiveClassifier.set("") // Remove the classifier so it replaces the regular JAR
duplicatesStrategy = DuplicatesStrategy.INCLUDE
mergeServiceFiles()
}

Expand All @@ -69,6 +70,10 @@ tasks.register<Test>("systemTest").configure {
group = "verification"
description = "Runs the System tests"

val test = project.extensions.getByType<SourceSetContainer>()["test"]
testClassesDirs = test.output.classesDirs
classpath = test.runtimeClasspath

outputs.upToDateWhen { false }

maxParallelForks = 1
Expand Down
4 changes: 4 additions & 0 deletions sentry-samples/sentry-samples-console/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,10 @@ tasks.register<Test>("systemTest").configure {
group = "verification"
description = "Runs the System tests"

val test = project.extensions.getByType<SourceSetContainer>()["test"]
testClassesDirs = test.output.classesDirs
classpath = test.runtimeClasspath

outputs.upToDateWhen { false }

maxParallelForks = 1
Expand Down
4 changes: 4 additions & 0 deletions sentry-samples/sentry-samples-jul/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,10 @@ tasks.register<Test>("systemTest").configure {
group = "verification"
description = "Runs the System tests"

val test = project.extensions.getByType<SourceSetContainer>()["test"]
testClassesDirs = test.output.classesDirs
classpath = test.runtimeClasspath

outputs.upToDateWhen { false }

maxParallelForks = 1
Expand Down
5 changes: 5 additions & 0 deletions sentry-samples/sentry-samples-log4j2/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ dependencies {
tasks.shadowJar {
manifest { attributes["Main-Class"] = "io.sentry.samples.log4j2.Main" }
archiveClassifier.set("") // Remove the classifier so it replaces the regular JAR
duplicatesStrategy = DuplicatesStrategy.INCLUDE
mergeServiceFiles()
// Use Log4j2 cache transformer to properly handle plugin files
transform(
Expand All @@ -67,6 +68,10 @@ tasks.register<Test>("systemTest").configure {
group = "verification"
description = "Runs the System tests"

val test = project.extensions.getByType<SourceSetContainer>()["test"]
testClassesDirs = test.output.classesDirs
classpath = test.runtimeClasspath

outputs.upToDateWhen { false }

maxParallelForks = 1
Expand Down
4 changes: 4 additions & 0 deletions sentry-samples/sentry-samples-logback/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,10 @@ tasks.register<Test>("systemTest").configure {
group = "verification"
description = "Runs the System tests"

val test = project.extensions.getByType<SourceSetContainer>()["test"]
testClassesDirs = test.output.classesDirs
classpath = test.runtimeClasspath

outputs.upToDateWhen { false }

maxParallelForks = 1
Expand Down
85 changes: 83 additions & 2 deletions sentry-samples/sentry-samples-netflix-dgs/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,13 +1,21 @@
import java.net.URI
import java.nio.file.FileSystems
import java.nio.file.Files
import java.nio.file.StandardCopyOption
import java.util.zip.ZipFile
import org.jetbrains.kotlin.config.KotlinCompilerVersion
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile

plugins {
alias(libs.plugins.springboot2)
alias(libs.plugins.spring.dependency.management)
java
application
alias(libs.plugins.shadow)
alias(libs.plugins.kotlin.jvm)
alias(libs.plugins.kotlin.spring)
}

application { mainClass.set("io.sentry.samples.netflix.dgs.NetlixDgsApplication") }

group = "io.sentry.sample.spring-boot"

version = "0.0.1-SNAPSHOT"
Expand All @@ -19,6 +27,7 @@ java.targetCompatibility = JavaVersion.VERSION_1_8
repositories { mavenCentral() }

dependencies {
implementation(platform(libs.springboot2.bom))
implementation(libs.springboot.starter.web)
implementation(Config.Libs.kotlinReflect)
implementation(kotlin(Config.kotlinStdLib, KotlinCompilerVersion.VERSION))
Expand All @@ -32,6 +41,78 @@ dependencies {
}
}

// Shadow 9.x enforces DuplicatesStrategy before transformers run, so the `append`
// transformer only sees one copy of each file. We pre-merge Spring metadata files
// from the runtime classpath and include the merged result in the shadow JAR.
val mergeSpringMetadata by
tasks.registering {
val outputDir = project.layout.buildDirectory.dir("merged-spring-metadata/META-INF")
val classpathJars = configurations.runtimeClasspath.get().filter { it.name.endsWith(".jar") }
val filesToMerge =
listOf(
"spring.factories",
"spring.handlers",
"spring.schemas",
"spring-autoconfigure-metadata.properties",
)
outputs.dir(outputDir)
inputs.files(classpathJars)
doLast {
val out = outputDir.get().asFile
out.mkdirs()
filesToMerge.forEach { fileName ->
val merged = StringBuilder()
classpathJars.forEach { jar ->
try {
val zip = ZipFile(jar)
val entry = zip.getEntry("META-INF/$fileName")
if (entry != null) {
merged.append(zip.getInputStream(entry).bufferedReader().readText())
if (!merged.endsWith("\n")) merged.append("\n")
}
zip.close()
} catch (e: Exception) {
/* skip non-zip files */
}
}
if (merged.isNotEmpty()) {
File(out, fileName).writeText(merged.toString())
}
}
}
}

// Configure the Shadow JAR (executable JAR with all dependencies)
tasks.shadowJar {
dependsOn(mergeSpringMetadata)
manifest { attributes["Main-Class"] = "io.sentry.samples.netflix.dgs.NetlixDgsApplication" }
archiveClassifier.set("")
mergeServiceFiles()
val metadataDir = project.layout.buildDirectory.dir("merged-spring-metadata/META-INF")
doLast {
val jarFile = archiveFile.get().asFile
val metaDir = metadataDir.get().asFile
if (!metaDir.exists()) return@doLast
val uri = URI.create("jar:${jarFile.toURI()}")
FileSystems.newFileSystem(uri, mapOf("create" to "false")).use { fs ->
metaDir.listFiles()?.forEach { merged ->
Files.copy(
merged.toPath(),
fs.getPath("META-INF/${merged.name}"),
StandardCopyOption.REPLACE_EXISTING,
)
}
}
}
}

tasks.jar {
enabled = false
dependsOn(tasks.shadowJar)
}

tasks.startScripts { dependsOn(tasks.shadowJar) }

tasks.withType<Test>().configureEach { useJUnitPlatform() }

tasks.withType<KotlinCompile>().configureEach {
Expand Down
4 changes: 4 additions & 0 deletions sentry-samples/sentry-samples-spring-7/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,10 @@ tasks.register<Test>("systemTest").configure {
group = "verification"
description = "Runs the System tests"

val test = project.extensions.getByType<SourceSetContainer>()["test"]
testClassesDirs = test.output.classesDirs
classpath = test.runtimeClasspath

outputs.upToDateWhen { false }

maxParallelForks = 1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,10 @@ tasks.register<Test>("systemTest").configure {
group = "verification"
description = "Runs the System tests"

val test = project.extensions.getByType<SourceSetContainer>()["test"]
testClassesDirs = test.output.classesDirs
classpath = test.runtimeClasspath

outputs.upToDateWhen { false }

maxParallelForks = 1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,10 @@ tasks.register<Test>("systemTest").configure {
group = "verification"
description = "Runs the System tests"

val test = project.extensions.getByType<SourceSetContainer>()["test"]
testClassesDirs = test.output.classesDirs
classpath = test.runtimeClasspath

outputs.upToDateWhen { false }

maxParallelForks = 1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,10 @@ tasks.register<Test>("systemTest").configure {
group = "verification"
description = "Runs the System tests"

val test = project.extensions.getByType<SourceSetContainer>()["test"]
testClassesDirs = test.output.classesDirs
classpath = test.runtimeClasspath

outputs.upToDateWhen { false }

maxParallelForks = 1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,10 @@ tasks.register<Test>("systemTest").configure {
group = "verification"
description = "Runs the System tests"

val test = project.extensions.getByType<SourceSetContainer>()["test"]
testClassesDirs = test.output.classesDirs
classpath = test.runtimeClasspath

outputs.upToDateWhen { false }

maxParallelForks = 1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,10 @@ tasks.register<Test>("systemTest").configure {
group = "verification"
description = "Runs the System tests"

val test = project.extensions.getByType<SourceSetContainer>()["test"]
testClassesDirs = test.output.classesDirs
classpath = test.runtimeClasspath

outputs.upToDateWhen { false }

maxParallelForks = 1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ java.targetCompatibility = JavaVersion.VERSION_17

repositories { mavenCentral() }

// Apollo 4.x requires coroutines 1.9.0+, override Spring Boot's managed version
extra["kotlin-coroutines.version"] = "1.9.0"

configure<JavaPluginExtension> {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
Expand Down Expand Up @@ -80,6 +83,10 @@ tasks.register<Test>("systemTest").configure {
group = "verification"
description = "Runs the System tests"

val test = project.extensions.getByType<SourceSetContainer>()["test"]
testClassesDirs = test.output.classesDirs
classpath = test.runtimeClasspath

outputs.upToDateWhen { false }

maxParallelForks = 1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ java.targetCompatibility = JavaVersion.VERSION_17

repositories { mavenCentral() }

// Apollo 4.x requires coroutines 1.9.0+, override Spring Boot's managed version
extra["kotlin-coroutines.version"] = "1.9.0"

configure<JavaPluginExtension> {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
Expand Down Expand Up @@ -114,6 +117,10 @@ tasks.register<Test>("systemTest").configure {
group = "verification"
description = "Runs the System tests"

val test = project.extensions.getByType<SourceSetContainer>()["test"]
testClassesDirs = test.output.classesDirs
classpath = test.runtimeClasspath

outputs.upToDateWhen { false }

maxParallelForks = 1
Expand Down
Loading
Loading