Skip to content

[DNM] ci(spring-boot): Parallelize Spring Boot matrix builds (JAVA-510) #2759

[DNM] ci(spring-boot): Parallelize Spring Boot matrix builds (JAVA-510)

[DNM] ci(spring-boot): Parallelize Spring Boot matrix builds (JAVA-510) #2759

name: Spring Boot 2.x Matrix
on:
push:
branches:
- main
paths-ignore:
- '*android*/**'
- 'sentry-compose/**'
- 'sentry-samples/sentry-samples-android/**'
pull_request:
paths-ignore:
- '*android*/**'
- 'sentry-compose/**'
- 'sentry-samples/sentry-samples-android/**'
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
spring-boot-2-versions:
runs-on: ubuntu-latest
outputs:
matrix: ${{ steps.set.outputs.matrix }}
steps:
- id: set
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
# One Gradle build per matrix cell → artifact sdk-build-sb2-{version} (sentry-*/build/libs,
# retention-days: 1, same workflow only). continue-on-error: without it, one failed version
# skips the entire spring-boot-2-matrix job (needs is job-level). Triage: spring-boot-2-matrix.
spring-boot-2-build:
needs: [spring-boot-2-versions]
continue-on-error: true
timeout-minutes: 25
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
springboot-version: ${{ fromJSON(needs.spring-boot-2-versions.outputs.matrix) }}
name: Build Spring Boot ${{ matrix.springboot-version }}
env:
GRADLE_ENCRYPTION_KEY: ${{ secrets.GRADLE_ENCRYPTION_KEY }}
steps:
- name: Checkout Repo
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
submodules: 'recursive'
- name: Set up Java
uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
with:
distribution: 'temurin'
java-version: '17'
# Workaround for https://github.com/gradle/actions/issues/21 to use config cache
- name: Cache buildSrc
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5
with:
path: buildSrc/build
key: build-logic-${{ hashFiles('buildSrc/src/**', 'buildSrc/build.gradle.kts','buildSrc/settings.gradle.kts') }}
- name: Setup Gradle
uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c
with:
cache-encryption-key: ${{ secrets.GRADLE_ENCRYPTION_KEY }}
- name: Update Spring Boot 2.x version
run: |
sed -i 's/^springboot2=.*/springboot2=${{ matrix.springboot-version }}/' gradle/libs.versions.toml
echo "Updated Spring Boot 2.x version to ${{ matrix.springboot-version }}"
- name: Exclude android modules from build
run: |
sed -i \
-e '/.*"sentry-android-ndk",/d' \
-e '/.*"sentry-android",/d' \
-e '/.*"sentry-compose",/d' \
-e '/.*"sentry-android-core",/d' \
-e '/.*"sentry-android-fragment",/d' \
-e '/.*"sentry-android-navigation",/d' \
-e '/.*"sentry-android-sqlite",/d' \
-e '/.*"sentry-android-timber",/d' \
-e '/.*"sentry-android-integration-tests:sentry-uitest-android-benchmark",/d' \
-e '/.*"sentry-android-integration-tests:sentry-uitest-android",/d' \
-e '/.*"sentry-android-integration-tests:sentry-uitest-android-critical",/d' \
-e '/.*"sentry-android-integration-tests:test-app-sentry",/d' \
-e '/.*"sentry-android-integration-tests:test-app-size",/d' \
-e '/.*"sentry-samples:sentry-samples-android",/d' \
-e '/.*"sentry-android-replay",/d' \
settings.gradle.kts
- name: Exclude android modules from ignore list
run: |
sed -i \
-e '/.*"sentry-uitest-android",/d' \
-e '/.*"sentry-uitest-android-benchmark",/d' \
-e '/.*"sentry-uitest-android-critical",/d' \
-e '/.*"test-app-sentry",/d' \
-e '/.*"test-app-size",/d' \
-e '/.*"sentry-samples-android",/d' \
build.gradle.kts
- name: Build SDK and samples
run: |
./gradlew assemble \
:sentry-samples:sentry-samples-spring-boot:shadowJar \
:sentry-samples:sentry-samples-spring-boot-webflux:shadowJar \
:sentry-samples:sentry-samples-spring-boot-opentelemetry:shadowJar \
:sentry-samples:sentry-samples-spring-boot-opentelemetry-noagent:shadowJar \
--parallel
- name: Upload build artifact
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
with:
name: sdk-build-sb2-${{ matrix.springboot-version }}
path: |
sentry-*/**/build/libs/*.jar
retention-days: 1
# System tests per (springboot-version × sample config). Uses sdk-build-sb2-{version} at
# workspace root (download path: .) and test/system-test-runner.py with --build false.
# Failure triage: (1) spring-boot-2-build cell for that version, (2) Download build artifact,
# (3) Run system test / spring-server.txt / test-results. Build job may be green while
# version cells are red (continue-on-error); failed builds fail here, not as skipped jobs.
spring-boot-2-matrix:
timeout-minutes: 20
runs-on: ubuntu-latest
needs: [spring-boot-2-build, spring-boot-2-versions]
strategy:
fail-fast: false
matrix:
springboot-version: ${{ fromJSON(needs.spring-boot-2-versions.outputs.matrix) }}
config:
- { sample: "sentry-samples-spring-boot", agent: "false", auto_init: "true" }
- { sample: "sentry-samples-spring-boot-webflux", agent: "false", auto_init: "true" }
- { sample: "sentry-samples-spring-boot-opentelemetry", agent: "true", auto_init: "true" }
- { sample: "sentry-samples-spring-boot-opentelemetry", agent: "true", auto_init: "false" }
- { sample: "sentry-samples-spring-boot-opentelemetry-noagent", agent: "false", auto_init: "true" }
name: Spring Boot ${{ matrix.springboot-version }} - ${{ matrix.config.sample }} (agent=${{ matrix.config.agent }}, auto-init=${{ matrix.config.auto_init }})
env:
SENTRY_URL: http://127.0.0.1:8000
GRADLE_ENCRYPTION_KEY: ${{ secrets.GRADLE_ENCRYPTION_KEY }}
steps:
- name: Checkout Repo
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- name: Set up Python
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6
with:
python-version: '3.10.5'
- name: Install Python dependencies
run: |
python3 -m pip install --upgrade pip
python3 -m pip install -r requirements.txt
- name: Set up Java
uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
with:
distribution: 'temurin'
java-version: '17'
- name: Setup Gradle
uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c
with:
cache-encryption-key: ${{ secrets.GRADLE_ENCRYPTION_KEY }}
- name: Update Spring Boot 2.x version
run: |
sed -i 's/^springboot2=.*/springboot2=${{ matrix.springboot-version }}/' gradle/libs.versions.toml
- name: Download build artifact
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
with:
name: sdk-build-sb2-${{ matrix.springboot-version }}
path: .
# Guard against a confusing silent failure: if the agent JAR is absent,
# ensure_agent_jar() in the test runner falls back to building it via Gradle
# without the Spring Boot version pin or android exclusions applied — a slow,
# misconfigured build that will likely time out. Fail fast and clearly instead.
- name: Verify agent JAR present in artifact
if: matrix.config.agent == 'true'
run: |
jar=$(find sentry-opentelemetry/sentry-opentelemetry-agent/build/libs/ \
-name "*agent*.jar" \
! -name "*dontuse*" ! -name "*sources*" ! -name "*javadoc*" \
-print -quit 2>/dev/null)
if [ -z "$jar" ]; then
echo "ERROR: agent JAR not found in downloaded artifact."
echo "Expected: sentry-opentelemetry/sentry-opentelemetry-agent/build/libs/*agent*.jar"
echo "Check that the build job's artifact upload completed successfully."
exit 1
fi
echo "Agent JAR found: $jar"
- name: Run system test
run: |
python3 test/system-test-runner.py test \
--module "${{ matrix.config.sample }}" \
--agent "${{ matrix.config.agent }}" \
--auto-init "${{ matrix.config.auto_init }}" \
--build "false"
- name: Upload test results
if: always()
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
with:
name: test-results-springboot-2-${{ matrix.springboot-version }}-${{ matrix.config.sample }}-agent${{ matrix.config.agent }}-init${{ matrix.config.auto_init }}
path: |
**/build/reports/*
**/build/test-results/**/*.xml
sentry-mock-server.txt
spring-server.txt
- name: Test Report
uses: phoenix-actions/test-reporting@7317eea6e13c47348dd0bb318669485157c518d6 # pin@v16
if: always()
with:
name: JUnit Spring Boot 2.x ${{ matrix.springboot-version }} ${{ matrix.config.sample }}
path: |
**/build/test-results/**/*.xml
reporter: java-junit
output-to: step-summary
fail-on-error: false
- name: Upload test results to Codecov
if: ${{ !cancelled() }}
uses: codecov/test-results-action@0fa95f0e1eeaafde2c782583b36b28ad0d8c77d3
with:
token: ${{ secrets.CODECOV_TOKEN }}
file: '**/build/test-results/**/*.xml'
spring-boot-2-war:
needs: [spring-boot-2-versions]
timeout-minutes: 25
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
springboot-version: ${{ fromJSON(needs.spring-boot-2-versions.outputs.matrix) }}
name: Spring Boot ${{ matrix.springboot-version }} - sentry-samples-spring (agent=false, auto-init=true)
env:
SENTRY_URL: http://127.0.0.1:8000
GRADLE_ENCRYPTION_KEY: ${{ secrets.GRADLE_ENCRYPTION_KEY }}
steps:
- name: Checkout Repo
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
submodules: 'recursive'
- name: Set up Python
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6
with:
python-version: '3.10.5'
- name: Install Python dependencies
run: |
python3 -m pip install --upgrade pip
python3 -m pip install -r requirements.txt
- name: Set up Java
uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
with:
distribution: 'temurin'
java-version: '17'
# Workaround for https://github.com/gradle/actions/issues/21 to use config cache
- name: Cache buildSrc
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5
with:
path: buildSrc/build
key: build-logic-${{ hashFiles('buildSrc/src/**', 'buildSrc/build.gradle.kts','buildSrc/settings.gradle.kts') }}
- name: Setup Gradle
uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c
with:
cache-encryption-key: ${{ secrets.GRADLE_ENCRYPTION_KEY }}
- name: Update Spring Boot 2.x version
run: |
sed -i 's/^springboot2=.*/springboot2=${{ matrix.springboot-version }}/' gradle/libs.versions.toml
echo "Updated Spring Boot 2.x version to ${{ matrix.springboot-version }}"
- name: Exclude android modules from build
run: |
sed -i \
-e '/.*"sentry-android-ndk",/d' \
-e '/.*"sentry-android",/d' \
-e '/.*"sentry-compose",/d' \
-e '/.*"sentry-android-core",/d' \
-e '/.*"sentry-android-fragment",/d' \
-e '/.*"sentry-android-navigation",/d' \
-e '/.*"sentry-android-sqlite",/d' \
-e '/.*"sentry-android-timber",/d' \
-e '/.*"sentry-android-integration-tests:sentry-uitest-android-benchmark",/d' \
-e '/.*"sentry-android-integration-tests:sentry-uitest-android",/d' \
-e '/.*"sentry-android-integration-tests:sentry-uitest-android-critical",/d' \
-e '/.*"sentry-android-integration-tests:test-app-sentry",/d' \
-e '/.*"sentry-android-integration-tests:test-app-size",/d' \
-e '/.*"sentry-samples:sentry-samples-android",/d' \
-e '/.*"sentry-android-replay",/d' \
settings.gradle.kts
- name: Exclude android modules from ignore list
run: |
sed -i \
-e '/.*"sentry-uitest-android",/d' \
-e '/.*"sentry-uitest-android-benchmark",/d' \
-e '/.*"sentry-uitest-android-critical",/d' \
-e '/.*"test-app-sentry",/d' \
-e '/.*"test-app-size",/d' \
-e '/.*"sentry-samples-android",/d' \
build.gradle.kts
- name: Build SDK
run: |
./gradlew assemble --parallel
- name: Run system test
run: |
python3 test/system-test-runner.py test \
--module "sentry-samples-spring" \
--agent "false" \
--auto-init "true" \
--build "true"
- name: Upload test results
if: always()
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
with:
name: test-results-springboot-2-${{ matrix.springboot-version }}-sentry-samples-spring-agentfalse-inittrue
path: |
**/build/reports/*
**/build/test-results/**/*.xml
sentry-mock-server.txt
spring-server.txt
- name: Test Report
uses: phoenix-actions/test-reporting@7317eea6e13c47348dd0bb318669485157c518d6 # pin@v16
if: always()
with:
name: JUnit Spring Boot 2.x ${{ matrix.springboot-version }} sentry-samples-spring
path: |
**/build/test-results/**/*.xml
reporter: java-junit
output-to: step-summary
fail-on-error: false
- name: Upload test results to Codecov
if: ${{ !cancelled() }}
uses: codecov/test-results-action@0fa95f0e1eeaafde2c782583b36b28ad0d8c77d3
with:
token: ${{ secrets.CODECOV_TOKEN }}
file: '**/build/test-results/**/*.xml'