From e35594f946835dcb7ac5dd32693cda18cb2244f8 Mon Sep 17 00:00:00 2001 From: Ludy Date: Wed, 24 Jun 2026 10:34:59 +0200 Subject: [PATCH] chore(build): centralize Gradle dependency version management (#6499) # Description of Changes This change centralizes several dependency version declarations into shared Gradle version properties and updates module build files to reference those properties instead of hardcoded version strings. ### What was changed - Added centralized version properties in the root `build.gradle` for: - commons-io - commons-lang3 - rhino - okhttp BOM - gson - guava - bucket4j - archunit - batik - jpdfium - JWT - AWS SDK - Testcontainers - Replaced hardcoded dependency versions across multiple modules with shared version variables. - Updated `resolutionStrategy.force` declarations to use centralized version properties. - Updated dependency constraints and BOM references to use shared version variables. - Removed module-specific duplicate version declarations from `app/proprietary/build.gradle`. - Standardized dependency declarations across `common`, `core`, `proprietary`, and `saas` modules. ## Why the change was made - Reduce duplication of dependency version definitions. - Simplify future dependency upgrades and maintenance. - Ensure consistent dependency versions across all modules. - Improve readability and reduce the risk of version drift between subprojects. - Make security-related dependency overrides easier to maintain from a single location. --- ## Checklist ### General - [ ] I have read the [Contribution Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md) - [ ] I have read the [Stirling-PDF Developer Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md) (if applicable) - [ ] I have read the [How to add new languages to Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md) (if applicable) - [ ] I have performed a self-review of my own code - [ ] My changes generate no new warnings ### Documentation - [ ] I have updated relevant docs on [Stirling-PDF's doc repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/) (if functionality has heavily changed) - [ ] I have read the section [Add New Translation Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags) (for new translation tags only) ### Translations (if applicable) - [ ] I ran [`scripts/counter_translation.py`](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/docs/counter_translation.md) ### UI Changes (if applicable) - [ ] Screenshots or videos demonstrating the UI changes are attached (e.g., as comments or direct attachments in the PR) ### Testing (if applicable) - [ ] I have run `task check` to verify linters, typechecks, and tests pass - [ ] I have tested my changes locally. Refer to the [Testing Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md#7-testing) for more details. --- app/common/build.gradle | 12 ++++++------ app/core/build.gradle | 13 ++++++------- app/proprietary/build.gradle | 32 +++++++++++++------------------- app/saas/build.gradle | 2 +- build.gradle | 30 +++++++++++++++++++++--------- 5 files changed, 47 insertions(+), 42 deletions(-) diff --git a/app/common/build.gradle b/app/common/build.gradle index 170f964af4..516edd4897 100644 --- a/app/common/build.gradle +++ b/app/common/build.gradle @@ -29,13 +29,13 @@ spotless { } } dependencies { - api 'com.google.guava:guava:33.6.0-jre' + api "com.google.guava:guava:${guavaVersion}" api 'org.springframework.boot:spring-boot-starter-webmvc' api 'org.springframework.boot:spring-boot-starter-aspectj' api 'com.googlecode.owasp-java-html-sanitizer:owasp-java-html-sanitizer:20260313.1' api 'com.fathzer:javaluator:3.0.6' api 'com.posthog.java:posthog:1.2.0' - api 'org.apache.commons:commons-lang3:3.20.0' + api "org.apache.commons:commons-lang3:${commonsLang3}" api 'com.drewnoakes:metadata-extractor:2.20.0' // Image metadata extractor api 'com.vladsch.flexmark:flexmark-html2md-converter:0.64.8' api "org.apache.pdfbox:pdfbox:$pdfboxVersion" @@ -60,7 +60,7 @@ dependencies { exclude group: 'com.google.code.gson', module: 'gson' } - api 'com.stirling:jpdfium:1.0.2' + api "com.stirling:jpdfium:${jpdfiumVersion}" // -PjpdfiumPlatforms=all| def jpdfiumPlatformsProp = (project.findProperty('jpdfiumPlatforms') ?: 'all').toString().trim() @@ -75,12 +75,12 @@ dependencies { } logger.lifecycle("JPDFium native platforms: ${jpdfiumPlatforms.join(', ')}") jpdfiumPlatforms.each { platform -> - runtimeOnly "com.stirling:jpdfium-natives-${platform}:1.0.2" + runtimeOnly "com.stirling:jpdfium-natives-${platform}:${jpdfiumVersion}" } // Bucket4j (local in-process token bucket for RateLimitStore default impl) - implementation 'com.bucket4j:bucket4j_jdk17-core:8.19.0' + implementation "com.bucket4j:bucket4j_jdk17-core:${bucket4jVersion}" // ArchUnit: enforces module dependency direction (see ArchitectureTest) - testImplementation 'com.tngtech.archunit:archunit-junit5:1.4.2' + testImplementation "com.tngtech.archunit:archunit-junit5:${archunitVersion}" } diff --git a/app/core/build.gradle b/app/core/build.gradle index 21acdb36e0..d77fbdd438 100644 --- a/app/core/build.gradle +++ b/app/core/build.gradle @@ -67,7 +67,7 @@ dependencies { exclude group: 'com.fasterxml.jackson.jaxrs' exclude group: 'com.fasterxml.jackson.module', module: 'jackson-module-jaxb-annotations' } - implementation 'commons-io:commons-io:2.22.0' + implementation "commons-io:commons-io:$commonsIoVersion" implementation "org.bouncycastle:bcprov-jdk18on:$bouncycastleVersion" implementation "org.bouncycastle:bcpkix-jdk18on:$bouncycastleVersion" implementation 'io.micrometer:micrometer-core' @@ -81,25 +81,24 @@ dependencies { implementation 'org.verapdf:validation-model:1.28.2' // CVE-2025-66453: Explicit rhino 1.7.15 to override verapdf's 1.7.13 - implementation 'org.mozilla:rhino:1.9.1' + implementation "org.mozilla:rhino:${rhinoVersion}" // veraPDF still uses javax.xml.bind, not the new jakarta namespace implementation 'javax.xml.bind:jaxb-api:2.3.1' implementation 'com.sun.xml.bind:jaxb-impl:2.3.9' implementation 'com.sun.xml.bind:jaxb-core:4.0.7' - implementation 'org.apache.poi:poi-ooxml:5.5.1' - // CVE-2022-25647: Explicit gson 2.13.2 to prevent unsafe deserialization (tabula would pull 2.8.7) - implementation 'com.google.code.gson:gson:2.13.2' + // CVE-2022-25647: Explicit gson to prevent unsafe deserialization (tabula would pull 2.8.7) + implementation "com.google.code.gson:gson:${gsonVersion}" implementation 'org.apache.pdfbox:jbig2-imageio:3.0.4' implementation 'com.opencsv:opencsv:5.12.0' // https://mvnrepository.com/artifact/com.opencsv/opencsv implementation 'org.apache.poi:poi-ooxml:5.5.1' // Batik only bridge module needed (transitively pulls anim, gvt, util, css, dom, svg-dom) // Replaces batik-all which included unused codec, svggen, transcoder, script modules - implementation 'org.apache.xmlgraphics:batik-bridge:1.19' + implementation "org.apache.xmlgraphics:batik-bridge:${batikVersion}" // Required by TwelveMonkeys imageio-batik SPI (SVGImageReaderSpi) during ImageIO init - runtimeOnly 'org.apache.xmlgraphics:batik-transcoder:1.19' + runtimeOnly "org.apache.xmlgraphics:batik-transcoder:${batikVersion}" // PDFBox Graphics2D bridge for Batik SVG to PDF conversion implementation 'de.rototor.pdfbox:graphics2d:3.0.5' diff --git a/app/proprietary/build.gradle b/app/proprietary/build.gradle index 821def1fec..7fb12de5ce 100644 --- a/app/proprietary/build.gradle +++ b/app/proprietary/build.gradle @@ -3,12 +3,6 @@ repositories { maven { url = "https://build.shibboleth.net/maven/releases" } } -ext { - jwtVersion = '0.13.0' - awsSdkVersion = '2.44.12' - testcontainersMinioVersion = '1.21.4' -} - bootRun { enabled = false } @@ -41,7 +35,7 @@ spotless { } dependencies { implementation project(':common') - api 'com.google.guava:guava:33.6.0-jre' + api "com.google.guava:guava:${guavaVersion}" api 'org.springframework:spring-jdbc' api 'org.springframework:spring-webmvc' @@ -61,37 +55,37 @@ dependencies { api 'com.github.ben-manes.caffeine:caffeine' implementation 'org.springframework.boot:spring-boot-starter-data-redis' api 'io.swagger.core.v3:swagger-core-jakarta:2.2.46' - implementation 'com.bucket4j:bucket4j_jdk17-core:8.19.0' + implementation "com.bucket4j:bucket4j_jdk17-core:${bucket4jVersion}" // Lettuce-backed Bucket4j ProxyManager used by ValkeyRateLimitStore for cluster-wide // token-bucket rate limiting (parity with in-process Bucket4j semantics; no fixed-window // boundary doubling). - implementation 'com.bucket4j:bucket4j_jdk17-lettuce:8.19.0' + implementation "com.bucket4j:bucket4j_jdk17-lettuce:${bucket4jVersion}" // https://mvnrepository.com/artifact/com.bucket4j/bucket4j_jdk17 implementation "org.bouncycastle:bcprov-jdk18on:$bouncycastleVersion" - implementation 'com.google.code.gson:gson:2.13.2' + implementation "com.google.code.gson:gson:${gsonVersion}" api 'io.micrometer:micrometer-registry-prometheus' - api "io.jsonwebtoken:jjwt-api:$jwtVersion" - runtimeOnly "io.jsonwebtoken:jjwt-impl:$jwtVersion" - runtimeOnly "io.jsonwebtoken:jjwt-jackson:$jwtVersion" + api "io.jsonwebtoken:jjwt-api:${jwtVersion}" + runtimeOnly "io.jsonwebtoken:jjwt-impl:${jwtVersion}" + runtimeOnly "io.jsonwebtoken:jjwt-jackson:${jwtVersion}" runtimeOnly 'com.h2database:h2:2.3.232' // Don't upgrade h2database - file format incompatible with 2.4.x, would break existing user databases runtimeOnly 'org.postgresql:postgresql:42.7.11' implementation('com.coveo:saml-client:5.0.0') { exclude group: 'org.opensaml', module: 'opensaml-core' } - implementation "software.amazon.awssdk:s3:$awsSdkVersion" - implementation "software.amazon.awssdk:url-connection-client:$awsSdkVersion" + implementation "software.amazon.awssdk:s3:${awsSdkVersion}" + implementation "software.amazon.awssdk:url-connection-client:${awsSdkVersion}" // Testcontainers: real MinIO/LocalStack (S3) and Valkey for integration tests in CI without // manually-started instances. Tests skip cleanly when Docker is unavailable. - testImplementation "org.testcontainers:testcontainers:$testcontainersMinioVersion" - testImplementation "org.testcontainers:minio:$testcontainersMinioVersion" - testImplementation "org.testcontainers:localstack:$testcontainersMinioVersion" - testImplementation "org.testcontainers:junit-jupiter:$testcontainersMinioVersion" + testImplementation "org.testcontainers:testcontainers:${testcontainersMinioVersion}" + testImplementation "org.testcontainers:minio:${testcontainersMinioVersion}" + testImplementation "org.testcontainers:localstack:${testcontainersMinioVersion}" + testImplementation "org.testcontainers:junit-jupiter:${testcontainersMinioVersion}" } tasks.register('prepareKotlinBuildScriptModel') {} diff --git a/app/saas/build.gradle b/app/saas/build.gradle index 560ad58f5f..d6ae305def 100644 --- a/app/saas/build.gradle +++ b/app/saas/build.gradle @@ -41,5 +41,5 @@ dependencies { api 'org.flywaydb:flyway-core' runtimeOnly 'org.flywaydb:flyway-database-postgresql' - testImplementation 'com.tngtech.archunit:archunit-junit5:1.4.2' + testImplementation "com.tngtech.archunit:archunit-junit5:${archunitVersion}" } diff --git a/build.gradle b/build.gradle index 6b324598f3..3b91ca502c 100644 --- a/build.gradle +++ b/build.gradle @@ -30,6 +30,19 @@ ext { commonmarkVersion = "0.28.0" googleJavaFormatVersion = "1.28.0" logback = "1.5.32" + commonsIoVersion = "2.22.0" + commonsLang3 = "3.20.0" + rhinoVersion = "1.9.1" + okhttpBomVersion = "5.3.2" + gsonVersion = "2.14.0" + guavaVersion = "33.6.0-jre" + bucket4jVersion = "8.19.0" + archunitVersion = "1.4.2" + batikVersion = "1.19" + jpdfiumVersion = "1.0.2" + jwtVersion = "0.13.0" + awsSdkVersion = "2.44.12" + testcontainersMinioVersion = "1.21.4" // junit-platform-launcher version managed by Spring Boot BOM modernJavaVersion = 25 } @@ -203,12 +216,12 @@ subprojects { // - CVE-2022-25647: gson 2.8.9+ (explicit dependency overrides tabula 2.8.7) // - CVE-2025-66453: rhino 1.7.15 (explicit dependency overrides verapdf 1.7.13) // Fallback strategy force declarations for additional safety: - resolutionStrategy.force 'com.google.code.gson:gson:2.13.2' - resolutionStrategy.force 'org.mozilla:rhino:1.9.1' + resolutionStrategy.force "com.google.code.gson:gson:${gsonVersion}" + resolutionStrategy.force "org.mozilla:rhino:${rhinoVersion}" // CVE-2025-48924: commons-lang3 3.20.0 DoS prevention - resolutionStrategy.force 'org.apache.commons:commons-lang3:3.20.0' - // CVE-2024-47554: commons-io 2.21.0 DoS prevention - resolutionStrategy.force 'commons-io:commons-io:2.21.0' + resolutionStrategy.force "org.apache.commons:commons-lang3:${commonsLang3}" + // CVE-2024-47554: commons-io DoS prevention + resolutionStrategy.force "commons-io:commons-io:${commonsIoVersion}" // Keep BouncyCastle modules aligned to avoid runtime linkage errors resolutionStrategy.force "org.bouncycastle:bcprov-jdk18on:${bouncycastleVersion}" resolutionStrategy.force "org.bouncycastle:bcpkix-jdk18on:${bouncycastleVersion}" @@ -221,7 +234,7 @@ subprojects { } dependencies { // Override BOM-managed commons-lang3 for CVE-2025-48924 fix - dependency 'org.apache.commons:commons-lang3:3.20.0' + dependency "org.apache.commons:commons-lang3:$commonsLang3" } } @@ -243,7 +256,7 @@ subprojects { testRuntimeOnly 'org.mockito:mockito-inline:5.2.0' testRuntimeOnly "org.junit.platform:junit-platform-launcher" - testImplementation platform("com.squareup.okhttp3:okhttp-bom:5.3.2") + testImplementation platform("com.squareup.okhttp3:okhttp-bom:${okhttpBomVersion}") testImplementation "com.squareup.okhttp3:mockwebserver" } @@ -599,7 +612,7 @@ dependencies { testImplementation 'org.springframework.boot:spring-boot-starter-test' testRuntimeOnly "org.junit.platform:junit-platform-launcher" - testImplementation platform("com.squareup.okhttp3:okhttp-bom:5.3.2") + testImplementation platform("com.squareup.okhttp3:okhttp-bom:${okhttpBomVersion}") testImplementation "com.squareup.okhttp3:mockwebserver" } @@ -670,7 +683,6 @@ tasks.register('buildRestartHelper', Jar) { } } - tasks.withType(Test).configureEach { // maxParallelForks: parallelise JUnit across cores // Half of available CPUs is a safe default; bump if your tests are I/O-bound.