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

slawrence pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/daffodil-infrastructure.git


The following commit(s) were added to refs/heads/main by this push:
     new 7dba75b  Add script to check releases
7dba75b is described below

commit 7dba75bad7f72486e801f5a8409689dbb86febf3
Author: Steve Lawrence <[email protected]>
AuthorDate: Wed Feb 26 11:08:16 2025 -0500

    Add script to check releases
    
    This includes downloading release artifacts from ASF Dist and Maven
    staging repo, verifying all checksums and gpg signatures, and optionally
    comparing against a local build for reproducibility.
    
    DAFFODIL-2971
---
 scripts/check-release.sh | 141 +++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 141 insertions(+)

diff --git a/scripts/check-release.sh b/scripts/check-release.sh
new file mode 100755
index 0000000..f8aa93e
--- /dev/null
+++ b/scripts/check-release.sh
@@ -0,0 +1,141 @@
+#!/bin/bash
+
+if [[ "$#" -lt "2" || "$#" -gt 3 ]]
+then
+       echo "error: incorrect number of arguments" >&2
+       echo "Usage: $0 <DIST_URL> <MAVEN_URL> [LOCAL_RELEASE_DIR]" >&2
+       exit 1
+fi
+
+# URL of release candidate directory in dev/dist/, e.g. 
https://dist.apache.org/repos/dist/dev/daffodil/1.0.0-rc1
+DIST_URL=$1
+
+# URL of maven staging repository, e.g. 
https://repository.apache.org/content/repositories/orgapachedaffodil-1234
+MAVEN_URL=$2
+
+# optional path to release directory built by running the 
daffodil-build-release
+# container. If not provided, only signature/checksum checks are done
+LOCAL_RELEASE_DIR=$3
+
+require_command() {
+       command -v "$1" &> /dev/null || { echo "error: command $1 not found in 
PATH"; exit 1; }
+}
+
+# error early if needed tools are missing
+require_command diff
+require_command gpg
+require_command md5sum
+require_command rpm
+require_command sha1sum
+require_command sha512sum
+require_command wget
+if [ -n "$LOCAL_RELEASE_DIR" ]
+then
+       require_command msidiff
+       require_command rpmsign
+fi
+
+WGET="wget --no-verbose --force-progress --recursive --level=inf -e robots=off 
--no-parent --no-host-directories --reject=index.html,robots.txt"
+
+RELEASE_DIR=release-download
+DIST_DIR=$RELEASE_DIR/asf-dist
+MAVEN_DIR=$RELEASE_DIR/maven-local
+
+printf "\n==== Downloading Release Files ====\n"
+
+# download dist/dev/ files
+mkdir -p $DIST_DIR
+pushd $DIST_DIR &>/dev/null
+$WGET --cut-dirs=4 $DIST_URL/
+popd &>/dev/null
+
+# download maven repository, delete nexus generated files
+if [ -n "$MAVEN_URL" ]
+then
+       mkdir -p $MAVEN_DIR
+       pushd $MAVEN_DIR &>/dev/null
+       $WGET --cut-dirs=3 $MAVEN_URL/
+       find . -type f \( -name 'archetype-catalog.xml' -o -name 
'maven-metadata.xml*' \) -delete
+       popd &>/dev/null
+fi
+
+printf "\n==== Download Complete ====\n"
+
+RED="\x1b[31m"
+GREEN="\033[32m"
+YELLOW="\033[33m"
+RESET="\033[0m"
+PASS="$GREEN✔$RESET"
+FAIL="$RED✘$RESET"
+WARN="$YELLOW‼$RESET"
+
+# used in the string of a find -exec command. Outputs a string representing
+# pass/fail depending on how the previous command ran, followed by the filename
+# from the find command
+PRINT_FIND_RESULT="&> /dev/null && echo -ne '$PASS' || echo -ne '$FAIL'; echo 
' {}'"
+
+printf "\n==== Dist SHA512 Checksum ====\n"
+find $DIST_DIR -type f ! -name '*.sha512' ! -name '*.asc' \
+       -exec bash -c "cd \"\$(dirname '{}')\" && sha512sum --check \$(basename 
'{}').sha512 $PRINT_FIND_RESULT" \;
+
+printf "\n==== Dist GPG Signatures ====\n"
+find $DIST_DIR -type f ! -name '*.sha512' ! -name '*.asc' \
+       -exec bash -c "gpg --verify '{}.asc' '{}' $PRINT_FIND_RESULT" \;
+
+printf "\n==== RPM Signatures ====\n"
+find $DIST_DIR -type f -name '*.rpm' \
+       -exec bash -c "rpm -K '{}' $PRINT_FIND_RESULT" \;
+
+if [ -n "$MAVEN_URL" ]
+then
+       printf "\n==== Maven SHA1 Checksums ====\n"
+       find $MAVEN_DIR -type f ! -name '*.sha1' ! -name '*.md5' ! -name 
'*.asc' \
+               -exec bash -c "diff <(sha1sum '{}' | cut -d' ' -f1 | tr -d 
'\n') <(cat '{}'.sha1) $PRINT_FIND_RESULT" \;
+
+       printf "\n==== Maven MD5 Checksums ====\n"
+       find $MAVEN_DIR -type f ! -name '*.sha1' ! -name '*.md5' ! -name 
'*.asc' \
+               -exec bash -c "diff <(md5sum '{}' | cut -d' ' -f1 | tr -d '\n' 
) <(cat '{}'.md5) $PRINT_FIND_RESULT" \;
+
+       printf "\n==== Maven GPG Signatures ====\n"
+       find $MAVEN_DIR -type f ! -name '*.sha1' ! -name '*.md5' ! -name 
'*.asc' \
+               -exec bash -c "gpg --verify '{}.asc' '{}' $PRINT_FIND_RESULT" \;
+fi
+
+printf "\n==== Reproducible Builds ====\n"
+if [ -z "$LOCAL_RELEASE_DIR" ]
+then
+       echo -e "$WARN no local release directory provided, skipping 
reproducible build check"
+       exit 0
+fi
+
+printf "\n==== Calculating Differences ====\n"
+
+# The released rpm file has an embedded signature, deleting the signature
+# should cause the RPMs to be byte-for-byte the same
+find $DIST_DIR -name '*.rpm' -execdir rpmsign --delsign {} \; &>/dev/null
+
+# Reasons for excluding files from the diff check:
+# - The downloaded .rpm file has an embedded signature (which we removed),
+#   locally built RPM does not so checksums will be different. RPMs should be
+#   exactly the same with the signature removed though.
+# - The downloaded .msi file has an embedded UUID and timestamps that cannot be
+#   changed, so msi and its checksum will be different. We use msidiff later to
+#   verify differences are only where expected
+# - The .asc files can only be generated by the system with the secret key, the
+#   locally built releases are not signed
+DIFF=$(diff \
+       --recursive \
+       --brief \
+       --exclude=*.rpm.sha512 \
+       --exclude=*.msi \
+       --exclude=*.msi.sha512 \
+       --exclude=*.asc \
+       --exclude=*.asc.md5 \
+       --exclude=*.asc.sha1 \
+       $RELEASE_DIR/ $LOCAL_RELEASE_DIR/)
+[ $? -eq 0 ] && echo -e "$PASS no differences found" || (echo "$DIFF" | xargs 
-I {} echo -e "$FAIL {}")
+
+printf "\n==== MSI Differences ====\n"
+echo -e "$WARN manual verification needed, diff should include only one UUID 
and two timestamps"
+echo -e "$WARN ignore for VS Code Extension and SBT Plugin"
+find $DIST_DIR $LOCAL_RELEASE_DIR -name *.msi -exec msidiff {} \+

Reply via email to