#!/bin/bash # Simple script that takes a list of the modular packages in a group of repositories (like AppStream,CodeReady from RHEL 8) and # compares them with the modules in another distribution (Like AppStream,PowerTools from Rocky 8) # # It uses straight dnf calls for its data, and requires the repos to be defined in repos.d/. Also requires git # # All modules and version are iterated over and compared. # # Usage takes the pattern : ./module_compare_html.sh REPO_A,REPO_B,REPO_C REPO_X,REPO_Y,REPO_Z # # Example: ./modules_compare_html.sh RHEL8_AppStream,RHEL8_CodeReady Rocky8_AppStream,Rocky8_PowerTools # REPOS1=$1 REPOS2=$2 # Get a complete list of modules+versions we want to compare against (usually from RHEL 8) # This includes a list that consists of things like "perl:5.24 , perl:5.26 , python38:3.8" , etc. MODULE_LIST1=$(dnf --disablerepo '*' --enablerepo "${REPOS1}" module list | grep -v '^Name' | grep -v '(RPMs)' | grep -v 'Hint:' | grep -vi ' subscription ' | grep -vi ' metadata ' | grep -v '^$' | awk '{print $1":"$2}') IFS=' ' mkdir -p /tmp/module_compare rm -f /tmp/module_compare/* # HTML header: echo "

Module Artifact Comparison for: ${REPOS1} vs. ${REPOS2}

" echo '
' echo "

Generated by Rocky Module Compare Script at: $(date +'%Y-%m-%d %H:%M:%S')

" # Grab module info (artifacts, streams, versions) from all modules, in the source repo and target repo MODULE1=$(dnf --disablerepo '*' --enablerepo "${REPOS1}" module info "*" 2> /dev/null) MODULE2=$(dnf --disablerepo '*' --enablerepo "${REPOS2}" module info "*" 2> /dev/null) # Big loop where we go through every possible module/version combination: for module in ${MODULE_LIST1}; do # isolate what stream ("version") of the module we want mod_name=$(echo "${module}" | awk -F ':' '{print $1}') mod_stream=$(echo "${module}" | awk -F ':' '{print $2}') # Isolate the latest released version of each module, that's the only one we're intrested in (indicated by the "Version :" line in module info) # Strategy: # get the module name and 3 lines after, # from that ensure the module stream is the one we want, # from that isolate the "Version :" line, # then isolate the version number only, sort, and grab the newest latest_version1=$(echo "${MODULE1}" | grep -A3 ": ${mod_name}$" | grep -A2 ": ${mod_stream}" | grep "^Version" | awk '{print $3}' | sort -n | tail -1) latest_version2=$(echo "${MODULE2}" | grep -A3 ": ${mod_name}$" | grep -A2 ": ${mod_stream}" | grep "^Version" | awk '{print $3}' | sort -n | tail -1) # Isolate individual module artifacts and write them (sorted) to a text file # order of operations: # grep to find the module name, then grep to find the version, followed by 1000 lines of continued text # sed to get this single module:stream:version, ending at the blank line (blank line separates all versions) # awk to find "Requires :" line, # sed to remove "Artifacts", # awk to isolate module rpm artifact ($2), # sed to remove the distro tag after module (module+el8.4.0+xyz) # sed to remove the git hash after "module+" ONLY IF we have a minor patch release (ie. module ends in a ".1.x86_64" or a ".2.src" or something similar) # sed to remove everything after .module in the normal case (no minor patch release at the end) #everything after ".module" (which is unique per-distro), except for ending ".$arch" (src/noarch/x86_64/etc.) # remove any blank lines, # and finally sort and write to text file echo "${MODULE1}" | grep -A1000 ": ${mod_name}$" | grep -A1000 "${latest_version1}" | sed -n '0,/^$/p' | awk "/Requires / { show=1; next } show; /^$/ { show=0 }" | sed 's/Artifacts //' | awk '{print $2}' | sed 's/module+.*+/module+/g' | sed 's/module+.*\.\(.*\)\./module.\1./g' | sed 's/module+.*\./module./g' | grep -v '^$' | sort > "/tmp/module_compare/${module}_1" # Do the same isolation of module rpms for module 2 and write that to a text file echo "${MODULE2}" | grep -A1000 ": ${mod_name}$" | grep -A1000 "${latest_version2}" | sed -n '0,/^$/p' | awk "/Requires / { show=1; next } show; /^$/ { show=0 }" | sed 's/Artifacts //' | awk '{print $2}' | sed 's/module+.*+/module+/g' | sed 's/module+.*\.\(.*\)\./module.\1./g' | sed 's/module+.*\./module./g' | grep -v '^$' | sort > "/tmp/module_compare/${module}_2" # Get list of differences from source repo (the "-" in git diff) diff1=$(git --no-pager diff "/tmp/module_compare/${module}_1" "/tmp/module_compare/${module}_2" | grep -A1000 '@@' | grep '^\-' | sort) # and the "+" (repo2): diff2=$(git --no-pager diff "/tmp/module_compare/${module}_1" "/tmp/module_compare/${module}_2" | grep -A1000 '@@' | grep '^\+' | sort) # If module artifacts are completely identical, then we will say as much: if [[ -z "${diff1}" ]] && [[ -z "${diff2}" ]]; then diff1="Identical Packages" diff2="Identical Packages" fi # If module 2 is empty, then it doesn't exist: if [ -s "/tmp/module_compare/${module}_1" ] && [ ! -s "/tmp/module_compare/${module}_2" ]; then diff1="N/A" diff2="Module packages not found" fi # swap line endings for
to make html friendly looking: diff1=$(echo "${diff1}" | sed 's/$/
/') diff2=$(echo "${diff2}" | sed 's/$/
/') # Now, write the table row line: echo "" done echo "
Module Name:Version ${REPOS1} Pkg Diffs (-) ${REPOS2} Pkg Diffs (+)
${module} ${diff1} ${diff2}
"