Skip to content

Commit 86b8bc8

Browse files
committed
chore(ci): Parallelize Spring Boot matrix by splitting build and test jobs (JAVA-510)
Prior to this commit, each Spring Boot matrix version ran all 5+ system tests sequentially in a single job (~45 min per version). A slow test blocked every test after it, and a build failure for one version had no clean failure isolation. What changed: - One build job per version compiles the SDK and samples, uploads JARs as a short-lived artifact - One test job per (version × sample config) cell downloads the artifact and runs a single test with --build false - A versions job is the single source of truth for the version list across all three workflows - The WAR servlet sample is extracted to its own job so it doesn't block or pad the main matrix - paths-ignore now correctly excludes all Android modules (not just sentry-android/) Result: The full SB2 matrix (7 versions × 5 configs = 35 jobs) runs in parallel. Wall-clock time drops from ~45 min × 7 sequential to ~15 min flat. Build failures are isolated per version; a single bad version no longer skips all others.
1 parent 184b991 commit 86b8bc8

3 files changed

Lines changed: 699 additions & 144 deletions

File tree

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

Lines changed: 233 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -5,23 +5,248 @@ on:
55
branches:
66
- main
77
paths-ignore:
8-
- '**/sentry-android/**'
8+
- '*android*/**'
9+
- 'sentry-compose/**'
10+
- 'sentry-samples/sentry-samples-android/**'
911
pull_request:
12+
paths-ignore:
13+
- '*android*/**'
14+
- 'sentry-compose/**'
15+
- 'sentry-samples/sentry-samples-android/**'
1016

1117
concurrency:
1218
group: ${{ github.workflow }}-${{ github.ref }}
1319
cancel-in-progress: true
1420

1521
jobs:
22+
spring-boot-2-versions:
23+
runs-on: ubuntu-latest
24+
outputs:
25+
matrix: ${{ steps.set.outputs.matrix }}
26+
steps:
27+
- id: set
28+
run: echo 'matrix=["2.1.0","2.2.5","2.4.13","2.5.15","2.6.15","2.7.0","2.7.18"]' >> $GITHUB_OUTPUT
29+
30+
# One Gradle build per matrix cell → artifact sdk-build-sb2-{version} (sentry-*/build/libs,
31+
# retention-days: 1, same workflow only). continue-on-error: without it, one failed version
32+
# skips the entire spring-boot-2-matrix job (needs is job-level). Triage: spring-boot-2-matrix.
33+
spring-boot-2-build:
34+
needs: [spring-boot-2-versions]
35+
continue-on-error: true
36+
timeout-minutes: 25
37+
runs-on: ubuntu-latest
38+
strategy:
39+
fail-fast: false
40+
matrix:
41+
springboot-version: ${{ fromJSON(needs.spring-boot-2-versions.outputs.matrix) }}
42+
43+
name: Build Spring Boot ${{ matrix.springboot-version }}
44+
env:
45+
GRADLE_ENCRYPTION_KEY: ${{ secrets.GRADLE_ENCRYPTION_KEY }}
46+
47+
steps:
48+
- name: Checkout Repo
49+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
50+
with:
51+
submodules: 'recursive'
52+
53+
- name: Set up Java
54+
uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
55+
with:
56+
distribution: 'temurin'
57+
java-version: '17'
58+
59+
# Workaround for https://github.com/gradle/actions/issues/21 to use config cache
60+
- name: Cache buildSrc
61+
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5
62+
with:
63+
path: buildSrc/build
64+
key: build-logic-${{ hashFiles('buildSrc/src/**', 'buildSrc/build.gradle.kts','buildSrc/settings.gradle.kts') }}
65+
66+
- name: Setup Gradle
67+
uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c
68+
with:
69+
cache-encryption-key: ${{ secrets.GRADLE_ENCRYPTION_KEY }}
70+
71+
- name: Update Spring Boot 2.x version
72+
run: |
73+
sed -i 's/^springboot2=.*/springboot2=${{ matrix.springboot-version }}/' gradle/libs.versions.toml
74+
echo "Updated Spring Boot 2.x version to ${{ matrix.springboot-version }}"
75+
76+
- name: Exclude android modules from build
77+
run: |
78+
sed -i \
79+
-e '/.*"sentry-android-ndk",/d' \
80+
-e '/.*"sentry-android",/d' \
81+
-e '/.*"sentry-compose",/d' \
82+
-e '/.*"sentry-android-core",/d' \
83+
-e '/.*"sentry-android-fragment",/d' \
84+
-e '/.*"sentry-android-navigation",/d' \
85+
-e '/.*"sentry-android-sqlite",/d' \
86+
-e '/.*"sentry-android-timber",/d' \
87+
-e '/.*"sentry-android-integration-tests:sentry-uitest-android-benchmark",/d' \
88+
-e '/.*"sentry-android-integration-tests:sentry-uitest-android",/d' \
89+
-e '/.*"sentry-android-integration-tests:sentry-uitest-android-critical",/d' \
90+
-e '/.*"sentry-android-integration-tests:test-app-sentry",/d' \
91+
-e '/.*"sentry-android-integration-tests:test-app-size",/d' \
92+
-e '/.*"sentry-samples:sentry-samples-android",/d' \
93+
-e '/.*"sentry-android-replay",/d' \
94+
settings.gradle.kts
95+
96+
- name: Exclude android modules from ignore list
97+
run: |
98+
sed -i \
99+
-e '/.*"sentry-uitest-android",/d' \
100+
-e '/.*"sentry-uitest-android-benchmark",/d' \
101+
-e '/.*"sentry-uitest-android-critical",/d' \
102+
-e '/.*"test-app-sentry",/d' \
103+
-e '/.*"test-app-size",/d' \
104+
-e '/.*"sentry-samples-android",/d' \
105+
build.gradle.kts
106+
107+
- name: Build SDK and samples
108+
run: |
109+
./gradlew assemble \
110+
:sentry-samples:sentry-samples-spring-boot:shadowJar \
111+
:sentry-samples:sentry-samples-spring-boot-webflux:shadowJar \
112+
:sentry-samples:sentry-samples-spring-boot-opentelemetry:shadowJar \
113+
:sentry-samples:sentry-samples-spring-boot-opentelemetry-noagent:shadowJar \
114+
--parallel
115+
116+
- name: Upload build artifact
117+
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
118+
with:
119+
name: sdk-build-sb2-${{ matrix.springboot-version }}
120+
path: |
121+
sentry-*/**/build/libs/*.jar
122+
retention-days: 1
123+
124+
# System tests per (springboot-version × sample config). Uses sdk-build-sb2-{version} at
125+
# workspace root (download path: .) and test/system-test-runner.py with --build false.
126+
# Failure triage: (1) spring-boot-2-build cell for that version, (2) Download build artifact,
127+
# (3) Run system test / spring-server.txt / test-results. Build job may be green while
128+
# version cells are red (continue-on-error); failed builds fail here, not as skipped jobs.
16129
spring-boot-2-matrix:
17-
timeout-minutes: 45
130+
timeout-minutes: 20
131+
runs-on: ubuntu-latest
132+
needs: [spring-boot-2-build, spring-boot-2-versions]
133+
strategy:
134+
fail-fast: false
135+
matrix:
136+
springboot-version: ${{ fromJSON(needs.spring-boot-2-versions.outputs.matrix) }}
137+
config:
138+
- { sample: "sentry-samples-spring-boot", agent: "false", auto_init: "true" }
139+
- { sample: "sentry-samples-spring-boot-webflux", agent: "false", auto_init: "true" }
140+
- { sample: "sentry-samples-spring-boot-opentelemetry", agent: "true", auto_init: "true" }
141+
- { sample: "sentry-samples-spring-boot-opentelemetry", agent: "true", auto_init: "false" }
142+
- { sample: "sentry-samples-spring-boot-opentelemetry-noagent", agent: "false", auto_init: "true" }
143+
144+
name: Spring Boot ${{ matrix.springboot-version }} - ${{ matrix.config.sample }} (agent=${{ matrix.config.agent }}, auto-init=${{ matrix.config.auto_init }})
145+
env:
146+
SENTRY_URL: http://127.0.0.1:8000
147+
GRADLE_ENCRYPTION_KEY: ${{ secrets.GRADLE_ENCRYPTION_KEY }}
148+
149+
steps:
150+
- name: Checkout Repo
151+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
152+
153+
- name: Set up Python
154+
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6
155+
with:
156+
python-version: '3.10.5'
157+
158+
- name: Install Python dependencies
159+
run: |
160+
python3 -m pip install --upgrade pip
161+
python3 -m pip install -r requirements.txt
162+
163+
- name: Set up Java
164+
uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
165+
with:
166+
distribution: 'temurin'
167+
java-version: '17'
168+
169+
- name: Setup Gradle
170+
uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c
171+
with:
172+
cache-encryption-key: ${{ secrets.GRADLE_ENCRYPTION_KEY }}
173+
174+
- name: Update Spring Boot 2.x version
175+
run: |
176+
sed -i 's/^springboot2=.*/springboot2=${{ matrix.springboot-version }}/' gradle/libs.versions.toml
177+
178+
- name: Download build artifact
179+
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
180+
with:
181+
name: sdk-build-sb2-${{ matrix.springboot-version }}
182+
path: .
183+
184+
# Guard against a confusing silent failure: if the agent JAR is absent,
185+
# ensure_agent_jar() in the test runner falls back to building it via Gradle
186+
# without the Spring Boot version pin or android exclusions applied — a slow,
187+
# misconfigured build that will likely time out. Fail fast and clearly instead.
188+
- name: Verify agent JAR present in artifact
189+
if: matrix.config.agent == 'true'
190+
run: |
191+
jar=$(find sentry-opentelemetry/sentry-opentelemetry-agent/build/libs/ \
192+
-name "*agent*.jar" \
193+
! -name "*dontuse*" ! -name "*sources*" ! -name "*javadoc*" \
194+
-print -quit 2>/dev/null)
195+
if [ -z "$jar" ]; then
196+
echo "ERROR: agent JAR not found in downloaded artifact."
197+
echo "Expected: sentry-opentelemetry/sentry-opentelemetry-agent/build/libs/*agent*.jar"
198+
echo "Check that the build job's artifact upload completed successfully."
199+
exit 1
200+
fi
201+
echo "Agent JAR found: $jar"
202+
203+
- name: Run system test
204+
run: |
205+
python3 test/system-test-runner.py test \
206+
--module "${{ matrix.config.sample }}" \
207+
--agent "${{ matrix.config.agent }}" \
208+
--auto-init "${{ matrix.config.auto_init }}" \
209+
--build "false"
210+
211+
- name: Upload test results
212+
if: always()
213+
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
214+
with:
215+
name: test-results-springboot-2-${{ matrix.springboot-version }}-${{ matrix.config.sample }}-agent${{ matrix.config.agent }}-init${{ matrix.config.auto_init }}
216+
path: |
217+
**/build/reports/*
218+
**/build/test-results/**/*.xml
219+
sentry-mock-server.txt
220+
spring-server.txt
221+
222+
- name: Test Report
223+
uses: phoenix-actions/test-reporting@7317eea6e13c47348dd0bb318669485157c518d6 # pin@v16
224+
if: always()
225+
with:
226+
name: JUnit Spring Boot 2.x ${{ matrix.springboot-version }} ${{ matrix.config.sample }}
227+
path: |
228+
**/build/test-results/**/*.xml
229+
reporter: java-junit
230+
output-to: step-summary
231+
fail-on-error: false
232+
233+
- name: Upload test results to Codecov
234+
if: ${{ !cancelled() }}
235+
uses: codecov/test-results-action@0fa95f0e1eeaafde2c782583b36b28ad0d8c77d3
236+
with:
237+
token: ${{ secrets.CODECOV_TOKEN }}
238+
file: '**/build/test-results/**/*.xml'
239+
240+
spring-boot-2-war:
241+
needs: [spring-boot-2-versions]
242+
timeout-minutes: 25
18243
runs-on: ubuntu-latest
19244
strategy:
20245
fail-fast: false
21246
matrix:
22-
springboot-version: [ '2.1.0', '2.2.5', '2.4.13', '2.5.15', '2.6.15', '2.7.0', '2.7.18' ]
247+
springboot-version: ${{ fromJSON(needs.spring-boot-2-versions.outputs.matrix) }}
23248

24-
name: Spring Boot ${{ matrix.springboot-version }}
249+
name: Spring Boot ${{ matrix.springboot-version }} - sentry-samples-spring (agent=false, auto-init=true)
25250
env:
26251
SENTRY_URL: http://127.0.0.1:8000
27252
GRADLE_ENCRYPTION_KEY: ${{ secrets.GRADLE_ENCRYPTION_KEY }}
@@ -100,59 +325,19 @@ jobs:
100325
run: |
101326
./gradlew assemble --parallel
102327
103-
- name: Test sentry-samples-spring-boot
104-
run: |
105-
python3 test/system-test-runner.py test \
106-
--module "sentry-samples-spring-boot" \
107-
--agent false \
108-
--auto-init "true" \
109-
--build "true"
110-
111-
- name: Test sentry-samples-spring-boot-webflux
112-
run: |
113-
python3 test/system-test-runner.py test \
114-
--module "sentry-samples-spring-boot-webflux" \
115-
--agent false \
116-
--auto-init "true" \
117-
--build "true"
118-
119-
- name: Test sentry-samples-spring-boot-opentelemetry agent init true
120-
run: |
121-
python3 test/system-test-runner.py test \
122-
--module "sentry-samples-spring-boot-opentelemetry" \
123-
--agent true \
124-
--auto-init "true" \
125-
--build "true"
126-
127-
- name: Test sentry-samples-spring-boot-opentelemetry agent init false
128-
run: |
129-
python3 test/system-test-runner.py test \
130-
--module "sentry-samples-spring-boot-opentelemetry" \
131-
--agent true \
132-
--auto-init "false" \
133-
--build "true"
134-
135-
- name: Test sentry-samples-spring-boot-opentelemetry-noagent
136-
run: |
137-
python3 test/system-test-runner.py test \
138-
--module "sentry-samples-spring-boot-opentelemetry-noagent" \
139-
--agent false \
140-
--auto-init "true" \
141-
--build "true"
142-
143-
- name: Test sentry-samples-spring
328+
- name: Run system test
144329
run: |
145330
python3 test/system-test-runner.py test \
146331
--module "sentry-samples-spring" \
147-
--agent false \
332+
--agent "false" \
148333
--auto-init "true" \
149334
--build "true"
150335
151336
- name: Upload test results
152337
if: always()
153338
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
154339
with:
155-
name: test-results-springboot-2-${{ matrix.springboot-version }}
340+
name: test-results-springboot-2-${{ matrix.springboot-version }}-sentry-samples-spring-agentfalse-inittrue
156341
path: |
157342
**/build/reports/*
158343
**/build/test-results/**/*.xml
@@ -163,7 +348,7 @@ jobs:
163348
uses: phoenix-actions/test-reporting@7317eea6e13c47348dd0bb318669485157c518d6 # pin@v16
164349
if: always()
165350
with:
166-
name: JUnit Spring Boot 2.x ${{ matrix.springboot-version }}
351+
name: JUnit Spring Boot 2.x ${{ matrix.springboot-version }} sentry-samples-spring
167352
path: |
168353
**/build/test-results/**/*.xml
169354
reporter: java-junit

0 commit comments

Comments
 (0)