diff --git a/.github/workflows/gradle-precommit.yml b/.github/workflows/gradle-precommit.yml index 3196b64d5324..c38d65ad4dc2 100644 --- a/.github/workflows/gradle-precommit.yml +++ b/.github/workflows/gradle-precommit.yml @@ -12,6 +12,7 @@ jobs: runs-on: ubuntu-latest steps: + # Setup - uses: actions/checkout@v2 - name: Set up JDK 11 uses: actions/setup-java@v1 @@ -21,3 +22,4 @@ jobs: run: chmod +x gradlew - name: Build with Gradle run: ./gradlew precommit + - uses: gradle/wrapper-validation-action@v1 diff --git a/.github/workflows/gradle-wrapper-validation.yml b/.github/workflows/gradle-wrapper-validation.yml deleted file mode 100644 index fad7221b9980..000000000000 --- a/.github/workflows/gradle-wrapper-validation.yml +++ /dev/null @@ -1,11 +0,0 @@ -name: "Validate Gradle Wrapper" -on: [push, pull_request] - -jobs: - validation: - name: "Validation" - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - uses: gradle/wrapper-validation-action@v1 - diff --git a/buildSrc/src/main/java/org/apache/lucene/gradle/WrapperDownloader.java b/buildSrc/src/main/java/org/apache/lucene/gradle/WrapperDownloader.java new file mode 100644 index 000000000000..8bbcc8d75d38 --- /dev/null +++ b/buildSrc/src/main/java/org/apache/lucene/gradle/WrapperDownloader.java @@ -0,0 +1,129 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.lucene.gradle; + +import java.io.IOException; +import java.net.URL; +import java.nio.channels.Channels; +import java.nio.channels.FileChannel; +import java.nio.channels.ReadableByteChannel; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.EnumSet; +import java.util.Locale; + +import static java.nio.file.StandardCopyOption.REPLACE_EXISTING; +import static java.nio.file.StandardOpenOption.APPEND; + +/** + * Standalone class that can be used to download a gradle-wrapper.jar + *

+ * Has no dependencies outside of standard java libraries + */ +public class WrapperDownloader { + public static void main(String[] args) { + if (args.length != 1) { + System.err.println("Usage: java WrapperDownloader.java "); + System.exit(1); + } + + try { + new WrapperDownloader().run(Paths.get(args[0])); + } catch (Exception e) { + System.err.println("ERROR: " + e.getMessage()); + System.exit(1); + } + } + + public void run(Path destination) throws IOException, NoSuchAlgorithmException { + Path checksumPath = destination.resolveSibling(destination.getFileName().toString() + ".sha256"); + if (!Files.exists(checksumPath)) { + throw new IOException("Checksum file not found: " + checksumPath); + } + String expectedChecksum = Files.readString(checksumPath, StandardCharsets.UTF_8).trim(); + + Path versionPath = destination.resolveSibling(destination.getFileName().toString() + ".version"); + if (!Files.exists(versionPath)) { + throw new IOException("Wrapper version file not found: " + versionPath); + } + String wrapperVersion = Files.readString(versionPath, StandardCharsets.UTF_8).trim(); + + MessageDigest digest = MessageDigest.getInstance("SHA-256"); + + if (Files.exists(destination)) { + if (checksum(digest, destination).equalsIgnoreCase(expectedChecksum)) { + // File exists, checksum matches, good to go! + return; + } else { + System.err.println("Checksum mismatch, will attempt to re-download gradle-wrapper.jar"); + System.out.println(destination); + Files.delete(destination); + } + } + + URL url = new URL("https://github.com/gradle/gradle/raw/v" + wrapperVersion + "/gradle/wrapper/gradle-wrapper.jar"); + System.err.println("Downloading gradle-wrapper.jar from " + url); + + // As of v6.0.1 the wrapper is approximately 60K + // Can increase this if gradle wrapper ever goes beyond 500K, but keep a safety check + final int maxSize = 512 * 1024; + + // Zero-copy save the jar to a temp file + Path temp = Files.createTempFile(destination.getParent(), ".gradle-wrapper", ".tmp"); + try { + try (ReadableByteChannel in = Channels.newChannel(url.openStream()); + FileChannel out = FileChannel.open(temp, EnumSet.of(APPEND))) { + out.transferFrom(in, 0, maxSize); + } catch (IOException e) { + throw new IOException("Could not download gradle-wrapper.jar (" + e.getMessage() + ")."); + } + + String checksum = checksum(digest, temp); + if (!checksum.equalsIgnoreCase(expectedChecksum)) { + throw new IOException(String.format(Locale.ROOT, + "Checksum mismatch on downloaded gradle-wrapper.jar (was: %s, expected: %s).", + checksum, + expectedChecksum)); + } + + Files.move(temp, destination, REPLACE_EXISTING); + temp = null; + } finally { + if (temp != null) { + Files.deleteIfExists(temp); + } + } + } + + private String checksum(MessageDigest messageDigest, Path path) throws IOException { + try { + char[] hex = "0123456789abcdef".toCharArray(); + byte[] digest = messageDigest.digest(Files.readAllBytes(path)); + StringBuilder sb = new StringBuilder(); + for (byte b : digest) { + sb.append(hex[(b >> 4) & 0xf]).append(hex[b & 0xf]); + } + return sb.toString(); + } catch (IOException e) { + throw new IOException("Could not compute digest of file: " + path + " (" + e.getMessage() + ")"); + } + } +} diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 5c2d1cf016b3..cc4fdc293d0e 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.jar.sha256 b/gradle/wrapper/gradle-wrapper.jar.sha256 new file mode 100644 index 000000000000..a9b144f3925b --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.jar.sha256 @@ -0,0 +1 @@ +28b330c20a9a73881dfe9702df78d4d78bf72368e8906c70080ab6932462fe9e \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.jar.version b/gradle/wrapper/gradle-wrapper.jar.version new file mode 100644 index 000000000000..6d54bbd77512 --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.jar.version @@ -0,0 +1 @@ +6.0.1 \ No newline at end of file diff --git a/gradlew b/gradlew index 6ccf783b2330..2d0bbb3a4286 100755 --- a/gradlew +++ b/gradlew @@ -80,8 +80,6 @@ case "`uname`" in ;; esac -CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar - # Determine the Java command to use to start the JVM. if [ -n "$JAVA_HOME" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then @@ -104,6 +102,14 @@ Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi +# LUCENE-9266: verify and download the gradle wrapper jar if we don't have one. +GRADLE_WRAPPER_JAR=$APP_HOME/gradle/wrapper/gradle-wrapper.jar +if ! $JAVACMD buildSrc/src/main/java/org/apache/lucene/gradle/WrapperDownloader.java $GRADLE_WRAPPER_JAR ; then + exit $? +fi + +CLASSPATH=$GRADLE_WRAPPER_JAR + # Don't fork a daemon mode on initial run that generates local defaults. GRADLE_DAEMON_CTRL= if [ ! -e "$APP_HOME/gradle.properties" ]; then diff --git a/gradlew.bat b/gradlew.bat index 6f874881f965..90faafb6b985 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -77,9 +77,14 @@ if "x%~1" == "x" goto execute set CMD_LINE_ARGS=%* :execute -@rem Setup the command line -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar +@rem LUCENE-9266: verify and download the gradle wrapper jar if we don't have one. +set GRADLE_WRAPPER_JAR=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar +"%JAVA_EXE%" buildSrc/src/main/java/org/apache/lucene/gradle/WrapperDownloader.java "%GRADLE_WRAPPER_JAR%" +IF %ERRORLEVEL% NEQ 0 goto fail + +@rem Setup the command line +set CLASSPATH=%GRADLE_WRAPPER_JAR% @rem Don't fork a daemon mode on initial run that generates local defaults. SET GRADLE_DAEMON_CTRL= diff --git a/solr/build.xml b/solr/build.xml index f20727e65623..74fbe60f2375 100644 --- a/solr/build.xml +++ b/solr/build.xml @@ -459,7 +459,7 @@ fullpath="${fullnamever}/solr/LUCENE_CHANGES.txt" /> + excludes="solr/example/**/*.sh solr/example/**/bin/ solr/scripts/** gradle/wrapper/gradle-wrapper.jar"/>