Skip to content

Commit 961ffe0

Browse files
runningcodeclaude
andcommitted
test(spring): Run each Spring Boot version in its own CI job
One job per Boot line doubled the matrix wall time, e.g. 12.5 minutes instead of about 6 for Boot 3. A single runner ran every version's suites, and the bare task name made Gradle configure every project to find it. The versions move to gradle/spring-boot-versions.json. build-logic reads it, and each workflow turns its line into one job per version, which runs that version's aggregate in both modules by project path. The version list stays in one place, and the check names match main's again. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 parent 8d9fab1 commit 961ffe0

13 files changed

Lines changed: 125 additions & 52 deletions

File tree

‎.cursor/rules/e2e_tests.mdc‎

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -64,14 +64,16 @@ it. Gradle runs the two in parallel.
6464

6565
## Running them
6666

67-
- The `springBootMatrix` block in each Spring module's build file runs its suites on every Spring
68-
Boot version in `SpringBootVersions` (build-logic), with a task per suite and version, e.g.
69-
`integrationTestWebfluxBoot3_2_12`. The suites and the SDK compile once, against the catalog's
70-
version; only the runtime classpath changes. `allIntegrationTestsBoot3_2_12` runs one version's
71-
suites, `allIntegrationTestsBoot3` every version's.
72-
- The `spring-boot-{2,3,4}-matrix.yml` workflows run `./gradlew allIntegrationTestsBoot<major>`,
73-
which picks up every module of the line. The suites aren't part of `check`, so a new suite only
74-
runs on CI once it's added to its module's `springBootMatrix` block.
67+
- The `springBootMatrix` block in each Spring module's build file runs its suites on every version
68+
of its Spring Boot line in `gradle/spring-boot-versions.json`, with a task per suite and version,
69+
e.g. `integrationTestWebfluxBoot3_2_12`. The suites and the SDK compile once, against the
70+
catalog's version; only the runtime classpath changes. `allIntegrationTestsBoot3_2_12` runs one
71+
version's suites, `allIntegrationTestsBoot3` every version's.
72+
- The `spring-boot-{2,3,4}-matrix.yml` workflows read the same file and run each version in its own
73+
job, e.g. `./gradlew :sentry-spring-jakarta:allIntegrationTestsBoot3_2_12
74+
:sentry-spring-boot-jakarta:allIntegrationTestsBoot3_2_12`. The suites aren't part of `check`, so
75+
a new suite only runs on CI once it's added to its module's `springBootMatrix` block, and a new
76+
module once it's added to its workflow.
7577
- Suite code may only use APIs that exist in the oldest version of its line. Compiled against a
7678
newer one, a missing API fails at runtime with `NoSuchMethodError` or `NoClassDefFoundError`.
7779

‎.github/workflows/spring-boot-2-matrix.yml‎

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,32 @@ concurrency:
1515
cancel-in-progress: true
1616

1717
jobs:
18+
versions:
19+
runs-on: ubuntu-latest
20+
name: Spring Boot 2.x versions
21+
outputs:
22+
versions: ${{ steps.versions.outputs.versions }}
23+
24+
steps:
25+
- name: Checkout Repo
26+
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
27+
with:
28+
sparse-checkout: gradle
29+
30+
- name: Read Spring Boot 2.x versions
31+
id: versions
32+
run: echo "versions=$(jq -c .boot2 gradle/spring-boot-versions.json)" >> "$GITHUB_OUTPUT"
33+
1834
spring-boot-2-matrix:
35+
needs: versions
1936
timeout-minutes: 45
2037
runs-on: ubuntu-latest
21-
name: Spring Boot 2.x
38+
strategy:
39+
fail-fast: false
40+
matrix:
41+
springboot-version: ${{ fromJSON(needs.versions.outputs.versions) }}
42+
43+
name: Spring Boot ${{ matrix.springboot-version }}
2244
env:
2345
GRADLE_ENCRYPTION_KEY: ${{ secrets.GRADLE_ENCRYPTION_KEY }}
2446

@@ -47,14 +69,18 @@ jobs:
4769
cache-encryption-key: ${{ secrets.GRADLE_ENCRYPTION_KEY }}
4870

4971
- name: Test integration suites
50-
# Runs every version even after one fails, as separate jobs per version would.
51-
run: ./gradlew allIntegrationTestsBoot2 --continue
72+
# Project paths, unlike a bare task name, keep Gradle from configuring every project.
73+
run: |
74+
task="allIntegrationTestsBoot${SPRINGBOOT_VERSION//./_}"
75+
./gradlew ":sentry-spring:$task" ":sentry-spring-boot:$task"
76+
env:
77+
SPRINGBOOT_VERSION: ${{ matrix.springboot-version }}
5278

5379
- name: Upload test results
5480
if: always()
5581
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7
5682
with:
57-
name: test-results-springboot-2
83+
name: test-results-springboot-2-${{ matrix.springboot-version }}
5884
path: |
5985
**/build/reports/*
6086
**/build/test-results/**/*.xml
@@ -63,7 +89,7 @@ jobs:
6389
uses: phoenix-actions/test-reporting@7317eea6e13c47348dd0bb318669485157c518d6 # pin@v16
6490
if: always()
6591
with:
66-
name: JUnit Spring Boot 2.x
92+
name: JUnit Spring Boot 2.x ${{ matrix.springboot-version }}
6793
path: |
6894
**/build/test-results/**/*.xml
6995
reporter: java-junit

‎.github/workflows/spring-boot-3-matrix.yml‎

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,32 @@ concurrency:
1515
cancel-in-progress: true
1616

1717
jobs:
18+
versions:
19+
runs-on: ubuntu-latest
20+
name: Spring Boot 3.x versions
21+
outputs:
22+
versions: ${{ steps.versions.outputs.versions }}
23+
24+
steps:
25+
- name: Checkout Repo
26+
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
27+
with:
28+
sparse-checkout: gradle
29+
30+
- name: Read Spring Boot 3.x versions
31+
id: versions
32+
run: echo "versions=$(jq -c .boot3 gradle/spring-boot-versions.json)" >> "$GITHUB_OUTPUT"
33+
1834
spring-boot-3-matrix:
35+
needs: versions
1936
timeout-minutes: 45
2037
runs-on: ubuntu-latest
21-
name: Spring Boot 3.x
38+
strategy:
39+
fail-fast: false
40+
matrix:
41+
springboot-version: ${{ fromJSON(needs.versions.outputs.versions) }}
42+
43+
name: Spring Boot ${{ matrix.springboot-version }}
2244
env:
2345
GRADLE_ENCRYPTION_KEY: ${{ secrets.GRADLE_ENCRYPTION_KEY }}
2446

@@ -47,14 +69,18 @@ jobs:
4769
cache-encryption-key: ${{ secrets.GRADLE_ENCRYPTION_KEY }}
4870

4971
- name: Test integration suites
50-
# Runs every version even after one fails, as separate jobs per version would.
51-
run: ./gradlew allIntegrationTestsBoot3 --continue
72+
# Project paths, unlike a bare task name, keep Gradle from configuring every project.
73+
run: |
74+
task="allIntegrationTestsBoot${SPRINGBOOT_VERSION//./_}"
75+
./gradlew ":sentry-spring-jakarta:$task" ":sentry-spring-boot-jakarta:$task"
76+
env:
77+
SPRINGBOOT_VERSION: ${{ matrix.springboot-version }}
5278

5379
- name: Upload test results
5480
if: always()
5581
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7
5682
with:
57-
name: test-results-springboot-3
83+
name: test-results-springboot-3-${{ matrix.springboot-version }}
5884
path: |
5985
**/build/reports/*
6086
**/build/test-results/**/*.xml
@@ -63,7 +89,7 @@ jobs:
6389
uses: phoenix-actions/test-reporting@7317eea6e13c47348dd0bb318669485157c518d6 # pin@v16
6490
if: always()
6591
with:
66-
name: JUnit Spring Boot 3.x
92+
name: JUnit Spring Boot 3.x ${{ matrix.springboot-version }}
6793
path: |
6894
**/build/test-results/**/*.xml
6995
reporter: java-junit

‎.github/workflows/spring-boot-4-matrix.yml‎

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,32 @@ concurrency:
1515
cancel-in-progress: true
1616

1717
jobs:
18+
versions:
19+
runs-on: ubuntu-latest
20+
name: Spring Boot 4.x versions
21+
outputs:
22+
versions: ${{ steps.versions.outputs.versions }}
23+
24+
steps:
25+
- name: Checkout Repo
26+
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
27+
with:
28+
sparse-checkout: gradle
29+
30+
- name: Read Spring Boot 4.x versions
31+
id: versions
32+
run: echo "versions=$(jq -c .boot4 gradle/spring-boot-versions.json)" >> "$GITHUB_OUTPUT"
33+
1834
spring-boot-4-matrix:
35+
needs: versions
1936
timeout-minutes: 45
2037
runs-on: ubuntu-latest
21-
name: Spring Boot 4.x
38+
strategy:
39+
fail-fast: false
40+
matrix:
41+
springboot-version: ${{ fromJSON(needs.versions.outputs.versions) }}
42+
43+
name: Spring Boot ${{ matrix.springboot-version }}
2244
env:
2345
GRADLE_ENCRYPTION_KEY: ${{ secrets.GRADLE_ENCRYPTION_KEY }}
2446

@@ -47,14 +69,18 @@ jobs:
4769
cache-encryption-key: ${{ secrets.GRADLE_ENCRYPTION_KEY }}
4870

4971
- name: Test integration suites
50-
# Runs every version even after one fails, as separate jobs per version would.
51-
run: ./gradlew allIntegrationTestsBoot4 --continue
72+
# Project paths, unlike a bare task name, keep Gradle from configuring every project.
73+
run: |
74+
task="allIntegrationTestsBoot${SPRINGBOOT_VERSION//./_}"
75+
./gradlew ":sentry-spring-7:$task" ":sentry-spring-boot-4:$task"
76+
env:
77+
SPRINGBOOT_VERSION: ${{ matrix.springboot-version }}
5278

5379
- name: Upload test results
5480
if: always()
5581
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7
5682
with:
57-
name: test-results-springboot-4
83+
name: test-results-springboot-4-${{ matrix.springboot-version }}
5884
path: |
5985
**/build/reports/*
6086
**/build/test-results/**/*.xml
@@ -63,7 +89,7 @@ jobs:
6389
uses: phoenix-actions/test-reporting@7317eea6e13c47348dd0bb318669485157c518d6 # pin@v16
6490
if: always()
6591
with:
66-
name: JUnit Spring Boot 4.x
92+
name: JUnit Spring Boot 4.x ${{ matrix.springboot-version }}
6793
path: |
6894
**/build/test-results/**/*.xml
6995
reporter: java-junit

‎build-logic/src/main/kotlin/io/sentry/gradle/SpringBootMatrixPlugin.kt‎

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package io.sentry.gradle
22

3+
import groovy.json.JsonSlurper
34
import javax.inject.Inject
45
import org.gradle.api.Plugin
56
import org.gradle.api.Project
@@ -25,14 +26,18 @@ abstract class SpringBootMatrixExtension @Inject constructor(private val project
2526
private var versions = emptyList<String>()
2627

2728
/**
28-
* Registers `allIntegrationTestsBoot<version>` for each of [versions], and
29-
* `allIntegrationTestsBoot<major>` for all of them, which CI runs from the root project for every
30-
* module of the line at once.
29+
* Registers `allIntegrationTestsBoot<version>` for each version of Spring Boot [line] in
30+
* `gradle/spring-boot-versions.json`, and `allIntegrationTestsBoot<line>` for all of them. The CI
31+
* workflows read the same file and run each version in its own job. A WAR module uses its Boot
32+
* module's line, because the Boot BOM decides its Spring version.
3133
*/
32-
fun versions(versions: List<String>) {
34+
fun versions(line: Int) {
35+
val file = project.layout.settingsDirectory.file("gradle/spring-boot-versions.json")
36+
val lines =
37+
JsonSlurper().parseText(project.providers.fileContents(file).asText.get()) as Map<*, *>
38+
val versions = (lines["boot$line"] as List<*>).map { it as String }
3339
this.versions = versions
34-
val major = versions.map { it.substringBefore('.') }.distinct().single()
35-
project.tasks.register("allIntegrationTestsBoot$major") {
40+
project.tasks.register("allIntegrationTestsBoot$line") {
3641
description = "Runs the integration suites on Spring Boot ${versions.joinToString()}."
3742
group = LifecycleBasePlugin.VERIFICATION_GROUP
3843
dependsOn(versions.map { aggregateName(it) })

‎build-logic/src/main/kotlin/io/sentry/gradle/SpringBootVersions.kt‎

Lines changed: 0 additions & 11 deletions
This file was deleted.

‎gradle/spring-boot-versions.json‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"boot2": ["2.7.0", "2.7.18"],
3+
"boot3": ["3.2.12", "3.3.13", "3.4.13", "3.5.13"],
4+
"boot4": ["4.0.0", "4.0.5", "4.1.0"]
5+
}

‎sentry-spring-7/build.gradle.kts‎

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import io.sentry.gradle.SpringBootVersions
21
import net.ltgt.gradle.errorprone.errorprone
32
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
43
import org.springframework.boot.gradle.plugin.SpringBootPlugin
@@ -147,6 +146,6 @@ testing {
147146

148147
// The suites on each Spring Boot 4 version the CI matrix tests.
149148
springBootMatrix {
150-
versions(SpringBootVersions.BOOT_4)
149+
versions(line = 4)
151150
test("integrationTest")
152151
}

‎sentry-spring-boot-4/build.gradle.kts‎

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import io.sentry.gradle.ChildJvmTestArguments
2-
import io.sentry.gradle.SpringBootVersions
32
import net.ltgt.gradle.errorprone.errorprone
43
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
54
import org.springframework.boot.gradle.plugin.SpringBootPlugin
@@ -432,7 +431,7 @@ listOf(
432431

433432
// The suites on each Spring Boot 4 version the CI matrix tests.
434433
springBootMatrix {
435-
versions(SpringBootVersions.BOOT_4)
434+
versions(line = 4)
436435
test("integrationTest")
437436
test("integrationTestLog4j2")
438437
test("integrationTestWebflux")

‎sentry-spring-boot-jakarta/build.gradle.kts‎

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import io.sentry.gradle.ChildJvmTestArguments
2-
import io.sentry.gradle.SpringBootVersions
32
import net.ltgt.gradle.errorprone.errorprone
43
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
54
import org.springframework.boot.gradle.plugin.SpringBootPlugin
@@ -371,7 +370,7 @@ listOf(
371370

372371
// The suites on each Spring Boot 3 version the CI matrix tests.
373372
springBootMatrix {
374-
versions(SpringBootVersions.BOOT_3)
373+
versions(line = 3)
375374
test("integrationTest")
376375
test("integrationTestLog4j2")
377376
test("integrationTestWebflux")

0 commit comments

Comments
 (0)