You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@grails.apache.org by jd...@apache.org on 2025/05/30 19:29:15 UTC

(grails-core) branch 7.0.x updated (03c621be30 -> 793b6fd0d9)

This is an automated email from the ASF dual-hosted git repository.

jdaugherty pushed a change to branch 7.0.x
in repository https://gitbox.apache.org/repos/asf/grails-core.git


    from 03c621be30 [skip ci] - Update headers, LICENSE and NOTICE for files from Spring Framework 5.3.x
     new 6593c67d87 [skip ci] add helper script to download
     new 3a6cbfb497 [skip ci] add source distribution verification
     new 83ed77c94b [skip ci] rework source distribution to verify with keys file
     new d43130d01b [skip ci] fix checksum / artifact list
     new 2e61ff2a59 [skip ci] scripts to automate jar file verification
     new 793b6fd0d9 [skip ci] wrapper verification automation

The 6 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .github/workflows/release.yml                      |   3 +-
 RELEASE.md                                         | 108 ++++++++++++++-------
 etc/bin/download-release-artifacts.sh              |  49 ++++++++++
 etc/bin/verify-jar-artifacts.sh                    | 102 +++++++++++++++++++
 ...rify-distribution.sh => verify-reproducible.sh} |   0
 etc/bin/verify-source-distribution.sh              |  78 +++++++++++++++
 etc/bin/verify-wrapper-distribution.sh             |  78 +++++++++++++++
 gradle/publish-config.gradle                       |   8 ++
 grails-gradle/gradle/checksum-config.gradle        |   7 ++
 9 files changed, 395 insertions(+), 38 deletions(-)
 create mode 100755 etc/bin/download-release-artifacts.sh
 create mode 100755 etc/bin/verify-jar-artifacts.sh
 rename etc/bin/{verify-distribution.sh => verify-reproducible.sh} (100%)
 create mode 100755 etc/bin/verify-source-distribution.sh
 create mode 100755 etc/bin/verify-wrapper-distribution.sh


(grails-core) 03/06: [skip ci] rework source distribution to verify with keys file

Posted by jd...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

jdaugherty pushed a commit to branch 7.0.x
in repository https://gitbox.apache.org/repos/asf/grails-core.git

commit 83ed77c94bc735e6833b7db13e9ae628ef8a997e
Author: James Daugherty <jd...@jdresources.net>
AuthorDate: Fri May 30 15:05:09 2025 -0400

    [skip ci] rework source distribution to verify with keys file
---
 etc/bin/verify-source-distribution.sh | 16 ++++++++++++++--
 1 file changed, 14 insertions(+), 2 deletions(-)

diff --git a/etc/bin/verify-source-distribution.sh b/etc/bin/verify-source-distribution.sh
index 608e578318..d8c2c2a6e6 100755
--- a/etc/bin/verify-source-distribution.sh
+++ b/etc/bin/verify-source-distribution.sh
@@ -21,6 +21,7 @@ set -euo pipefail
 
 RELEASE_TAG=$1
 DOWNLOAD_LOCATION="${2:-downloads}"
+SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
 
 if [ -z "${RELEASE_TAG}" ]; then
   echo "Usage: $0 [release-tag] <optional download location>"
@@ -37,11 +38,20 @@ if [ -z "$ZIP_FILE" ]; then
   exit 1
 fi
 
+export GRAILS_GPG_HOME=$(mktemp -d)
+cleanup() {
+  rm -rf "${GRAILS_GPG_HOME}"
+}
+trap cleanup EXIT
+
 echo "Verifying checksum..."
 shasum -a 512 -c "apache-grails-${VERSION}-incubating-src.zip.sha512"
+echo "✅ Checksum Verified"
 
 echo "Verifying GPG signature..."
-gpg --verify "apache-grails-${VERSION}-incubating-src.zip.asc" "apache-grails-${VERSION}-incubating-src.zip"
+gpg --homedir "${GRAILS_GPG_HOME}" --import "${SCRIPT_DIR}/../../KEYS"
+gpg --homedir "${GRAILS_GPG_HOME}" --verify "apache-grails-${VERSION}-incubating-src.zip.asc" "apache-grails-${VERSION}-incubating-src.zip"
+echo "✅ GPG Verified"
 
 rm -rf grails || true
 echo "Extracting zip file..."
@@ -61,6 +71,8 @@ for FILE in "${REQUIRED_FILES[@]}"; do
     echo "Missing required file: $FILE"
     exit 1
   fi
+
+  echo "✅ Found required file: $FILE"
 done
 
-echo "✅ All checks passed successfully for Apache Grails ${VERSION}."
\ No newline at end of file
+echo "✅ All source distribution checks passed successfully for Apache Grails ${VERSION}."
\ No newline at end of file


(grails-core) 04/06: [skip ci] fix checksum / artifact list

Posted by jd...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

jdaugherty pushed a commit to branch 7.0.x
in repository https://gitbox.apache.org/repos/asf/grails-core.git

commit d43130d01b80714bdb46a67aa019cfc8ee00cd9b
Author: James Daugherty <jd...@jdresources.net>
AuthorDate: Fri May 30 15:13:56 2025 -0400

    [skip ci] fix checksum / artifact list
---
 gradle/publish-config.gradle                | 8 ++++++++
 grails-gradle/gradle/checksum-config.gradle | 7 +++++++
 2 files changed, 15 insertions(+)

diff --git a/gradle/publish-config.gradle b/gradle/publish-config.gradle
index a97c99cbde..a592702510 100644
--- a/gradle/publish-config.gradle
+++ b/gradle/publish-config.gradle
@@ -53,6 +53,9 @@ afterEvaluate {
             List filesToChecksum = []
             publishing.publications.withType(MavenPublication).all { MavenPublication publication ->
                 publication.artifacts.each { MavenArtifact artifact ->
+                    if(artifact.file.name == 'grails-plugin.xml') {
+                        return
+                    }
                     filesToChecksum << artifact.file
                 }
             }
@@ -60,6 +63,7 @@ afterEvaluate {
             checksumTask.configure { Checksum check ->
                 check.inputFiles.setFrom(filesToChecksum.unique())
                 check.finalizedBy(artifactsTask)
+
             }
 
             artifactsTask.configure {
@@ -67,6 +71,10 @@ afterEvaluate {
                     Map<String, String> artifacts = [:]
                     project.publishing.publications.withType(MavenPublication).all { MavenPublication publication ->
                         publication.artifacts.each { MavenArtifact artifact ->
+                            if(!artifact.file.exists() || artifact.file.name == 'grails-plugin.xml') {
+                                return
+                            }
+
                             if(artifact.classifier) {
                                 artifacts[artifact.file.name] = "${publication.groupId}:${publication.artifactId}:${publication.version}:${artifact.classifier}" as String
                             }
diff --git a/grails-gradle/gradle/checksum-config.gradle b/grails-gradle/gradle/checksum-config.gradle
index 26f6ee7f8b..066bd4091b 100644
--- a/grails-gradle/gradle/checksum-config.gradle
+++ b/grails-gradle/gradle/checksum-config.gradle
@@ -39,6 +39,9 @@ afterEvaluate {
             List filesToChecksum = []
             publishing.publications.withType(MavenPublication).all { MavenPublication publication ->
                 publication.artifacts.each { MavenArtifact artifact ->
+                    if(artifact.file.name == 'grails-plugin.xml') {
+                        return
+                    }
                     filesToChecksum << artifact.file
                 }
             }
@@ -53,6 +56,10 @@ afterEvaluate {
                     Map<String, String> artifacts = [:]
                     project.publishing.publications.withType(MavenPublication).all { MavenPublication publication ->
                         publication.artifacts.each { MavenArtifact artifact ->
+                            if(!artifact.file.exists() || artifact.file.name == 'grails-plugin.xml') {
+                                return
+                            }
+
                             if(artifact.classifier) {
                                 artifacts[artifact.file.name] = "${publication.groupId}:${publication.artifactId}:${publication.version}:${artifact.classifier}" as String
                             }


(grails-core) 02/06: [skip ci] add source distribution verification

Posted by jd...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

jdaugherty pushed a commit to branch 7.0.x
in repository https://gitbox.apache.org/repos/asf/grails-core.git

commit 3a6cbfb497beeb7f0f42bc5e4d9faecd1a0f8c3f
Author: James Daugherty <jd...@jdresources.net>
AuthorDate: Fri May 30 14:40:34 2025 -0400

    [skip ci] add source distribution verification
---
 etc/bin/verify-source-distribution.sh | 66 +++++++++++++++++++++++++++++++++++
 1 file changed, 66 insertions(+)

diff --git a/etc/bin/verify-source-distribution.sh b/etc/bin/verify-source-distribution.sh
new file mode 100755
index 0000000000..608e578318
--- /dev/null
+++ b/etc/bin/verify-source-distribution.sh
@@ -0,0 +1,66 @@
+#!/usr/bin/env bash
+#
+#  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
+#
+#    https://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.
+#
+set -euo pipefail
+
+RELEASE_TAG=$1
+DOWNLOAD_LOCATION="${2:-downloads}"
+
+if [ -z "${RELEASE_TAG}" ]; then
+  echo "Usage: $0 [release-tag] <optional download location>"
+  exit 1
+fi
+
+VERSION=${RELEASE_TAG#v}
+
+cd $DOWNLOAD_LOCATION
+ZIP_FILE=$(ls "apache-grails-${VERSION}-incubating-src.zip" 2>/dev/null | head -n 1)
+
+if [ -z "$ZIP_FILE" ]; then
+  echo "Error: Could not find apache-grails-${VERSION}-incubating-src.zip in $DOWNLOAD_LOCATION"
+  exit 1
+fi
+
+echo "Verifying checksum..."
+shasum -a 512 -c "apache-grails-${VERSION}-incubating-src.zip.sha512"
+
+echo "Verifying GPG signature..."
+gpg --verify "apache-grails-${VERSION}-incubating-src.zip.asc" "apache-grails-${VERSION}-incubating-src.zip"
+
+rm -rf grails || true
+echo "Extracting zip file..."
+unzip -q "apache-grails-${VERSION}-incubating-src.zip"
+
+SRC_DIR="grails"
+if [ ! -d "$SRC_DIR" ]; then
+  echo "Error: Expected extracted folder '$SRC_DIR' not found."
+  exit 1
+fi
+
+echo "Checking for required files existence..."
+REQUIRED_FILES=("LICENSE" "NOTICE" "README.md" "CONTRIBUTING.md" "PUBLISHED_ARTIFACTS" "CHECKSUMS")
+
+for FILE in "${REQUIRED_FILES[@]}"; do
+  if [ ! -f "$SRC_DIR/$FILE" ]; then
+    echo "Missing required file: $FILE"
+    exit 1
+  fi
+done
+
+echo "✅ All checks passed successfully for Apache Grails ${VERSION}."
\ No newline at end of file


(grails-core) 06/06: [skip ci] wrapper verification automation

Posted by jd...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

jdaugherty pushed a commit to branch 7.0.x
in repository https://gitbox.apache.org/repos/asf/grails-core.git

commit 793b6fd0d94cda3c17b929c8d9260b4b8de8d105
Author: James Daugherty <jd...@jdresources.net>
AuthorDate: Fri May 30 15:28:55 2025 -0400

    [skip ci] wrapper verification automation
---
 .github/workflows/release.yml                      |  3 ++-
 RELEASE.md                                         | 31 +++++++++++++++++++++-
 etc/bin/verify-source-distribution.sh              | 12 ++++-----
 ...tribution.sh => verify-wrapper-distribution.sh} | 26 +++++++++---------
 4 files changed, 51 insertions(+), 21 deletions(-)

diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 8e51b9ecd4..f2d8d84bc0 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -77,7 +77,8 @@ jobs:
           gpg --default-key "${GPG_KEY_ID}" --batch --yes --pinentry-mode loopback --armor --detach-sign grails-wrapper/build/distributions/apache-grails-wrapper-${{ steps.release_version.outputs.value }}-incubating-bin.zip
       - name: "📦 Create wrapper checksum"
         run: |
-          sha512sum grails-wrapper/build/distributions/apache-grails-wrapper-${{ steps.release_version.outputs.value }}-incubating-bin.zip > "grails-wrapper/build/distributions/apache-grails-wrapper-${{ steps.release_version.outputs.value }}-incubating-bin.zip.sha512"
+          cd grails-wrapper/build/distributions
+          sha512sum apache-grails-wrapper-${{ steps.release_version.outputs.value }}-incubating-bin.zip > "apache-grails-wrapper-${{ steps.release_version.outputs.value }}-incubating-bin.zip.sha512"
       - name: "📤 Upload grails wrapper ZIP"
         uses: softprops/action-gh-release@v2
         with:
diff --git a/RELEASE.md b/RELEASE.md
index f203600f23..cb37d25815 100644
--- a/RELEASE.md
+++ b/RELEASE.md
@@ -70,7 +70,7 @@ Use `etc/bin/download-release-artifacts.sh` to download the staged artifacts. Th
 
 The following are the source distribution artifacts:
    * `apache-grails-<version>-incubating-src.zip` - the source distribution
-   * `apache-grails-<version>-incubating-src.zip.asc` - the public key to verify the source distribution
+   * `apache-grails-<version>-incubating-src.zip.asc` - the generated signature of the source distribution
    * `apache-grails-<version>-incubating-src.zip.sha512` - the checksum to verify the source distribution
 
 Use `etc/bin/verify-source-distribution.sh` to verify the source distribution. This script performs the following:
@@ -113,6 +113,35 @@ Bootstrap the source distribution so that it can be built:
 Run the `verify-reproducible.sh` shell script to compare the published jar files to a locally built version of them. For any differences, extract the jar files, use IntelliJ to compare each differing file. Assuming differences are ordering related, we can continue with the verification.
 
 ### Binary Distribution Verification
+
+Grails has 2 binary distributions:
+   * `grailsw` - the Grails wrapper, which is a script that downloads the necessary jars to run Grails. This will exist inside of the generated applications, but can be optionally downloaded as a standalone binary distribution.
+   * `grails` - the delegating CLI, which is a script that delegates to the Grails Forge CLI. This is the `sdkman` distribution.
+
+#### Verify Grails Wrapper Binary Distribution
+
+The following are the Grails Wrapper distribution artifacts:
+* `apache-grails-wrapper-<version>-incubating-bin.zip` - the wrapper distribution
+* `apache-grails-wrapper-<version>-incubating-bin.zip.asc` - the generated signature of the source distribution
+* `apache-grails-wrapper-<version>-incubating-bin.zip.sha512` - the checksum to verify the source distribution
+
+Use `etc/bin/verify-wrapper-distribution.sh` to verify the wrapper distribution. This script performs the following:
+
+Verifies the wrapper distribution checksum via the command:
+   ```bash
+   shasum -a 512 -c apache-grails-wrapper-<version>-incubating-bin.zip.sha512
+   ```
+
+Verifies the wrapper distribution signature via the command:
+   ```bash
+    gpg --verify apache-grails-wrapper-<version>-incubating-bin.zip.asc apache-grails-<version>-incubating-bin.zip
+   ```
+
+Extracts the zip file and verifies the contents:
+* Ensure the `LICENSE` & `NOTICE` files are present to ensure license compliance.
+
+#### Verify Grails Delegating CLI Binary Distribution
+
 Download the binary distribution & expand it to test the various CLI's: `grailsw` (wrapper), `grails` (delegating), `grails-forge-cli`, and `grails-shell-cli`.  For each CLI, verify the published signature in the `PUBLISHED` file:
    ```bash
     gpg --verify <cli>.asc <cli>
diff --git a/etc/bin/verify-source-distribution.sh b/etc/bin/verify-source-distribution.sh
index d8c2c2a6e6..c05827f456 100755
--- a/etc/bin/verify-source-distribution.sh
+++ b/etc/bin/verify-source-distribution.sh
@@ -53,13 +53,13 @@ gpg --homedir "${GRAILS_GPG_HOME}" --import "${SCRIPT_DIR}/../../KEYS"
 gpg --homedir "${GRAILS_GPG_HOME}" --verify "apache-grails-${VERSION}-incubating-src.zip.asc" "apache-grails-${VERSION}-incubating-src.zip"
 echo "✅ GPG Verified"
 
-rm -rf grails || true
+SRC_DIR="grails"
+rm -rf "${SRC_DIR}" || true
 echo "Extracting zip file..."
 unzip -q "apache-grails-${VERSION}-incubating-src.zip"
 
-SRC_DIR="grails"
-if [ ! -d "$SRC_DIR" ]; then
-  echo "Error: Expected extracted folder '$SRC_DIR' not found."
+if [ ! -d "${SRC_DIR}" ]; then
+  echo "Error: Expected extracted folder '${SRC_DIR}' not found."
   exit 1
 fi
 
@@ -67,8 +67,8 @@ echo "Checking for required files existence..."
 REQUIRED_FILES=("LICENSE" "NOTICE" "README.md" "CONTRIBUTING.md" "PUBLISHED_ARTIFACTS" "CHECKSUMS")
 
 for FILE in "${REQUIRED_FILES[@]}"; do
-  if [ ! -f "$SRC_DIR/$FILE" ]; then
-    echo "Missing required file: $FILE"
+  if [ ! -f "${SRC_DIR}/$FILE" ]; then
+    echo "❌ Missing required file: $FILE"
     exit 1
   fi
 
diff --git a/etc/bin/verify-source-distribution.sh b/etc/bin/verify-wrapper-distribution.sh
similarity index 64%
copy from etc/bin/verify-source-distribution.sh
copy to etc/bin/verify-wrapper-distribution.sh
index d8c2c2a6e6..064228c92f 100755
--- a/etc/bin/verify-source-distribution.sh
+++ b/etc/bin/verify-wrapper-distribution.sh
@@ -31,10 +31,10 @@ fi
 VERSION=${RELEASE_TAG#v}
 
 cd $DOWNLOAD_LOCATION
-ZIP_FILE=$(ls "apache-grails-${VERSION}-incubating-src.zip" 2>/dev/null | head -n 1)
+ZIP_FILE=$(ls "apache-grails-wrapper-${VERSION}-incubating-bin.zip" 2>/dev/null | head -n 1)
 
 if [ -z "$ZIP_FILE" ]; then
-  echo "Error: Could not find apache-grails-${VERSION}-incubating-src.zip in $DOWNLOAD_LOCATION"
+  echo "Error: Could not find apache-grails-wrapper-${VERSION}-incubating-bin.zip in $DOWNLOAD_LOCATION"
   exit 1
 fi
 
@@ -45,34 +45,34 @@ cleanup() {
 trap cleanup EXIT
 
 echo "Verifying checksum..."
-shasum -a 512 -c "apache-grails-${VERSION}-incubating-src.zip.sha512"
+shasum -a 512 -c "apache-grails-wrapper-${VERSION}-incubating-bin.zip.sha512"
 echo "✅ Checksum Verified"
 
 echo "Verifying GPG signature..."
 gpg --homedir "${GRAILS_GPG_HOME}" --import "${SCRIPT_DIR}/../../KEYS"
-gpg --homedir "${GRAILS_GPG_HOME}" --verify "apache-grails-${VERSION}-incubating-src.zip.asc" "apache-grails-${VERSION}-incubating-src.zip"
+gpg --homedir "${GRAILS_GPG_HOME}" --verify "apache-grails-wrapper-${VERSION}-incubating-bin.zip.asc" "apache-grails-wrapper-${VERSION}-incubating-bin.zip"
 echo "✅ GPG Verified"
 
-rm -rf grails || true
+SRC_DIR="apache-grails-wrapper-${VERSION}-incubating-bin"
+rm -rf "${SRC_DIR}" || true
 echo "Extracting zip file..."
-unzip -q "apache-grails-${VERSION}-incubating-src.zip"
+unzip -q "apache-grails-wrapper-${VERSION}-incubating-bin.zip"
 
-SRC_DIR="grails"
-if [ ! -d "$SRC_DIR" ]; then
-  echo "Error: Expected extracted folder '$SRC_DIR' not found."
+if [ ! -d "${SRC_DIR}" ]; then
+  echo "Error: Expected extracted folder '${SRC_DIR}' not found."
   exit 1
 fi
 
 echo "Checking for required files existence..."
-REQUIRED_FILES=("LICENSE" "NOTICE" "README.md" "CONTRIBUTING.md" "PUBLISHED_ARTIFACTS" "CHECKSUMS")
+REQUIRED_FILES=("LICENSE" "NOTICE")
 
 for FILE in "${REQUIRED_FILES[@]}"; do
-  if [ ! -f "$SRC_DIR/$FILE" ]; then
-    echo "Missing required file: $FILE"
+  if [ ! -f "${SRC_DIR}/$FILE" ]; then
+    echo "❌ Missing required file: $FILE"
     exit 1
   fi
 
   echo "✅ Found required file: $FILE"
 done
 
-echo "✅ All source distribution checks passed successfully for Apache Grails ${VERSION}."
\ No newline at end of file
+echo "✅ All wrapper binary distribution checks passed successfully for Apache Grails ${VERSION}."
\ No newline at end of file


(grails-core) 01/06: [skip ci] add helper script to download

Posted by jd...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

jdaugherty pushed a commit to branch 7.0.x
in repository https://gitbox.apache.org/repos/asf/grails-core.git

commit 6593c67d8766e870fef9bdad7e80f8582f3bc871
Author: James Daugherty <jd...@jdresources.net>
AuthorDate: Fri May 30 14:40:27 2025 -0400

    [skip ci] add helper script to download
---
 etc/bin/download-release-artifacts.sh | 49 +++++++++++++++++++++++++++++++++++
 1 file changed, 49 insertions(+)

diff --git a/etc/bin/download-release-artifacts.sh b/etc/bin/download-release-artifacts.sh
new file mode 100755
index 0000000000..0bbf31dd01
--- /dev/null
+++ b/etc/bin/download-release-artifacts.sh
@@ -0,0 +1,49 @@
+#!/usr/bin/env bash
+#
+#  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
+#
+#    https://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.
+#
+set -e
+
+RELEASE_TAG=$1
+DOWNLOAD_LOCATION="${2:-downloads}"
+
+if [ -z "${RELEASE_TAG}" ]; then
+  echo "Usage: $0 [release-tag] <optional download location>"
+  exit 1
+fi
+
+echo "Downloading files to ${DOWNLOAD_LOCATION}"
+mkdir -p "${DOWNLOAD_LOCATION}"
+
+VERSION=${RELEASE_TAG#v}
+
+# Source distro
+curl -L -o "${DOWNLOAD_LOCATION}/apache-grails-$VERSION-incubating-src.zip" "https://github.com/apache/grails-core/releases/download/$RELEASE_TAG/apache-grails-$VERSION-incubating-src.zip"
+curl -L -o "${DOWNLOAD_LOCATION}/apache-grails-$VERSION-incubating-src.zip.asc" "https://github.com/apache/grails-core/releases/download/$RELEASE_TAG/apache-grails-$VERSION-incubating-src.zip.asc"
+curl -L -o "${DOWNLOAD_LOCATION}/apache-grails-$VERSION-incubating-src.zip.sha512" "https://github.com/apache/grails-core/releases/download/$RELEASE_TAG/apache-grails-$VERSION-incubating-src.zip.sha512"
+
+# wrapper
+curl -L -o "${DOWNLOAD_LOCATION}/apache-grails-wrapper-$VERSION-incubating-bin.zip" "https://github.com/apache/grails-core/releases/download/$RELEASE_TAG/apache-grails-wrapper-$VERSION-incubating-bin.zip"
+curl -L -o "${DOWNLOAD_LOCATION}/apache-grails-wrapper-$VERSION-incubating-bin.zip.asc" "https://github.com/apache/grails-core/releases/download/$RELEASE_TAG/apache-grails-wrapper-$VERSION-incubating-bin.zip.asc"
+curl -L -o "${DOWNLOAD_LOCATION}/apache-grails-wrapper-$VERSION-incubating-bin.zip.sha512" "https://github.com/apache/grails-core/releases/download/$RELEASE_TAG/apache-grails-wrapper-$VERSION-incubating-bin.zip.sha512"
+
+# checksums
+curl -L -o "${DOWNLOAD_LOCATION}/CHECKSUMS.txt" "https://github.com/apache/grails-core/releases/download/$RELEASE_TAG/CHECKSUMS.txt"
+
+# published artifacts
+curl -L -o "${DOWNLOAD_LOCATION}/PUBLISHED_ARTIFACTS.txt" "https://github.com/apache/grails-core/releases/download/$RELEASE_TAG/PUBLISHED_ARTIFACTS.txt"
\ No newline at end of file


(grails-core) 05/06: [skip ci] scripts to automate jar file verification

Posted by jd...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

jdaugherty pushed a commit to branch 7.0.x
in repository https://gitbox.apache.org/repos/asf/grails-core.git

commit 2e61ff2a599151f5e2dfa2ed06554199f2c6bb6a
Author: James Daugherty <jd...@jdresources.net>
AuthorDate: Fri May 30 15:19:25 2025 -0400

    [skip ci] scripts to automate jar file verification
---
 RELEASE.md                                         |  77 ++++++++--------
 etc/bin/verify-jar-artifacts.sh                    | 102 +++++++++++++++++++++
 ...rify-distribution.sh => verify-reproducible.sh} |   0
 3 files changed, 143 insertions(+), 36 deletions(-)

diff --git a/RELEASE.md b/RELEASE.md
index 77e94e8942..f203600f23 100644
--- a/RELEASE.md
+++ b/RELEASE.md
@@ -62,61 +62,44 @@ During the staging step, we must create a source distribution & stage any binary
 
 Prior to releasing a vote, we need to verify the staged artifacts. Follow the below steps to verify each staged artifact.
 
+### Download the Staged Artifacts
+
+Use `etc/bin/download-release-artifacts.sh` to download the staged artifacts. This script will download the source distribution, wrapper binary distribution, and sdkman binary distribution. The distribution should come from [https://dist.apache.org/repos/dist/dev/grails/version](https://dist.apache.org/repos/dist/dev/grails).
+
 ### Source Distribution Verification
-Download the zipped source distribution artifacts:
+
+The following are the source distribution artifacts:
    * `apache-grails-<version>-incubating-src.zip` - the source distribution
    * `apache-grails-<version>-incubating-src.zip.asc` - the public key to verify the source distribution
    * `apache-grails-<version>-incubating-src.zip.sha512` - the checksum to verify the source distribution
 
-from [https://dist.apache.org/repos/dist/dev/grails/version](https://dist.apache.org/repos/dist/dev/grails)
+Use `etc/bin/verify-source-distribution.sh` to verify the source distribution. This script performs the following:
 
-Verify the source distribution checksum via the command:
+Verifies the source distribution checksum via the command:
    ```bash
    shasum -a 512 -c apache-grails-<version>-incubating-src.zip.sha512
    ```
 
-Verify the source distribution signature via the command:
+Verifies the source distribution signature via the command:
    ```bash
     gpg --verify apache-grails-<version>-incubating-src.zip.asc apache-grails-<version>-incubating-src.zip
    ```
 
-Extract the zip file and verify the contents:
+Extracts the zip file and verifies the contents:
    * Ensure the `LICENSE` & `NOTICE` files are present to ensure license compliance.
    * Ensure `README.md` & `CONTRIBUTING.md` are present to ensure project build & usage instructions are present.
-   * Ensure the `PUBLISHED` file is present so we know how to pull the various jar files.
+   * Ensure the `PUBLISHED_ARTIFACTS` file is present so we know how to pull the various jar files.
+   * Ensure the `CHECKSUMS` file is present so we can ensure those checksums match the staged artifacts.
 
 ### Jar file Signature Verification (Nexus Staging Repositories)
-As part of uploading to repository.apache.org the signatures are verified to match a KEY that has been distributed.  It does not verify that the jar files are built with a key trusted by the Grails project.
 
-Download the latest KEYS file and make sure it's imported into gpg:
-```bash
-    wget https://github.com/apache/grails-core/blob/7.0.x/KEYS
-    gpg --import KEYS
-```
+As part of uploading to repository.apache.org the signatures are verified to match a KEY that has been distributed, but RAO does not verify that the jar files are built with a key trusted by the Grails project.
+
+To ensure checksums match the server & signatures match, run the script `etc/bin/verify-jar-artifacts.sh` in the `grails-core` repository. This script will download the jar files from the staging repository, verify their signatures, and ensure they match the checksums provided in the source distribution.
 
-The jar files will need downloaded and verified they were signed by a valid Grails key.  Run the script (substitute the staging repo name):  
+Example: 
 ```bash
-    wget --recursive --no-parent --accept jar,asc https://repository.apache.org/content/repositories/orgapachegrails-1020/org/apache/grails
-    for jar_file in *.jar; do
-      asc_file="${jar_file}.asc"
-    
-      if [[ -f "$asc_file" ]]; then
-        echo "🔍 Verifying $jar_file..."
-    
-        gpg --verify "$asc_file" "$jar_file"
-        verify_status=$?
-    
-        if [ $verify_status -eq 0 ]; then
-          echo "✅ $jar_file is correctly signed."
-        else
-          echo "❌ $jar_file FAILED signature verification!"
-        fi
-    
-        echo ""
-      else
-        echo "⚠️ No .asc file found for $jar_file. Skipping."
-      fi
-    done
+    ./etc/bin/verify-jar-artifacts.sh orgapachegrails-1026 v7.0.0-M4 <grailsdownloadlocation>
 ```
 
 ### Reproducible Jar File
@@ -127,7 +110,7 @@ Bootstrap the source distribution so that it can be built:
     gradle wrapper
     ```
 
-Run the `verify-distribution.sh` shell script to compare the published jar files to a locally built version of them. For any differences, extract the jar files, use IntelliJ to compare each differing file. Assuming differences are ordering related, we can continue with the verification.
+Run the `verify-reproducible.sh` shell script to compare the published jar files to a locally built version of them. For any differences, extract the jar files, use IntelliJ to compare each differing file. Assuming differences are ordering related, we can continue with the verification.
 
 ### Binary Distribution Verification
 Download the binary distribution & expand it to test the various CLI's: `grailsw` (wrapper), `grails` (delegating), `grails-forge-cli`, and `grails-shell-cli`.  For each CLI, verify the published signature in the `PUBLISHED` file:
@@ -182,4 +165,26 @@ To remove a Nexus staging repo, run the workflow `Release - Drop Nexus Staging`
 
 ## Rollback Distribution
 
-To remove the staged distribution, use your SVN credentials to remove the version directory at [https://dist.apache.org/repos/dist/dev/grails](https://dist.apache.org/repos/dist/dev/grails)
\ No newline at end of file
+To remove the staged distribution, use your SVN credentials to remove the version directory at [https://dist.apache.org/repos/dist/dev/grails](https://dist.apache.org/repos/dist/dev/grails)
+
+## Appendix: GPG Configuration
+If you wish to verify any artifact manually, you must trust the key used to build Grails. To do so:
+
+Download the latest KEYS file and make sure it's imported into gpg:
+```bash
+    wget https://github.com/apache/grails-core/blob/7.0.x/KEYS
+    gpg --import KEYS
+```
+
+Setup the key for trust:
+```bash
+   gpg --edit-key <key id>
+   gpg> trust
+   gpg> 4
+   gpg> quit
+```
+
+Setup the key for validity:
+```bash
+   gpg --lsign-key 08E2CEC47E38FE415F080AB62ADECADC11775306
+```
\ No newline at end of file
diff --git a/etc/bin/verify-jar-artifacts.sh b/etc/bin/verify-jar-artifacts.sh
new file mode 100755
index 0000000000..0fe52d14f4
--- /dev/null
+++ b/etc/bin/verify-jar-artifacts.sh
@@ -0,0 +1,102 @@
+#!/usr/bin/env bash
+#
+#  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
+#
+#    https://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.
+#
+
+set -euo pipefail
+
+STAGING_REPO_ID=$1
+RELEASE_TAG=$2
+DOWNLOAD_LOCATION="${3:-downloads}"
+DOWNLOAD_LOCATION=$(realpath "${DOWNLOAD_LOCATION}")
+
+if [ -z "${STAGING_REPO_ID}" ] || [ -z "${RELEASE_TAG}" ]; then
+  echo "Usage: $0 [staging-repo-id] [release-tag] <optional download location>"
+  exit 1
+fi
+
+VERSION=${RELEASE_TAG#v}
+
+ARTIFACTS_FILE="${DOWNLOAD_LOCATION}/PUBLISHED_ARTIFACTS"
+CHECKSUMS_FILE="${DOWNLOAD_LOCATION}/CHECKSUMS"
+
+if [ ! -f "${ARTIFACTS_FILE}" ] || [ ! -f "${CHECKSUMS_FILE}" ]; then
+  echo "Required files ${ARTIFACTS_FILE} and/or ${CHECKSUMS_FILE} not found."
+  exit 1
+fi
+
+
+REPO_BASE_URL="https://repository.apache.org/content/repositories/${STAGING_REPO_ID}"
+
+# Create a temporary directory to work in
+WORK_DIR='build'
+mkdir -p $WORK_DIR
+echo "Using temp dir: $WORK_DIR"
+cd "$WORK_DIR"
+
+# Read each line from PUBLISHED_ARTIFACTS
+while IFS= read -r line; do
+  JAR_FILE=$(echo "${line}" | awk '{print $1}')
+  [[ "${JAR_FILE}" != *.jar ]] && continue
+  
+  COORDINATES=$(echo "${line}" | awk '{print $2}')
+
+  GROUP_ID=$(echo "${COORDINATES}" | cut -d: -f1 | tr '.' '/')
+  ARTIFACT_ID=$(echo "${COORDINATES}" | cut -d: -f2)
+  VERSION=$(echo "${COORDINATES}" | cut -d: -f3)
+  CLASSIFIER=$(echo "${COORDINATES}" | cut -d: -f4-)
+
+  if [[ -n "${CLASSIFIER}" ]]; then
+    FILE_NAME="${ARTIFACT_ID}-${VERSION}-${CLASSIFIER}.jar"
+  else
+    FILE_NAME="${ARTIFACT_ID}-${VERSION}.jar"
+  fi
+
+  JAR_URL="${REPO_BASE_URL}/${GROUP_ID}/${ARTIFACT_ID}/${VERSION}/${FILE_NAME}"
+  ASC_URL="${JAR_URL}.asc"
+
+  echo "🔎 Checking artifact: ${FILE_NAME}"
+  echo "... Downloading: ${JAR_URL}"
+  curl -sSfLO "${JAR_URL}"
+
+  echo "... Downloading signature: ${ASC_URL}"
+  curl -sSfLO "${ASC_URL}"
+
+  echo "... Verifying GPG signature..."
+  gpg --verify "${FILE_NAME}.asc" "${FILE_NAME}"
+
+  EXPECTED_CHECKSUM=$(grep "^${FILE_NAME} " "${CHECKSUMS_FILE}" | awk '{print $2}')
+  if [ -z "${EXPECTED_CHECKSUM}" ]; then
+    echo "❌ Checksum not found for ${FILE_NAME}"
+    exit 1
+  fi
+
+  echo "... Verifying checksum..."
+  ACTUAL_CHECKSUM=$(shasum -a 512 "${FILE_NAME}" | awk '{print $1}')
+
+  if [ "${ACTUAL_CHECKSUM}" != "${EXPECTED_CHECKSUM}" ]; then
+    echo "❌ Checksum mismatch for ${FILE_NAME}"
+    echo "Expected: ${EXPECTED_CHECKSUM}"
+    echo "Actual:   ${ACTUAL_CHECKSUM}"
+    exit 1
+  fi
+
+  echo "✅ Verified: ${FILE_NAME}"
+done < "${ARTIFACTS_FILE}"
+
+echo "✅✅✅ All artifacts verified successfully. ✅✅✅"
diff --git a/etc/bin/verify-distribution.sh b/etc/bin/verify-reproducible.sh
similarity index 100%
rename from etc/bin/verify-distribution.sh
rename to etc/bin/verify-reproducible.sh