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 2917e16  Output count of total failures
2917e16 is described below

commit 2917e163b3475620da2e190de0de5b4c202bffc6
Author: Steve Lawrence <[email protected]>
AuthorDate: Mon Sep 8 07:42:04 2025 -0400

    Output count of total failures
    
    With the amount of lines output, it can be difficult to notice a small
    number of failures. This keeps a count of all failures and outputs the
    total at the end to make it more obvious if all tests passed or not.
    
    The main difficulty in keeping a count is that most of the checks are
    done in "find ... -exec", and the exec doesn't have a way to increment a
    bash variable since it occurs in a separate process space. To get around
    this, we add a new "test_files" function that accepts a list of files
    (retrieved using the same find command) and a string of commands to run
    on each file, using {} to reference each file similar to -exec. Checking
    the result of the command evaluation happens in the same process space,
    so we can check for failure and increment a variable. This new function
    also handles printing pass/fail results. The all means the new function
    is a bit more complex, but does make the actual tests more clear.
    
    This also changes the recursive diff to use the new test_files function,
    allowing us to compare files individually so we can list both matching
    and non-matching files. This makes it more clear exactly which files are
    checked for reproducibility. This also switches to using cmp since we no
    longer need the recursive capabilities that diff provides.
    
    Also add missing quotes in some places and rewrite RPM signature removal
    to avoid potential issues with spaces in files names.
    
    DAFFODIL-3039
---
 containers/check-release/Dockerfile           |   2 +-
 containers/check-release/src/check-release.sh | 211 +++++++++++++++++---------
 2 files changed, 137 insertions(+), 76 deletions(-)

diff --git a/containers/check-release/Dockerfile 
b/containers/check-release/Dockerfile
index ffe3a11..1a6e08f 100644
--- a/containers/check-release/Dockerfile
+++ b/containers/check-release/Dockerfile
@@ -17,7 +17,7 @@ FROM registry.fedoraproject.org/fedora:41
 
 RUN \
   dnf -y --quiet --repo=fedora install \
-    diff \
+    cmp \
     gpg \
     wget
 
diff --git a/containers/check-release/src/check-release.sh 
b/containers/check-release/src/check-release.sh
index fd67462..eb677e2 100755
--- a/containers/check-release/src/check-release.sh
+++ b/containers/check-release/src/check-release.sh
@@ -62,7 +62,7 @@ require_command() {
 }
 
 # error early if needed tools are missing
-require_command diff
+require_command cmp
 require_command gpg
 require_command md5sum
 require_command rpm
@@ -108,18 +108,72 @@ 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 
' {}'"
+FAILURE_COUNT=0
+
+# Read a list of newline separated paths from a file ($1) and commands from
+# stdin to evaluate for each line in the file. Each line in the file is
+# expected to be a path to a file, but it is not enforced. All {} strings in 
the
+# commands are replaced with the current line in the file prior to evaluation.
+# The commands are also evaluated in a new bash process, so they are free to
+# include commands like 'cd' or 'exit' without affecting the main script. Note
+# this means they cannot access variables or functions in the current process
+# scope. For each line, this outputs a pass/fail icon (based on the exit code
+# of the last command) followed by the line. A count of all failures is tallied
+# in the FAILURE_COUNT variable.
+#
+# Usage tips:
+#
+# It is recommended to wrap {} in apostrophes to avoid unexpected variable or
+# other expansions.
+#
+# Process substitution can be used for the file list to to avoid the need to
+# create actual files.
+#
+# Commands are read from stdin to support the recommended use of heredocs. In
+# general, tests should use <<-'CMD' commands CMD, especially if no variable
+# expansion or process substitution is wanted or needed. If that is needed,
+# tests should usually use <<-CMD commands CMD.
+#
+# Usage examples:
+#
+# test_files all_text_files.txt <<-'CMD'
+#     gpg --verify '{}.asc' '{}'
+# CMD
+#
+# test_files <(find dir/ -name '*.txt') <<-CMD
+#     cmp '{}' "$OTHER_DIR"/'{}'
+# CMD
+#
+test_files() {
+       FILE_LIST="$1"
+       CMDS=$(cat)
+       while IFS= read -r LINE
+       do
+               CMDS_TO_EVAL="${CMDS//\{\}/$LINE}"
+               bash -c "$CMDS_TO_EVAL" &> /dev/null
+               RC=$?
+               print_result $RC $LINE
+               [ $RC -eq 0 ] || FAILURE_COUNT=$((FAILURE_COUNT + 1))
+       done < "$FILE_LIST"
+}
+
+print_result() {
+       RC=$1
+       MESSAGE=$2
+       [ $RC -eq 0 ] && echo -ne "$PASS" || echo -ne "$FAIL"
+       echo " $MESSAGE"
+}
 
 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" \;
+test_files <(find "$DIST_DIR" -type f ! -name '*.sha512' ! -name '*.asc') 
<<-'CMD'
+       cd "$(dirname '{}')"
+       sha512sum --check "$(basename '{}').sha512"
+CMD
 
 printf "\n==== Dist GPG Signatures ====\n"
-find $DIST_DIR -type f ! -name '*.sha512' ! -name '*.asc' \
-       -exec bash -c "gpg --verify '{}.asc' '{}' $PRINT_FIND_RESULT" \;
+test_files <(find "$DIST_DIR" -type f ! -name '*.sha512' ! -name '*.asc') 
<<-'CMD'
+       gpg --verify '{}.asc' '{}'
+CMD
 
 printf "\n==== RPM Embedded Signatures ====\n"
 # The "rpm -K ..." command is used to verify that embedded digests and/or
@@ -133,85 +187,92 @@ printf "\n==== RPM Embedded Signatures ====\n"
 # signatures are valid, or "NOT OK" otherwise. We require that released RPMs
 # have both embedded signatures and digests and that they are all valid, so we
 # ensure the output of rpm -K contains the expect string that indicates this.
-find $DIST_DIR -type f -name '*.rpm' \
-       -exec bash -c "rpm -K '{}' | grep 'digests signatures OK' 
$PRINT_FIND_RESULT" \;
+test_files <(find "$DIST_DIR" -type f -name '*.rpm') <<-'CMD'
+       rpm -K '{}' | grep 'digests signatures OK'
+CMD
 
 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" \;
+       test_files <(find "$MAVEN_DIR" -type f ! -name '*.sha1' ! -name '*.md5' 
! -name '*.asc') <<-'CMD'
+               cmp <(sha1sum '{}' | cut -d' ' -f1 | tr -d '\n') '{}.sha1'
+       CMD
 
        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" \;
+       test_files <(find "$MAVEN_DIR" -type f ! -name '*.sha1' ! -name '*.md5' 
! -name '*.asc') <<-'CMD'
+               cmp <(md5sum '{}' | cut -d' ' -f1 | tr -d '\n' ) '{}.md5'
+       CMD
 
        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" \;
+       test_files <(find "$MAVEN_DIR" -type f ! -name '*.sha1' ! -name '*.md5' 
! -name '*.asc') <<-'CMD'
+               gpg --verify '{}.asc' '{}'
+       CMD
 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
-
-# RPM files have an embedded signature which makes reproducibility checking
-# difficult since locally built RPMs will not have the embedded signature. The
-# RPMs should be identical if we delete that signature, but unfortunately
-# rpmsign --delsign does not necessarily make RPMs byte for byte identical--
-# sometimes it rebuilds them in slightly different ways that are technically
-# the same but not identical. So we sort of delete the signature header
-# ourselves. This is done by calculating the size of the signature header in
-# the locally built RPM and copying those bytes into the dist RPM. As long as
-# the two signature headers are the same size (which they should always be),
-# this should work. Since we are changing the dist files, we create a backup of
-# them first, replace the signature header, run the diff command, then restore
-# the backups.
-#
-# All signature/checksum data is stored in a "signature header". This header
-# starts immediately after the 96-byte "lead". The header format is:
-#
-#  * magic number: 8 bytes
-#  * index_count: 4 bytes (uint32_t)
-#  * data_length: 4 bytes (uint32_t)
-#  * index: index_count * 16-byte entries
-#  * data: data_length bytes
-#
-# To find the total length of the signature header we read the index_count and
-# data_length fields at a known offset (skipping the lead and magic number),
-# then add together the length of 3 fixed length fields (16 bytes), the length
-# of the index (16 * index_count) and the length of the data (data_length).
-BACKUP_DIR=$(mktemp -d)
-find $DIST_DIR -name '*.rpm' -exec cp --parents {} $BACKUP_DIR \;
-for SRC_RPM in `find $LOCAL_RELEASE_DIR -name '*.rpm'`
-do
-       find $DIST_DIR -name "$(basename $SRC_RPM)" -exec bash -c '
+else
+       # RPM files have an embedded signature which makes reproducibility 
checking
+       # difficult since locally built RPMs will not have the embedded 
signature. The
+       # RPMs should be identical if we delete that signature, but 
unfortunately
+       # rpmsign --delsign does not necessarily make RPMs byte for byte 
identical--
+       # sometimes it rebuilds them in slightly different ways that are 
technically
+       # the same but not identical. So we sort of delete the signature header
+       # ourselves. This is done by calculating the size of the signature 
header in
+       # the locally built RPM and copying those bytes into the dist RPM. As 
long as
+       # the two signature headers are the same size (which they should always 
be),
+       # this should work. Since we are changing the dist files, we create a 
backup of
+       # them first, replace the signature header, run the diff command, then 
restore
+       # the backups.
+       #
+       # All signature/checksum data is stored in a "signature header". This 
header
+       # starts immediately after the 96-byte "lead". The header format is:
+       #
+       #  * magic number: 8 bytes
+       #  * index_count: 4 bytes (uint32_t)
+       #  * data_length: 4 bytes (uint32_t)
+       #  * index: index_count * 16-byte entries
+       #  * data: data_length bytes
+       #
+       # To find the total length of the signature header we read the 
index_count and
+       # data_length fields at a known offset (skipping the lead and magic 
number),
+       # then add together the length of 3 fixed length fields (16 bytes), the 
length
+       # of the index (16 * index_count) and the length of the data 
(data_length).
+       BACKUP_DIR="$(mktemp -d)"
+       find "$RELEASE_DIR" -name '*.rpm' -exec cp --parents '{}' "$BACKUP_DIR" 
\;
+       while IFS= read -r RPM_PATH
+       do
+               LOCAL_RPM="$LOCAL_RELEASE_DIR/$RPM_PATH"
+               RELEASE_RPM="$RELEASE_DIR/$RPM_PATH"
                LEAD_SIZE=96
-               read SIG_INDEX_COUNT SIG_DATA_LENGTH < <(od -An -t u4 -j 
$((LEAD_SIZE+8)) -N 8 --endian=big "$1")
+               read SIG_INDEX_COUNT SIG_DATA_LENGTH < <(od -An -t u4 -j 
$((LEAD_SIZE+8)) -N 8 --endian=big "$LOCAL_RPM")
                SIG_HEADER_LENGTH=$((16 + SIG_INDEX_COUNT*16 + SIG_DATA_LENGTH))
-               dd if="$1" of="$2" bs=1 skip=$LEAD_SIZE seek=$LEAD_SIZE 
count=$SIG_HEADER_LENGTH conv=notrunc
-       ' _ "$SRC_RPM" {} \; &> /dev/null
-done
-
-# 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 .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=*.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 {}")
-
-# restore and delete the backup directory
-cp -R $BACKUP_DIR/. .
-rm -rf $BACKUP_DIR
+               dd if="$LOCAL_RPM" of="$RELEASE_RPM" skip=$LEAD_SIZE 
seek=$LEAD_SIZE \
+                       bs=1 count=$SIG_HEADER_LENGTH conv=notrunc &> /dev/null
+       done < <(find "$LOCAL_RELEASE_DIR/" -name '*.rpm' -printf '%P\n')
+
+       # 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 .asc files can only be generated by the system with the secret 
key, the
+       #   locally built releases are not signed
+       test_files <(find "$RELEASE_DIR/" "$LOCAL_RELEASE_DIR/" \
+                       -type f \
+                       ! -name '*.rpm.sha512' \
+                       ! -name '*.asc' \
+                       ! -name '*.asc.md5' \
+                       ! -name '*.asc.sha1' \
+                       -printf '%P\n' | sort -u) <<-CMD
+               cmp "$RELEASE_DIR"/'{}' "$LOCAL_RELEASE_DIR"/'{}'
+       CMD
+
+       # restore and delete the backup directory
+       cp -R "$BACKUP_DIR/." .
+       rm -rf "$BACKUP_DIR"
+fi
+
+printf "\n==== Results ====\n"
+print_result $FAILURE_COUNT "Total Failed Checks: $FAILURE_COUNT"

Reply via email to