mirror of
https://github.com/Stirling-Tools/Stirling-PDF.git
synced 2026-09-03 05:10:16 +03:00
Bumps `logback` from 1.5.32 to 1.6.1. Updates `ch.qos.logback:logback-core` from 1.5.32 to 1.6.1 <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/qos-ch/logback/releases">ch.qos.logback:logback-core's releases</a>.</em></p> <blockquote> <h2>Logback 1.6.1</h2> <p><strong>2026-07-28 Release of logback version 1.6.1</strong></p> <p>• In TimeBasedRollingPolicy, when the file option is set, the intermediate file renamed before asynchronous compression now receives the target archive name without the compression suffix (e.g. <code>.gz</code>, <code>.zip</code>, <code>.xz</code>). Previously it used a nanotime-based <code>.tmp</code> suffix. This makes the file easier to identify if compression fails during rollover. (See also the following paragraph.)</p> <p>• On GZ, ZIP, or XZ compression failure, the original (uncompressed) log file is no longer deleted. Compression strategies now delete the source file only after successful compression and emit a warning that the original was left intact.</p> <p>• ConsoleAppender with <!-- raw HTML omitted --> now probes JLine's org.jline.jansi.AnsiConsole first and falls back to the legacy FuseSource org.fusesource.jansi.AnsiConsole class. This keeps ANSI coloring working after Jansi moved under the JLine project. The optional org.jline:jansi-core artifact is declared as a dependency alongside the existing FuseSource jansi dependency. A preferredJansiClassName property was added for tests. This issue was reported in <a href="https://redirect.github.com/qos-ch/logback/issues/1043">issues/1043</a> by <a href="https://github.com/seonwooj0810">seonwoo_jung</a> who also provided the relevant PR.</p> <p>• LayoutWrappingEncoder now reports an error at start() when no layout is set and guards encode() against a null layout. Previously, a missing layout (for example after an ignored <!-- raw HTML omitted -->/<!-- raw HTML omitted -->/<!-- raw HTML omitted --> branch) allowed the encoder to start and then fail with a NullPointerException on every event, resulting in silent log loss. This issue was reported in <a href="https://redirect.github.com/qos-ch/logback/issues/1046">issues/1046</a> by <a href="https://github.com/seonwooj0810">seonwoo_jung</a> who also provided the relevant PR.</p> <p>• FileCollisionAnalyser now detects file collisions involving nested appenders of SiftingAppender. When the nested file or fileNamePattern does not textually reference the discriminator key (e.g. ${userId}), a warning is issued at configuration time naming the appender, the key, and the shared target. This closes a gap where statically declared file appenders were checked but sifted nested appenders were not. This enhancement was contributed in [PR <a href="https://redirect.github.com/qos-ch/logback/issues/1041">#1041</a>](<a href="https://redirect.github.com/qos-ch/logback/issues/1041">qos-ch/logback#1041</a>) by <a href="https://github.com/seonwooj0810">seonwoo_jung</a>.</p> <p>• More defensive handling in SyslogOutputStream and SyslogAppenderBase: the close() method now ensures that resources are closed, writes and flushes check that the underlying resources are in a valid state and fallback to no-op otherwise.</p> <p>• A bit-wise identical binary of this version can be reproduced by building from source code at commit 57759f433000a133088ef0441038963134437fbd associated with the tag v_1.6.1. The release was built using Java "21" 2023-10-17 LTS build 21.0.1.+12-LTS-29 under Linux Debian 11.6.</p> <p>• See <a href="https://logback.qos.ch/news.html#1.6.1">https://logback.qos.ch/news.html#1.6.1</a> for the original text.</p> <h2>Logback 1.6.0</h2> <p><strong>2026-07-23 Release of logback version 1.6.0</strong></p> <p>• Removed certain deprecated variables, methods, and classes. For the list of removed members see <a href="https://logback.qos.ch/notes/release_1.6.0.txt">release_1.6.0.txt.</a></p> <p>• In <code>AsyncAppenderBase</code>, the <code>put(ILoggingEvent)</code> method now has the protected modifier to allow access from derived classes. This change was requested by Thomas Skjølberg in <a href="https://redirect.github.com/qos-ch/logback/pull/1053">pr#1053</a>.</p> <p>• Bump SLF4J dependency to version 2.0.18.</p> <p>• <strong>See also the overview of the <a href="https://logback.qos.ch/news.html#latest_stable">1.6.x series</a>.</strong></p> <p>• A bit-wise identical binary of this version can be reproduced by building from source code at commit b07adf36019b51a10f824fdd94009985c587b1d3 associated with the tag v_1.6.0. The release was built using Java "21" 2023-10-17 LTS build 21.0.1.+12-LTS-29 under Linux Debian 11.6.</p> <h2>Logback 1.5.38</h2> <p><strong>2026-07-09 Release of logback version 1.5.38</strong></p> <p>• In <code>HardenedObjectInputStream</code>, fixed a typo preventing <code>Throwable</code> objects from being white-filtered. This issue was reported in [PR <a href="https://redirect.github.com/qos-ch/logback/issues/1045">#1045</a>](<a href="https://redirect.github.com/qos-ch/logback/pull/1045">qos-ch/logback#1045</a>) by <a href="https://github.com/t0rchwo0d">t0rchwo0d</a>.</p> <p>• A bitwise identical binary of this version can be reproduced by building from source code at commit d04984a41fce42977466f45a2f076f0ee5cc4207 associated with the tag v_1.5.38. Release built using Java "21" 2023-10-17 LTS build 21.0.1.+12-LTS-29 under Linux Debian 11.6.</p> <h2>Logback 1.5.37</h2> <p><strong>2026-06-26 Release of logback version 1.5.37</strong></p> <ol> <li>• Given the numerous vulnerabilities related to conditional configuration processing based on the evaluation of Java expressions using the Janino library, support for such expressions has been removed. Users are offered the an <a href="https://logback.qos.ch/translator/services/conditionalConfigMigrator.html">online migration service</a> or the <code><condition></code> element introduced in version 1.5.20. See the <a href="https://logback.qos.ch/manual/configuration.html#conditional">relevant documentation</a> for more details.</li> </ol> <p>• A bitwise identical binary of this version can be reproduced by building from source code at commit c1df7f522e648eec7b4ef6a12c8758fec0f00048 associated with the tag v_1.5.37. Release built using Java "21" 2023-10-17 LTS build 21.0.1.+12-LTS-29 under Linux Debian 11.6.</p> <h2>Logback 1.5.36</h2> <p><strong>2026-06-25 Release of logback version 1.5.36</strong></p> <p>• The 'condition' attribute in <code><if></code> elements now reject certain references that are associated with ACE attacks. This issue was reported by "yulate" (<a href="mailto:yulate531@gmail.com.com">yulate531@gmail.com.com</a>) and registered as <a href="https://www.cve.org/cverecord?id=CVE-2026-13006">CVE-2026-13006</a>. <strong>Please note that version 1.5.37 provides the full fix to this vulnerability.</strong></p> <!-- raw HTML omitted --> </blockquote> <p>... (truncated)</p> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/qos-ch/logback/commit/57759f433000a133088ef0441038963134437fbd"><code>57759f4</code></a> prepare release 1.6.1</li> <li><a href="https://github.com/qos-ch/logback/commit/175f99f2093ae07f4c8d44f93b800f65b03a6e19"><code>175f99f</code></a> fix imports</li> <li><a href="https://github.com/qos-ch/logback/commit/4b8773ed127fdc62b85a7c7ddaef10f25830788c"><code>4b8773e</code></a> add compressionFailureLeavesOriginalFileIntact test for XZ compression</li> <li><a href="https://github.com/qos-ch/logback/commit/cafaf1115fd20be19b2f7a4a09184446e8bbc04d"><code>cafaf11</code></a> do not delete original file if compression fails</li> <li><a href="https://github.com/qos-ch/logback/commit/ee50125b293f5a731543de9f9f5fb72756a43464"><code>ee50125</code></a> let the temporary file before compression be target file without the .gz or ....</li> <li><a href="https://github.com/qos-ch/logback/commit/5626acc301f4039537a6c668f0f2d51989472785"><code>5626acc</code></a> minor refactoring</li> <li><a href="https://github.com/qos-ch/logback/commit/d97da4fbc0de00ca901ef78d91b9fc1850ae803f"><code>d97da4f</code></a> minor refactoring</li> <li><a href="https://github.com/qos-ch/logback/commit/159c045d8f045ccf8b382775d81d83919c228cca"><code>159c045</code></a> more defensive coding in SyslogOutputStream and in SyslogAppenderBase</li> <li><a href="https://github.com/qos-ch/logback/commit/9427d6b23d5a692c8a76a994c076ef68ded7835c"><code>9427d6b</code></a> slight refactoring for clarity</li> <li><a href="https://github.com/qos-ch/logback/commit/79c4179c0b440a9dcf35bc9bda1ead2b2f90966c"><code>79c4179</code></a> slight refactoring</li> <li>Additional commits viewable in <a href="https://github.com/qos-ch/logback/compare/v_1.5.32...v_1.6.1">compare view</a></li> </ul> </details> <br /> Updates `ch.qos.logback:logback-classic` from 1.5.32 to 1.6.1 <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/qos-ch/logback/releases">ch.qos.logback:logback-classic's releases</a>.</em></p> <blockquote> <h2>Logback 1.6.1</h2> <p><strong>2026-07-28 Release of logback version 1.6.1</strong></p> <p>• In TimeBasedRollingPolicy, when the file option is set, the intermediate file renamed before asynchronous compression now receives the target archive name without the compression suffix (e.g. <code>.gz</code>, <code>.zip</code>, <code>.xz</code>). Previously it used a nanotime-based <code>.tmp</code> suffix. This makes the file easier to identify if compression fails during rollover. (See also the following paragraph.)</p> <p>• On GZ, ZIP, or XZ compression failure, the original (uncompressed) log file is no longer deleted. Compression strategies now delete the source file only after successful compression and emit a warning that the original was left intact.</p> <p>• ConsoleAppender with <!-- raw HTML omitted --> now probes JLine's org.jline.jansi.AnsiConsole first and falls back to the legacy FuseSource org.fusesource.jansi.AnsiConsole class. This keeps ANSI coloring working after Jansi moved under the JLine project. The optional org.jline:jansi-core artifact is declared as a dependency alongside the existing FuseSource jansi dependency. A preferredJansiClassName property was added for tests. This issue was reported in <a href="https://redirect.github.com/qos-ch/logback/issues/1043">issues/1043</a> by <a href="https://github.com/seonwooj0810">seonwoo_jung</a> who also provided the relevant PR.</p> <p>• LayoutWrappingEncoder now reports an error at start() when no layout is set and guards encode() against a null layout. Previously, a missing layout (for example after an ignored <!-- raw HTML omitted -->/<!-- raw HTML omitted -->/<!-- raw HTML omitted --> branch) allowed the encoder to start and then fail with a NullPointerException on every event, resulting in silent log loss. This issue was reported in <a href="https://redirect.github.com/qos-ch/logback/issues/1046">issues/1046</a> by <a href="https://github.com/seonwooj0810">seonwoo_jung</a> who also provided the relevant PR.</p> <p>• FileCollisionAnalyser now detects file collisions involving nested appenders of SiftingAppender. When the nested file or fileNamePattern does not textually reference the discriminator key (e.g. ${userId}), a warning is issued at configuration time naming the appender, the key, and the shared target. This closes a gap where statically declared file appenders were checked but sifted nested appenders were not. This enhancement was contributed in [PR <a href="https://redirect.github.com/qos-ch/logback/issues/1041">#1041</a>](<a href="https://redirect.github.com/qos-ch/logback/issues/1041">qos-ch/logback#1041</a>) by <a href="https://github.com/seonwooj0810">seonwoo_jung</a>.</p> <p>• More defensive handling in SyslogOutputStream and SyslogAppenderBase: the close() method now ensures that resources are closed, writes and flushes check that the underlying resources are in a valid state and fallback to no-op otherwise.</p> <p>• A bit-wise identical binary of this version can be reproduced by building from source code at commit 57759f433000a133088ef0441038963134437fbd associated with the tag v_1.6.1. The release was built using Java "21" 2023-10-17 LTS build 21.0.1.+12-LTS-29 under Linux Debian 11.6.</p> <p>• See <a href="https://logback.qos.ch/news.html#1.6.1">https://logback.qos.ch/news.html#1.6.1</a> for the original text.</p> <h2>Logback 1.6.0</h2> <p><strong>2026-07-23 Release of logback version 1.6.0</strong></p> <p>• Removed certain deprecated variables, methods, and classes. For the list of removed members see <a href="https://logback.qos.ch/notes/release_1.6.0.txt">release_1.6.0.txt.</a></p> <p>• In <code>AsyncAppenderBase</code>, the <code>put(ILoggingEvent)</code> method now has the protected modifier to allow access from derived classes. This change was requested by Thomas Skjølberg in <a href="https://redirect.github.com/qos-ch/logback/pull/1053">pr#1053</a>.</p> <p>• Bump SLF4J dependency to version 2.0.18.</p> <p>• <strong>See also the overview of the <a href="https://logback.qos.ch/news.html#latest_stable">1.6.x series</a>.</strong></p> <p>• A bit-wise identical binary of this version can be reproduced by building from source code at commit b07adf36019b51a10f824fdd94009985c587b1d3 associated with the tag v_1.6.0. The release was built using Java "21" 2023-10-17 LTS build 21.0.1.+12-LTS-29 under Linux Debian 11.6.</p> <h2>Logback 1.5.38</h2> <p><strong>2026-07-09 Release of logback version 1.5.38</strong></p> <p>• In <code>HardenedObjectInputStream</code>, fixed a typo preventing <code>Throwable</code> objects from being white-filtered. This issue was reported in [PR <a href="https://redirect.github.com/qos-ch/logback/issues/1045">#1045</a>](<a href="https://redirect.github.com/qos-ch/logback/pull/1045">qos-ch/logback#1045</a>) by <a href="https://github.com/t0rchwo0d">t0rchwo0d</a>.</p> <p>• A bitwise identical binary of this version can be reproduced by building from source code at commit d04984a41fce42977466f45a2f076f0ee5cc4207 associated with the tag v_1.5.38. Release built using Java "21" 2023-10-17 LTS build 21.0.1.+12-LTS-29 under Linux Debian 11.6.</p> <h2>Logback 1.5.37</h2> <p><strong>2026-06-26 Release of logback version 1.5.37</strong></p> <ol> <li>• Given the numerous vulnerabilities related to conditional configuration processing based on the evaluation of Java expressions using the Janino library, support for such expressions has been removed. Users are offered the an <a href="https://logback.qos.ch/translator/services/conditionalConfigMigrator.html">online migration service</a> or the <code><condition></code> element introduced in version 1.5.20. See the <a href="https://logback.qos.ch/manual/configuration.html#conditional">relevant documentation</a> for more details.</li> </ol> <p>• A bitwise identical binary of this version can be reproduced by building from source code at commit c1df7f522e648eec7b4ef6a12c8758fec0f00048 associated with the tag v_1.5.37. Release built using Java "21" 2023-10-17 LTS build 21.0.1.+12-LTS-29 under Linux Debian 11.6.</p> <h2>Logback 1.5.36</h2> <p><strong>2026-06-25 Release of logback version 1.5.36</strong></p> <p>• The 'condition' attribute in <code><if></code> elements now reject certain references that are associated with ACE attacks. This issue was reported by "yulate" (<a href="mailto:yulate531@gmail.com.com">yulate531@gmail.com.com</a>) and registered as <a href="https://www.cve.org/cverecord?id=CVE-2026-13006">CVE-2026-13006</a>. <strong>Please note that version 1.5.37 provides the full fix to this vulnerability.</strong></p> <!-- raw HTML omitted --> </blockquote> <p>... (truncated)</p> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/qos-ch/logback/commit/57759f433000a133088ef0441038963134437fbd"><code>57759f4</code></a> prepare release 1.6.1</li> <li><a href="https://github.com/qos-ch/logback/commit/175f99f2093ae07f4c8d44f93b800f65b03a6e19"><code>175f99f</code></a> fix imports</li> <li><a href="https://github.com/qos-ch/logback/commit/4b8773ed127fdc62b85a7c7ddaef10f25830788c"><code>4b8773e</code></a> add compressionFailureLeavesOriginalFileIntact test for XZ compression</li> <li><a href="https://github.com/qos-ch/logback/commit/cafaf1115fd20be19b2f7a4a09184446e8bbc04d"><code>cafaf11</code></a> do not delete original file if compression fails</li> <li><a href="https://github.com/qos-ch/logback/commit/ee50125b293f5a731543de9f9f5fb72756a43464"><code>ee50125</code></a> let the temporary file before compression be target file without the .gz or ....</li> <li><a href="https://github.com/qos-ch/logback/commit/5626acc301f4039537a6c668f0f2d51989472785"><code>5626acc</code></a> minor refactoring</li> <li><a href="https://github.com/qos-ch/logback/commit/d97da4fbc0de00ca901ef78d91b9fc1850ae803f"><code>d97da4f</code></a> minor refactoring</li> <li><a href="https://github.com/qos-ch/logback/commit/159c045d8f045ccf8b382775d81d83919c228cca"><code>159c045</code></a> more defensive coding in SyslogOutputStream and in SyslogAppenderBase</li> <li><a href="https://github.com/qos-ch/logback/commit/9427d6b23d5a692c8a76a994c076ef68ded7835c"><code>9427d6b</code></a> slight refactoring for clarity</li> <li><a href="https://github.com/qos-ch/logback/commit/79c4179c0b440a9dcf35bc9bda1ead2b2f90966c"><code>79c4179</code></a> slight refactoring</li> <li>Additional commits viewable in <a href="https://github.com/qos-ch/logback/compare/v_1.5.32...v_1.6.1">compare view</a></li> </ul> </details> <br /> Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) --- <details> <summary>Dependabot commands and options</summary> <br /> You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) </details> Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
818 lines
31 KiB
Groovy
818 lines
31 KiB
Groovy
plugins {
|
|
id "java"
|
|
id "jacoco"
|
|
id "io.spring.dependency-management" version "1.1.7"
|
|
id "org.springframework.boot" version "4.0.6"
|
|
id "org.springdoc.openapi-gradle-plugin" version "1.9.0"
|
|
id "io.swagger.swaggerhub" version "1.3.2"
|
|
id "com.diffplug.spotless" version "8.8.0"
|
|
id "com.github.jk1.dependency-license-report"
|
|
//id "nebula.lint" version "19.0.3"
|
|
id "org.sonarqube" version "7.3.1.8318"
|
|
}
|
|
|
|
import com.github.jk1.license.render.*
|
|
import groovy.json.JsonOutput
|
|
import groovy.json.JsonSlurper
|
|
import groovy.xml.XmlSlurper
|
|
import org.gradle.api.JavaVersion
|
|
import org.gradle.api.tasks.testing.Test
|
|
import org.gradle.jvm.toolchain.JavaLanguageVersion
|
|
import stirling.software.gradle.ModuleLicenseOverrideFilter
|
|
|
|
ext {
|
|
springBootVersion = "4.0.6"
|
|
pdfboxVersion = "3.0.8"
|
|
imageioVersion = "3.13.1"
|
|
lombokVersion = "1.18.46"
|
|
bouncycastleVersion = "1.85"
|
|
springSecuritySamlVersion = "7.1.0"
|
|
openSamlVersion = "5.2.1"
|
|
commonmarkVersion = "0.28.0"
|
|
googleJavaFormatVersion = "1.35.0"
|
|
logback = "1.6.1"
|
|
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"
|
|
jinjavaVersion = "2.8.4"
|
|
jackson2Version = "2.22.1"
|
|
bucket4jVersion = "8.19.0"
|
|
archunitVersion = "1.4.2"
|
|
batikVersion = "1.19"
|
|
jpdfiumVersion = "1.0.4"
|
|
jwtVersion = "0.13.0"
|
|
awsSdkVersion = "2.44.12"
|
|
jschVersion = "2.28.6"
|
|
commonsNetVersion = "3.11.1"
|
|
smbjVersion = "0.14.0"
|
|
tinkVersion = "1.23.0"
|
|
testcontainersMinioVersion = "1.21.4"
|
|
// junit-platform-launcher version managed by Spring Boot BOM
|
|
modernJavaVersion = 25
|
|
}
|
|
|
|
def buildJavaMajorVersion = (project.findProperty('javaVersion') ?: ext.modernJavaVersion).toString().toInteger()
|
|
def buildJavaLanguageVersion = JavaLanguageVersion.of(buildJavaMajorVersion)
|
|
def buildJavaVersion = JavaVersion.toVersion(buildJavaMajorVersion.toString())
|
|
|
|
java {
|
|
sourceCompatibility = buildJavaVersion
|
|
targetCompatibility = buildJavaVersion
|
|
toolchain {
|
|
languageVersion = buildJavaLanguageVersion
|
|
}
|
|
}
|
|
|
|
ext.isSecurityDisabled = { ->
|
|
System.getenv('DOCKER_ENABLE_SECURITY') == 'false' ||
|
|
System.getenv('DISABLE_ADDITIONAL_FEATURES') == 'true' ||
|
|
(project.hasProperty('DISABLE_ADDITIONAL_FEATURES') &&
|
|
System.getProperty('DISABLE_ADDITIONAL_FEATURES') == 'true')
|
|
}
|
|
|
|
ext.mavenUrl = System.getenv("MAVEN_PUBLIC_URL") ?: ""
|
|
ext.username = System.getenv('MAVEN_USER') ?: ""
|
|
ext.password = System.getenv('MAVEN_PASSWORD') ?: ""
|
|
|
|
if (rootProject.ext.mavenUrl.isEmpty()) {
|
|
println "No custom MAVEN_PUBLIC_URL set, defaulting to Maven Central"
|
|
} else {
|
|
println "MAVEN_PUBLIC_URL set"
|
|
}
|
|
|
|
jar {
|
|
enabled = false
|
|
manifest {
|
|
attributes "Implementation-Title": "Stirling-PDF",
|
|
"Implementation-Version": project.version
|
|
}
|
|
}
|
|
|
|
bootJar {
|
|
enabled = false
|
|
}
|
|
|
|
// :saas is only included for SaaS builds, but a default-flavor clean must still remove artifacts
|
|
// left behind by an earlier SaaS build.
|
|
tasks.named('clean') {
|
|
delete layout.projectDirectory.dir('app/saas/build')
|
|
}
|
|
|
|
// Configure main class for the root project
|
|
springBoot {
|
|
mainClass = 'stirling.software.SPDF.SPDFApplication'
|
|
}
|
|
|
|
allprojects {
|
|
group = 'stirling.software'
|
|
version = '2.14.2'
|
|
|
|
configurations.configureEach {
|
|
exclude group: "org.springframework.boot", module: "spring-boot-starter-tomcat"
|
|
}
|
|
}
|
|
|
|
def appVersionStr = project.version.toString()
|
|
def tauriConfigPath = layout.projectDirectory.file('frontend/editor/src-tauri/tauri.conf.json').asFile.path
|
|
def sim1Path = layout.projectDirectory.file('frontend/editor/src/core/testing/serverExperienceSimulations.ts').asFile.path
|
|
def sim2Path = layout.projectDirectory.file('frontend/editor/src/proprietary/testing/serverExperienceSimulations.ts').asFile.path
|
|
def aurDesktopPkgbuildPath = layout.projectDirectory.file('.github/aur/stirling-pdf-desktop/PKGBUILD').asFile.path
|
|
def aurServerPkgbuildPath = layout.projectDirectory.file('.github/aur/stirling-pdf-server-bin/PKGBUILD').asFile.path
|
|
|
|
tasks.register('syncAppVersion') {
|
|
group = 'versioning'
|
|
description = 'Synchronizes app version across desktop, simulation, and AUR PKGBUILD configs.'
|
|
|
|
doLast {
|
|
println "Synchronizing application version to ${appVersionStr}"
|
|
|
|
def tauriConfigFile = new File(tauriConfigPath)
|
|
if (tauriConfigFile.exists()) {
|
|
def content = tauriConfigFile.getText('UTF-8')
|
|
def matcher = (content =~ /(?m)^(\s*"version":\s*")([^"]*)(")/)
|
|
if (!matcher.find()) {
|
|
throw new GradleException("Could not locate version in ${tauriConfigFile} for synchronization")
|
|
}
|
|
def updatedContent = matcher.replaceFirst("${matcher.group(1)}${appVersionStr}${matcher.group(3)}")
|
|
if (content != updatedContent) {
|
|
tauriConfigFile.write(updatedContent, 'UTF-8')
|
|
}
|
|
}
|
|
|
|
[new File(sim1Path), new File(sim2Path)].each { f ->
|
|
if (f.exists()) {
|
|
def content = f.getText('UTF-8')
|
|
def matcher = (content =~ /(appVersion:\s*(['"]))(.*?)(\2)/)
|
|
if (!matcher.find()) {
|
|
throw new GradleException("Could not locate appVersion in ${f} for synchronization")
|
|
}
|
|
def updatedContent = matcher.replaceFirst("${matcher.group(1)}${appVersionStr}${matcher.group(4)}")
|
|
if (content != updatedContent) {
|
|
f.write(updatedContent, 'UTF-8')
|
|
}
|
|
}
|
|
}
|
|
|
|
[new File(aurDesktopPkgbuildPath), new File(aurServerPkgbuildPath)].each { f ->
|
|
if (f.exists()) {
|
|
def content = f.getText('UTF-8')
|
|
def matcher = (content =~ /(?m)^(pkgver=)(.*)$/)
|
|
if (!matcher.find()) {
|
|
throw new GradleException("Could not locate pkgver in ${f} for synchronization")
|
|
}
|
|
def updatedContent = matcher.replaceFirst("\$1${appVersionStr}")
|
|
if (content != updatedContent) {
|
|
f.write(updatedContent, 'UTF-8')
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
tasks.register('writeVersion', WriteProperties) {
|
|
destinationFile = layout.projectDirectory.file('app/common/src/main/resources/version.properties')
|
|
println "Writing version.properties to ${destinationFile.get().asFile.path}"
|
|
comment = "${new Date()}"
|
|
property 'version', project.provider { project.version.toString() }
|
|
}
|
|
|
|
subprojects {
|
|
apply plugin: 'java'
|
|
apply plugin: 'java-library'
|
|
apply plugin: 'com.diffplug.spotless'
|
|
apply plugin: 'org.springframework.boot'
|
|
apply plugin: 'io.spring.dependency-management'
|
|
apply plugin: 'jacoco'
|
|
apply from: rootProject.file('gradle/spotless.gradle')
|
|
|
|
java {
|
|
sourceCompatibility = buildJavaVersion
|
|
targetCompatibility = buildJavaVersion
|
|
toolchain {
|
|
languageVersion = buildJavaLanguageVersion
|
|
}
|
|
}
|
|
|
|
if (project.name != "stirling-pdf") {
|
|
bootJar {
|
|
enabled = false
|
|
}
|
|
}
|
|
|
|
repositories {
|
|
if (!rootProject.ext.mavenUrl.isEmpty()) {
|
|
maven {
|
|
url = rootProject.ext.mavenUrl + '/releases'
|
|
credentials(PasswordCredentials) {
|
|
username = rootProject.ext.username
|
|
password = rootProject.ext.password
|
|
}
|
|
authentication {
|
|
basic(BasicAuthentication)
|
|
}
|
|
allowInsecureProtocol = true
|
|
}
|
|
}
|
|
// Maven Central first; mirrors below are fallbacks for niche artifacts.
|
|
mavenCentral()
|
|
maven { url = "https://repository.jboss.org/" }
|
|
maven { url = "https://build.shibboleth.net/maven/releases" }
|
|
}
|
|
|
|
configurations.configureEach {
|
|
exclude group: 'org.springframework.boot', module: 'spring-boot-starter-tomcat'
|
|
// Exclude vulnerable BouncyCastle version used in tableau
|
|
exclude group: 'org.bouncycastle', module: 'bcpkix-jdk15on'
|
|
exclude group: 'org.bouncycastle', module: 'bcutil-jdk15on'
|
|
exclude group: 'org.bouncycastle', module: 'bcmail-jdk15on'
|
|
|
|
// Security CVE fixes - hardcoded resolution strategy to ensure safe versions
|
|
// Primary fixes via explicit dependencies in app/core/build.gradle:
|
|
// - 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:${gsonVersion}"
|
|
resolutionStrategy.force "org.mozilla:rhino:${rhinoVersion}"
|
|
// CVE-2025-48924: commons-lang3 3.20.0 DoS prevention
|
|
resolutionStrategy.force "org.apache.commons:commons-lang3:${commonsLang3}"
|
|
// CVE-2024-47554: commons-io DoS prevention
|
|
resolutionStrategy.force "commons-io:commons-io:${commonsIoVersion}"
|
|
// Jackson 2 is transitive-only here (jinjava, opensaml, jjwt request older versions);
|
|
// pin the family to a current release and keep modules aligned.
|
|
resolutionStrategy.force "com.fasterxml.jackson.core:jackson-core:${jackson2Version}"
|
|
resolutionStrategy.force "com.fasterxml.jackson.core:jackson-databind:${jackson2Version}"
|
|
resolutionStrategy.force "com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:${jackson2Version}"
|
|
resolutionStrategy.force "com.fasterxml.jackson.datatype:jackson-datatype-jdk8:${jackson2Version}"
|
|
resolutionStrategy.force "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:${jackson2Version}"
|
|
// Keep BouncyCastle modules aligned to avoid runtime linkage errors
|
|
resolutionStrategy.force "org.bouncycastle:bcprov-jdk18on:${bouncycastleVersion}"
|
|
resolutionStrategy.force "org.bouncycastle:bcpkix-jdk18on:${bouncycastleVersion}"
|
|
resolutionStrategy.force "org.bouncycastle:bcutil-jdk18on:${bouncycastleVersion}"
|
|
}
|
|
|
|
dependencyManagement {
|
|
imports {
|
|
mavenBom "org.springframework.boot:spring-boot-dependencies:$springBootVersion"
|
|
}
|
|
dependencies {
|
|
// Override BOM-managed commons-lang3 for CVE-2025-48924 fix
|
|
dependency "org.apache.commons:commons-lang3:$commonsLang3"
|
|
}
|
|
}
|
|
|
|
dependencies {
|
|
implementation 'org.springframework.boot:spring-boot-starter-actuator'
|
|
implementation 'io.github.pixee:java-security-toolkit:1.2.3'
|
|
|
|
//tmp for security bumps
|
|
implementation "ch.qos.logback:logback-core:$logback"
|
|
implementation "ch.qos.logback:logback-classic:$logback"
|
|
compileOnly "org.projectlombok:lombok:$lombokVersion"
|
|
annotationProcessor "org.projectlombok:lombok:$lombokVersion"
|
|
|
|
// Jackson 3 (Spring Boot 4 uses tools.jackson)
|
|
implementation 'org.springframework.boot:spring-boot-starter-jackson'
|
|
|
|
testImplementation 'org.springframework.boot:spring-boot-starter-test'
|
|
testImplementation 'org.springframework.boot:spring-boot-starter-webmvc-test'
|
|
testRuntimeOnly 'org.mockito:mockito-inline:5.2.0'
|
|
testRuntimeOnly "org.junit.platform:junit-platform-launcher"
|
|
|
|
testImplementation platform("com.squareup.okhttp3:okhttp-bom:${okhttpBomVersion}")
|
|
testImplementation "com.squareup.okhttp3:mockwebserver"
|
|
}
|
|
|
|
tasks.withType(JavaCompile).configureEach {
|
|
options.encoding = "UTF-8"
|
|
options.release = buildJavaMajorVersion
|
|
if (!project.hasProperty("noSpotless")) {
|
|
dependsOn "spotlessApply"
|
|
}
|
|
}
|
|
|
|
tasks.named("compileJava", JavaCompile).configure {
|
|
// options.compilerArgs.add("-Xlint:deprecation")
|
|
// options.compilerArgs.add("-Xlint:unchecked")
|
|
}
|
|
|
|
def jacocoReport = tasks.named("jacocoTestReport")
|
|
|
|
tasks.withType(Test).configureEach {
|
|
useJUnitPlatform()
|
|
jvmArgs '--enable-native-access=ALL-UNNAMED'
|
|
systemProperty 'java.awt.headless', 'true'
|
|
systemProperty 'apple.awt.UIElement', 'true'
|
|
|
|
testLogging {
|
|
events "started", "failed"
|
|
showExceptions = true
|
|
showCauses = true
|
|
showStackTraces = true
|
|
exceptionFormat "full"
|
|
}
|
|
finalizedBy(jacocoReport)
|
|
}
|
|
|
|
jacocoReport.configure {
|
|
dependsOn(tasks.named("test"))
|
|
reports {
|
|
xml.required.set(true)
|
|
csv.required.set(false)
|
|
html.required.set(true)
|
|
}
|
|
doLast {
|
|
def xmlReport = reports.xml.outputLocation.get().asFile
|
|
if (!xmlReport.exists()) {
|
|
logger.lifecycle("Jacoco coverage report not found at ${xmlReport}")
|
|
return
|
|
}
|
|
|
|
def xmlContent = xmlReport.getText("UTF-8")
|
|
xmlContent = xmlContent.replaceFirst('(?s)<!DOCTYPE.*?>', '')
|
|
def report = new XmlSlurper(false, false).parseText(xmlContent)
|
|
def counters = report.counter.collectEntries { counter ->
|
|
def type = counter.@type.text()
|
|
def covered = counter.@covered.text() as BigDecimal
|
|
def missed = counter.@missed.text() as BigDecimal
|
|
[(type): [covered: covered, missed: missed]]
|
|
}
|
|
|
|
def thresholds = [
|
|
LINE : 0.13,
|
|
INSTRUCTION: 0.14,
|
|
BRANCH : 0.09
|
|
]
|
|
|
|
def types = ["LINE", "INSTRUCTION", "BRANCH"]
|
|
def headers = ["Metric", "Coverage", "Covered/Total", "Status", "Target"]
|
|
|
|
def rows = types.collect { String type ->
|
|
def data = counters[type]
|
|
if (!data) {
|
|
return [type, "—", "—", "No data", ""]
|
|
}
|
|
|
|
def total = data.covered + data.missed
|
|
if (total == 0) {
|
|
return [type, "—", "0/${total.toBigInteger()}", "No executions", ""]
|
|
}
|
|
|
|
def ratio = data.covered / total * 100
|
|
def coverageText = String.format(Locale.ROOT, "%.2f%%", ratio)
|
|
def coveredText = String.format(Locale.ROOT, "%d/%d",
|
|
data.covered.toBigInteger(),
|
|
total.toBigInteger())
|
|
|
|
def threshold = thresholds[type]
|
|
def thresholdPercent = threshold != null ? threshold * 100 : null
|
|
def targetText = thresholdPercent != null ?
|
|
String.format(Locale.ROOT, ">= %.2f%%", thresholdPercent) : ""
|
|
def passed = thresholdPercent != null ? ratio >= thresholdPercent : null
|
|
def statusText = passed == null ? "" : (passed ? "PASS" : "FAIL")
|
|
|
|
return [type, coverageText, coveredText, statusText, targetText]
|
|
}
|
|
|
|
def columnIndexes = (0..<headers.size())
|
|
def columnWidths = columnIndexes.collect { idx ->
|
|
Math.max(headers[idx].length(), rows.collect { row ->
|
|
row[idx] != null ? row[idx].toString().length() : 0
|
|
}.max() ?: 0)
|
|
}
|
|
|
|
def formatRow = { List<String> values ->
|
|
columnIndexes.collect { idx ->
|
|
def value = values[idx] ?: ""
|
|
value.padRight(columnWidths[idx])
|
|
}.join(" | ")
|
|
}
|
|
|
|
def separator = columnIndexes.collect { idx ->
|
|
''.padRight(columnWidths[idx], '-')
|
|
}.join("-+-")
|
|
|
|
logger.lifecycle("")
|
|
logger.lifecycle("==== JaCoCo Coverage Summary ====")
|
|
logger.lifecycle(formatRow(headers))
|
|
logger.lifecycle(separator)
|
|
rows.each { row ->
|
|
logger.lifecycle(formatRow(row))
|
|
}
|
|
logger.lifecycle(separator)
|
|
|
|
def htmlReport = reports.html.outputLocation.get().asFile
|
|
logger.lifecycle("Detailed HTML report available at: ${htmlReport}")
|
|
if (rows.any { it[3] == "FAIL" }) {
|
|
logger.lifecycle("Some coverage targets were missed. Please review the detailed report above.")
|
|
} else if (rows.any { it[3] == "PASS" }) {
|
|
logger.lifecycle("Great job! All tracked coverage metrics meet their targets.")
|
|
}
|
|
logger.lifecycle("=================================\n")
|
|
}
|
|
}
|
|
|
|
tasks.named("build") {
|
|
dependsOn jacocoReport
|
|
}
|
|
|
|
jacocoTestCoverageVerification {
|
|
dependsOn jacocoReport
|
|
violationRules {
|
|
rule {
|
|
enabled = true
|
|
element = 'BUNDLE'
|
|
// Bytecode-Anweisungen abgedeckt
|
|
limit {
|
|
counter = 'INSTRUCTION'
|
|
value = 'COVEREDRATIO'
|
|
minimum = 0.14
|
|
}
|
|
// wie viele Quellcode-Zeilen abgedeckt
|
|
limit {
|
|
counter = 'LINE'
|
|
value = 'COVEREDRATIO'
|
|
minimum = 0.13
|
|
}
|
|
// Verzweigungen (if/else, switch) abgedeckt; misst Logik-Abdeckung
|
|
limit {
|
|
counter = 'BRANCH'
|
|
value = 'COVEREDRATIO'
|
|
minimum = 0.09
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
tasks.named("processResources") {
|
|
dependsOn(rootProject.tasks.writeVersion)
|
|
}
|
|
|
|
if (name == 'stirling-pdf') {
|
|
apply plugin: 'org.springdoc.openapi-gradle-plugin'
|
|
|
|
openApi {
|
|
apiDocsUrl = "http://localhost:8080/v1/api-docs"
|
|
outputDir = file("$projectDir")
|
|
outputFileName = "SwaggerDoc.json"
|
|
waitTimeInSeconds = 60 // Increase the wait time to 60 seconds
|
|
}
|
|
|
|
tasks.named("forkedSpringBootRun") {
|
|
dependsOn(":common:jar")
|
|
dependsOn(":proprietary:jar")
|
|
}
|
|
|
|
tasks.register("copySwaggerDoc", Copy) {
|
|
doNotTrackState("Writes SwaggerDoc.json to project root")
|
|
from(layout.projectDirectory.file("SwaggerDoc.json"))
|
|
into(rootProject.projectDir)
|
|
dependsOn("generateOpenApiDocs")
|
|
}
|
|
|
|
tasks.register("cleanSwaggerInBuild", Delete) {
|
|
doNotTrackState("Cleans up SwaggerDoc.json in build directory")
|
|
delete(layout.projectDirectory.file("SwaggerDoc.json"))
|
|
dependsOn("copySwaggerDoc")
|
|
}
|
|
|
|
tasks.named("copySwaggerDoc") {
|
|
finalizedBy("cleanSwaggerInBuild")
|
|
}
|
|
|
|
tasks.named("generateOpenApiDocs") {
|
|
finalizedBy("copySwaggerDoc")
|
|
doNotTrackState("OpenAPI plugin writes outside build directory")
|
|
}
|
|
|
|
tasks.named("bootRun") {
|
|
def runtimeArgs = [
|
|
"-XX:+UseG1GC",
|
|
"-XX:MaxGCPauseMillis=200",
|
|
"-XX:G1HeapRegionSize=4m",
|
|
"-XX:+ExplicitGCInvokesConcurrent",
|
|
"-XX:+UseStringDeduplication",
|
|
"-XX:+UseCompactObjectHeaders",
|
|
"--enable-native-access=ALL-UNNAMED"
|
|
]
|
|
|
|
// Optional JaCoCo agent for e2e/cucumber backend coverage.
|
|
//
|
|
// Enabled with `-PjacocoAgent=true`. The default destfile lives
|
|
// outside the source tree so it doesn't poison a normal bootRun
|
|
// for a developer who forgot to pass the property. Override
|
|
// both with `-PjacocoExec=/path/to.exec` if you need a custom
|
|
// location (e.g. when sharing it with the Playwright runner).
|
|
if (rootProject.hasProperty('jacocoAgent') &&
|
|
rootProject.property('jacocoAgent').toString() == 'true') {
|
|
def agentJar = rootProject.layout.buildDirectory
|
|
.file('jacoco/jacocoagent.jar').get().asFile.absolutePath
|
|
def execFile = (rootProject.findProperty('jacocoExec') ?:
|
|
rootProject.layout.projectDirectory
|
|
.file('.test-state/playwright/jacoco.exec').asFile.absolutePath
|
|
).toString()
|
|
// The JaCoCo agent argument is a comma-separated key=value list,
|
|
// so a path that itself contains ',' or '=' would smuggle extra
|
|
// agent options (e.g. -PjacocoExec='out.exec,sessionid=evil').
|
|
// Today the value only comes from our own CI workflows, but
|
|
// validating defensively is cheap and silences Aikido.
|
|
//
|
|
// Control characters are checked via String.contains rather
|
|
// than inside a slashy regex character class - a literal NULL
|
|
// accidentally landing in the regex killed Groovy parsing on
|
|
// the previous attempt.
|
|
def hasBadChar = execFile.find(/[,= ]/) != null ||
|
|
execFile.contains('\r') ||
|
|
execFile.contains('\n') ||
|
|
execFile.contains('\t')
|
|
if (hasBadChar) {
|
|
throw new GradleException(
|
|
"jacocoExec='" + execFile + "' contains characters " +
|
|
"(',', '=', whitespace, or control chars) that " +
|
|
"would break -javaagent option parsing. Choose " +
|
|
"a different path."
|
|
)
|
|
}
|
|
runtimeArgs.add("-javaagent:${agentJar}=destfile=${execFile},output=file,append=false,dumponexit=true")
|
|
dependsOn(rootProject.tasks.named('copyJacocoAgent'))
|
|
doFirst {
|
|
new File(execFile).parentFile?.mkdirs()
|
|
logger.lifecycle("JaCoCo agent attached: ${execFile}")
|
|
}
|
|
}
|
|
|
|
jvmArgs = runtimeArgs
|
|
}
|
|
}
|
|
}
|
|
|
|
tasks.withType(JavaCompile).configureEach {
|
|
options.encoding = "UTF-8"
|
|
if (!project.hasProperty("noSpotless")) {
|
|
dependsOn "spotlessApply"
|
|
}
|
|
}
|
|
|
|
gradle.taskGraph.whenReady { graph ->
|
|
if (project.hasProperty("noSpotless")) {
|
|
allprojects { scopedProject ->
|
|
scopedProject.tasks.matching { it.name.startsWith("spotless") }.configureEach {
|
|
enabled = false
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
def allProjects = ((subprojects as Set<Project>) + project) as Set<Project>
|
|
def moduleLicenseOverridesFile = project.layout.projectDirectory.file("app/license-overrides.json").asFile
|
|
|
|
licenseReport {
|
|
projects = allProjects
|
|
renderers = [new JsonReportRenderer()]
|
|
allowedLicensesFile = project.layout.projectDirectory.file("app/allowed-licenses.json").asFile
|
|
outputDir = project.layout.buildDirectory.dir("reports/dependency-license").get().asFile.path
|
|
configurations = [ "productionRuntimeClasspath", "runtimeClasspath" ]
|
|
filters = [new ModuleLicenseOverrideFilter(moduleLicenseOverridesFile)]
|
|
}
|
|
|
|
tasks.named('generateLicenseReport') {
|
|
inputs.file(moduleLicenseOverridesFile)
|
|
}
|
|
|
|
tasks.named('checkLicensePreparation') {
|
|
inputs.file(moduleLicenseOverridesFile)
|
|
}
|
|
|
|
// Configure the forked spring boot run task to properly delegate to the stirling-pdf module
|
|
tasks.named('forkedSpringBootRun') {
|
|
dependsOn ':stirling-pdf:bootRun'
|
|
doFirst {
|
|
println "Delegating forkedSpringBootRun to :stirling-pdf:bootRun"
|
|
}
|
|
}
|
|
|
|
spotless {
|
|
yaml {
|
|
target '*.yml', '*.yaml'
|
|
trimTrailingWhitespace()
|
|
leadingTabsToSpaces()
|
|
endWithNewline()
|
|
}
|
|
format 'gradle', {
|
|
target 'build.gradle', 'settings.gradle', 'gradle/*.gradle', 'gradle/**/*.gradle'
|
|
trimTrailingWhitespace()
|
|
leadingTabsToSpaces()
|
|
endWithNewline()
|
|
}
|
|
}
|
|
|
|
sonar {
|
|
properties {
|
|
property "sonar.projectKey", "Stirling-Tools_Stirling-PDF"
|
|
property "sonar.organization", "stirling-tools"
|
|
|
|
property "sonar.exclusions", "**/build-wrapper-dump.json, **/src/main/java/org/apache/**, **/src/main/resources/static/pdfjs/**, **/src/main/resources/static/pdfjs-legacy/**, **/src/main/resources/static/js/thirdParty/**"
|
|
property "sonar.coverage.exclusions", "**/src/main/java/org/apache/**, **/src/main/resources/static/pdfjs/**, **/src/main/resources/static/pdfjs-legacy/**, **/src/main/resources/static/js/thirdParty/**"
|
|
property "sonar.cpd.exclusions", "**/src/main/java/org/apache/**, **/src/main/resources/static/pdfjs/**, **/src/main/resources/static/pdfjs-legacy/**, **/src/main/resources/static/js/thirdParty/**"
|
|
}
|
|
}
|
|
|
|
swaggerhubUpload {
|
|
// dependsOn = generateOpenApiDocs // Depends on your task generating Swagger docs
|
|
api = "Stirling-PDF" // The name of your API on SwaggerHub
|
|
owner = "${System.getenv().getOrDefault('SWAGGERHUB_USER', 'Frooodle')}" // Your SwaggerHub username (or organization name)
|
|
version = project.version // The version of your API
|
|
inputFile = file("SwaggerDoc.json") // The path to your Swagger docs
|
|
token = "${System.getenv("SWAGGERHUB_API_KEY")}" // Your SwaggerHub API key, passed as an environment variable
|
|
oas = "3.0.0" // The version of the OpenAPI Specification you"re using
|
|
}
|
|
|
|
repositories {
|
|
if (!rootProject.ext.mavenUrl.isEmpty()) {
|
|
maven {
|
|
url = rootProject.ext.mavenUrl + '/releases'
|
|
credentials(PasswordCredentials) {
|
|
username = rootProject.ext.username
|
|
password = rootProject.ext.password
|
|
}
|
|
authentication {
|
|
basic(BasicAuthentication)
|
|
}
|
|
allowInsecureProtocol = true
|
|
}
|
|
}
|
|
mavenCentral()
|
|
maven { url = "https://repository.jboss.org/" }
|
|
maven { url = "https://build.shibboleth.net/maven/releases" }
|
|
}
|
|
|
|
dependencies {
|
|
implementation project(':stirling-pdf')
|
|
implementation project(':common')
|
|
if (rootProject.ext.isSecurityDisabled()) {
|
|
implementation project(':proprietary')
|
|
}
|
|
|
|
testImplementation 'org.springframework.boot:spring-boot-starter-test'
|
|
testRuntimeOnly "org.junit.platform:junit-platform-launcher"
|
|
|
|
testImplementation platform("com.squareup.okhttp3:okhttp-bom:${okhttpBomVersion}")
|
|
testImplementation "com.squareup.okhttp3:mockwebserver"
|
|
}
|
|
|
|
tasks.named("test") {
|
|
useJUnitPlatform()
|
|
}
|
|
|
|
// Make sure all relevant processes depend on writeVersion
|
|
processResources.dependsOn(writeVersion)
|
|
|
|
tasks.register('printVersion') {
|
|
doLast {
|
|
println project.version
|
|
}
|
|
}
|
|
|
|
tasks.named('bootRun') {
|
|
group = 'application'
|
|
description = 'Delegates to :stirling-pdf:bootRun'
|
|
dependsOn ':stirling-pdf:bootRun'
|
|
|
|
doFirst {
|
|
println "Delegating to :stirling-pdf:bootRun"
|
|
}
|
|
}
|
|
|
|
tasks.named('build') {
|
|
group = 'build'
|
|
description = 'Delegates to :stirling-pdf:bootJar'
|
|
dependsOn ':stirling-pdf:bootJar', 'buildRestartHelper', 'syncAppVersion'
|
|
|
|
doFirst {
|
|
println "Delegating to :stirling-pdf:bootJar"
|
|
}
|
|
}
|
|
|
|
// Task to compile RestartHelper.java
|
|
tasks.register('compileRestartHelper', JavaCompile) {
|
|
group = 'build'
|
|
description = 'Compiles the RestartHelper utility'
|
|
|
|
source = fileTree(dir: 'scripts', include: 'RestartHelper.java')
|
|
classpath = files()
|
|
destinationDirectory = layout.buildDirectory.dir("restart-helper-classes")
|
|
def restartMajorVersion = buildJavaMajorVersion
|
|
def restartLanguageVersion = JavaLanguageVersion.of(restartMajorVersion)
|
|
def restartCompatibility = JavaVersion.toVersion(restartMajorVersion.toString())
|
|
sourceCompatibility = restartCompatibility
|
|
targetCompatibility = restartCompatibility
|
|
javaCompiler = javaToolchains.compilerFor {
|
|
languageVersion = restartLanguageVersion
|
|
}
|
|
options.release.set(restartMajorVersion)
|
|
}
|
|
|
|
// Task to create restart-helper.jar
|
|
tasks.register('buildRestartHelper', Jar) {
|
|
group = 'build'
|
|
description = 'Builds the restart-helper.jar'
|
|
dependsOn 'compileRestartHelper'
|
|
|
|
from layout.buildDirectory.dir("restart-helper-classes")
|
|
archiveFileName = 'restart-helper.jar'
|
|
destinationDirectory = layout.buildDirectory.dir("libs")
|
|
|
|
manifest {
|
|
attributes 'Main-Class': 'RestartHelper'
|
|
}
|
|
|
|
doLast {
|
|
println "restart-helper.jar created at: ${destinationDirectory.get()}/restart-helper.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.
|
|
maxParallelForks = Math.max(1, (Runtime.runtime.availableProcessors().intdiv(2)) as int)
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// JaCoCo helpers used by CI for cucumber + Playwright (live backend) coverage.
|
|
//
|
|
// These let CI attach the JaCoCo agent to a running Spring Boot process
|
|
// (gradle bootRun or the docker image, via JAVA_TOOL_OPTIONS) and then turn
|
|
// the resulting .exec dump back into HTML + XML reports without anyone
|
|
// hand-installing the JaCoCo CLI.
|
|
// ----------------------------------------------------------------------------
|
|
|
|
configurations {
|
|
jacocoRuntimeAgent
|
|
jacocoCli
|
|
}
|
|
|
|
dependencies {
|
|
// The :runtime classifier on org.jacoco.agent IS the agent jar - no
|
|
// unzipping required. Kept on the version the plugin already picks so
|
|
// agent + reporter line up exactly.
|
|
jacocoRuntimeAgent "org.jacoco:org.jacoco.agent:${jacoco.toolVersion}:runtime"
|
|
jacocoCli "org.jacoco:org.jacoco.cli:${jacoco.toolVersion}"
|
|
}
|
|
|
|
tasks.register('copyJacocoAgent', Copy) {
|
|
group = 'verification'
|
|
description = 'Copies the JaCoCo runtime agent jar to build/jacoco/jacocoagent.jar.'
|
|
from configurations.jacocoRuntimeAgent
|
|
into layout.buildDirectory.dir('jacoco')
|
|
rename { 'jacocoagent.jar' }
|
|
}
|
|
|
|
// Aggregates an externally-produced .exec (e.g. from e2e:live or the cucumber
|
|
// docker container) against this project's compiled classes + sources.
|
|
//
|
|
// Inputs are configured via -P properties so the same task works for every
|
|
// caller:
|
|
//
|
|
// ./gradlew jacocoReportFromExec -PexecFile=.test-state/playwright/jacoco.exec \
|
|
// -PreportDir=build/reports/jacoco/e2e-live
|
|
tasks.register('jacocoReportFromExec', JacocoReport) {
|
|
group = 'verification'
|
|
description = 'Generates a JaCoCo HTML+XML report from an externally captured .exec.'
|
|
|
|
def execProp = project.findProperty('execFile') ?: project.findProperty('execFiles')
|
|
def reportProp = project.findProperty('reportDir') ?: "build/reports/jacoco/external"
|
|
|
|
executionData fileTree(rootProject.rootDir) {
|
|
if (execProp) {
|
|
include execProp.toString().split(',').collect { it.trim() }
|
|
} else {
|
|
// Sensible defaults so the task is usable without props.
|
|
include '.test-state/**/*.exec'
|
|
include 'coverage-tools/exec/*.exec'
|
|
include 'testing/cucumber-coverage/*.exec'
|
|
}
|
|
}
|
|
|
|
// Pull compiled classes + sources from every subproject so the report is
|
|
// an aggregate. JaCoCo silently skips classes that have no matching .exec
|
|
// probes, so this is safe even when only a subset of code was exercised.
|
|
classDirectories.setFrom(files(subprojects.collect { sub ->
|
|
sub.fileTree(dir: "${sub.buildDir}/classes/java/main", excludes: [
|
|
'**/generated/**',
|
|
])
|
|
}))
|
|
sourceDirectories.setFrom(files(subprojects.collect { sub ->
|
|
"${sub.projectDir}/src/main/java"
|
|
}))
|
|
|
|
reports {
|
|
xml.required.set(true)
|
|
html.required.set(true)
|
|
csv.required.set(false)
|
|
xml.outputLocation.set(layout.projectDirectory.file("${reportProp}/jacocoTestReport.xml"))
|
|
html.outputLocation.set(layout.projectDirectory.dir("${reportProp}/html"))
|
|
}
|
|
}
|