diff --git a/renovate.json b/.github/renovate.json5 similarity index 82% rename from renovate.json rename to .github/renovate.json5 index 39a2b6e9a..d09a6b53f 100644 --- a/renovate.json +++ b/.github/renovate.json5 @@ -1,6 +1,6 @@ { "$schema": "https://docs.renovatebot.com/renovate-schema.json", "extends": [ - "config:base" + "config:base", ] } diff --git a/.github/workflows/gradle-wrapper-validation.yml b/.github/workflows/gradle-wrapper-validation.yml index c82936bc9..ed844d98d 100644 --- a/.github/workflows/gradle-wrapper-validation.yml +++ b/.github/workflows/gradle-wrapper-validation.yml @@ -17,4 +17,4 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - uses: gradle/wrapper-validation-action@v2 + - uses: gradle/actions/wrapper-validation@v3 diff --git a/build.gradle b/build.gradle index 2677a4ee1..b1979a1de 100644 --- a/build.gradle +++ b/build.gradle @@ -23,6 +23,9 @@ apply from: file('gradle/dependencies.gradle') tasks.withType(Test).configureEach { useJUnitPlatform() + // https://docs.gradle.org/8.8/userguide/performance.html#execute_tests_in_parallel + maxParallelForks = Runtime.runtime.availableProcessors().intdiv(2) ?: 1 + if (System.env.CI == 'true') { testLogging.showStandardStreams = true minHeapSize "1g" diff --git a/gradle/dependencies.gradle b/gradle/dependencies.gradle index 948c3749d..9ddaf369a 100644 --- a/gradle/dependencies.gradle +++ b/gradle/dependencies.gradle @@ -4,13 +4,13 @@ dependencies { shadow 'org.codehaus.groovy:groovy-backports-compat23:3.0.8' implementation 'org.jdom:jdom2:2.0.6.1' - implementation 'org.ow2.asm:asm:9.6' - implementation 'org.ow2.asm:asm-commons:9.6' - implementation 'commons-io:commons-io:2.15.1' + implementation 'org.ow2.asm:asm:9.7' + implementation 'org.ow2.asm:asm-commons:9.7' + implementation 'commons-io:commons-io:2.16.1' implementation 'org.apache.ant:ant:1.10.14' - implementation 'org.codehaus.plexus:plexus-utils:4.0.0' - implementation 'org.codehaus.plexus:plexus-xml:4.0.3' - implementation "org.apache.logging.log4j:log4j-core:2.23.0" + implementation 'org.codehaus.plexus:plexus-utils:4.0.1' + implementation 'org.codehaus.plexus:plexus-xml:4.0.4' + implementation "org.apache.logging.log4j:log4j-core:2.23.1" implementation('org.vafer:jdependency:2.10') { exclude group: 'org.ow2.asm' } @@ -21,7 +21,7 @@ dependencies { testImplementation 'org.spockframework:spock-junit4:2.3-groovy-3.0' testImplementation 'xmlunit:xmlunit:1.6' testImplementation 'org.apache.commons:commons-lang3:3.14.0' - testImplementation 'com.google.guava:guava:33.0.0-jre' + testImplementation 'com.google.guava:guava:33.2.1-jre' testImplementation 'org.junit.jupiter:junit-jupiter-api:5.10.2' testRuntimeOnly 'org.junit.vintage:junit-vintage-engine:5.10.2' testRuntimeOnly 'org.junit.platform:junit-platform-launcher' diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index d64cd4917..e6441136f 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index a80b22ce5..a4413138c 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/gradlew b/gradlew index 1aa94a426..b740cf133 100755 --- a/gradlew +++ b/gradlew @@ -55,7 +55,7 @@ # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # within the Gradle project. # # You can find Gradle at https://github.com/gradle/gradle/. diff --git a/gradlew.bat b/gradlew.bat index 6689b85be..7101f8e46 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -43,11 +43,11 @@ set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 if %ERRORLEVEL% equ 0 goto execute -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail @@ -57,11 +57,11 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe if exist "%JAVA_EXE%" goto execute -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail diff --git a/settings.gradle b/settings.gradle index c61e7eed8..3675a13e5 100644 --- a/settings.gradle +++ b/settings.gradle @@ -6,7 +6,7 @@ pluginManagement { } plugins { - id 'com.gradle.enterprise' version '3.16.2' + id 'com.gradle.develocity' version '3.17.5' } dependencyResolutionManagement { @@ -15,12 +15,14 @@ dependencyResolutionManagement { } } -gradleEnterprise { +def isCI = providers.environmentVariable('CI').present + +develocity { buildScan { - termsOfServiceUrl = 'https://gradle.com/terms-of-service' - termsOfServiceAgree = 'yes' - publishAlways() - if (System.env.CI == 'true') { + termsOfUseUrl = 'https://gradle.com/terms-of-service' + termsOfUseAgree = 'yes' + publishing.onlyIf { isCI } + if (isCI) { tag 'CI' if (System.env.CIRCLE_TAG) { link 'VCS', "https://github.com/johnrengelman/shadow/tree/${System.env.CIRCLE_TAG}" diff --git a/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/ShadowPlugin.groovy b/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/ShadowPlugin.groovy index 1191afc94..36ced5f5d 100644 --- a/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/ShadowPlugin.groovy +++ b/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/ShadowPlugin.groovy @@ -6,8 +6,6 @@ import org.gradle.api.Project import org.gradle.api.plugins.ApplicationPlugin import org.gradle.api.plugins.JavaPlugin -import static java.util.Objects.nonNull - class ShadowPlugin implements Plugin { @Override @@ -21,17 +19,25 @@ class ShadowPlugin implements Plugin { plugins.apply(ShadowApplicationPlugin) } + // Legacy build scan support for Gradle Enterprise, users should migrate to develocity plugin. rootProject.plugins.withId('com.gradle.enterprise') { - rootProject.buildScan.buildFinished { - def shadowTasks = tasks.withType(ShadowJar) - shadowTasks.each { task -> - if (task.didWork) { - task.stats.buildScanData.each { k, v -> - rootProject.buildScan.value "shadow.${task.path}.${k}", v.toString() - } - rootProject.buildScan.value "shadow.${task.path}.configurations", task.configurations*.name.join(", ") - } + configureBuildScan(rootProject) + } + rootProject.plugins.withId('com.gradle.develocity') { + configureBuildScan(rootProject) + } + } + } + + private void configureBuildScan(Project rootProject) { + rootProject.buildScan.buildFinished { + def shadowTasks = tasks.withType(ShadowJar) + shadowTasks.each { task -> + if (task.didWork) { + task.stats.buildScanData.each { k, v -> + rootProject.buildScan.value "shadow.${task.path}.${k}", v.toString() } + rootProject.buildScan.value "shadow.${task.path}.configurations", task.configurations*.name.join(", ") } } } diff --git a/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/internal/CleanProperties.groovy b/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/internal/CleanProperties.groovy index 5bed7a56d..b54b5271b 100644 --- a/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/internal/CleanProperties.groovy +++ b/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/internal/CleanProperties.groovy @@ -1,32 +1,34 @@ -/* - * Source https://stackoverflow.com/a/39043903/519333 - */ package com.github.jengelman.gradle.plugins.shadow.internal class CleanProperties extends Properties { - private static class StripFirstLineStream extends FilterOutputStream { - private boolean firstLineSeen = false + private static class StripCommentsWithTimestampBufferedWriter extends BufferedWriter { - StripFirstLineStream(final OutputStream out) { + private final int lengthOfExpectedTimestamp + + StripCommentsWithTimestampBufferedWriter(final Writer out) { super(out) + + lengthOfExpectedTimestamp = ("#" + new Date().toString()).length() } @Override - void write(final int b) throws IOException { - if (firstLineSeen) { - super.write(b) - } else if (b == '\n') { - super.write(b) - - firstLineSeen = true + void write(final String str) throws IOException { + if (couldBeCommentWithTimestamp(str)) { + return } + super.write(str) } + private boolean couldBeCommentWithTimestamp(final String str) { + return str != null && + str.startsWith("#") && + str.length() == lengthOfExpectedTimestamp + } } @Override - void store(final OutputStream out, final String comments) throws IOException { - super.store(new StripFirstLineStream(out), null) + void store(final Writer writer, final String comments) throws IOException { + super.store(new StripCommentsWithTimestampBufferedWriter(writer), comments) } } diff --git a/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/transformers/PropertiesFileTransformerTest.groovy b/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/transformers/PropertiesFileTransformerTest.groovy index ff23aed96..a57ee221d 100644 --- a/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/transformers/PropertiesFileTransformerTest.groovy +++ b/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/transformers/PropertiesFileTransformerTest.groovy @@ -40,21 +40,42 @@ final class PropertiesFileTransformerTest extends TransformerTestSupport { void testTransformation() { transformer.transform(new TransformerContext(MANIFEST_NAME, getResourceStream(MANIFEST_NAME), Collections.emptyList(), new ShadowStats())) + def testableZipFile = doTransformAndGetTransformedFile(transformer, false) + def targetLines = readFrom(testableZipFile, MANIFEST_NAME) + + assertFalse(targetLines.isEmpty()) + + assertTrue(targetLines.contains("Manifest-Version=1.0")) + } + + @Test + void testTransformationPropertiesAreReproducible() { + transformer.transform(new TransformerContext(MANIFEST_NAME, getResourceStream(MANIFEST_NAME), Collections.emptyList(), new ShadowStats())) + + def firstRunTransformedFile = doTransformAndGetTransformedFile(transformer, true) + def firstRunTargetLines = readFrom(firstRunTransformedFile, MANIFEST_NAME) + + Thread.sleep(1000) // wait for 1sec to ensure timestamps in properties would change + + def secondRunTransformedFile = doTransformAndGetTransformedFile(transformer, true) + def secondRunTargetLines = readFrom(secondRunTransformedFile, MANIFEST_NAME) + + assertEquals(firstRunTargetLines, secondRunTargetLines) + } + + static File doTransformAndGetTransformedFile(final PropertiesFileTransformer transformer, final boolean preserveFileTimestamps) { def testableZipFile = File.createTempFile("testable-zip-file-", ".jar") def fileOutputStream = new FileOutputStream(testableZipFile) def bufferedOutputStream = new BufferedOutputStream(fileOutputStream) def zipOutputStream = new ZipOutputStream(bufferedOutputStream) try { - transformer.modifyOutputStream(zipOutputStream, false) + transformer.modifyOutputStream(zipOutputStream, preserveFileTimestamps) } finally { zipOutputStream.close() } - def targetLines = readFrom(testableZipFile, MANIFEST_NAME) - - assertFalse(targetLines.isEmpty()) - assertTrue(targetLines.contains("Manifest-Version=1.0")) + return testableZipFile } static List readFrom(File jarFile, String resourceName) {