92 lines
3.3 KiB
Bash
Executable file
92 lines
3.3 KiB
Bash
Executable file
#!/bin/bash
|
|
# Compare required external symbols of compiled Python extension modules between
|
|
# the PR build (pre-installed by Testing Farm) and the latest stable version
|
|
# available in the distribution repositories.
|
|
#
|
|
# The PR build is already installed before this test runs (via the Testing Farm
|
|
# artifact mechanism). We save its .so files, downgrade to the stable repo version,
|
|
# collect symbols from both, and compare.
|
|
#
|
|
# Output:
|
|
# + [module] symbol — PR build adds a new required symbol (potential issue possibly requiring update of Requires)
|
|
# - [module] symbol — PR build drops a previously required symbol (generally OK)
|
|
#
|
|
# Exit codes:
|
|
# 0 — no changes, or no stable version available to compare against (skipped)
|
|
# 1 — symbol differences detected between PR build and stable release
|
|
set -eo pipefail
|
|
|
|
PYVER=${VERSION}
|
|
SCRIPT_DIR="$(dirname "$(realpath "${BASH_SOURCE[0]}")")"
|
|
|
|
WORK_DIR=""
|
|
PKGS_MODIFIED=false
|
|
|
|
cleanup() {
|
|
if [[ "$PKGS_MODIFIED" == true ]]; then
|
|
echo ""
|
|
echo "=== Reverting package changes ==="
|
|
dnf history undo last -y 2>&1 || echo "WARNING: dnf history undo failed" >&2
|
|
fi
|
|
[[ -n "$WORK_DIR" ]] && rm -rf "$WORK_DIR"
|
|
}
|
|
trap cleanup EXIT
|
|
|
|
# Directories containing compiled extension modules
|
|
SCAN_DIRS=()
|
|
for d in "/usr/lib64/python${PYVER}" "/usr/lib64/python${PYVER}t"; do
|
|
[ -d "$d" ] && SCAN_DIRS+=("$d")
|
|
done
|
|
|
|
if [ ${#SCAN_DIRS[@]} -eq 0 ]; then
|
|
echo "ERROR: No Python extension directories found for python${PYVER}" >&2
|
|
exit 1
|
|
fi
|
|
|
|
SCAN_ARGS=("${SCAN_DIRS[@]}")
|
|
for f in /usr/lib64/libpython${PYVER}*.so.*; do
|
|
[[ -f "$f" && ! -L "$f" ]] && SCAN_ARGS+=("$f")
|
|
done
|
|
|
|
WORK_DIR=$(mktemp -d)
|
|
|
|
echo "=== Collecting PR build symbols ==="
|
|
python${PYVER} "$SCRIPT_DIR/collect_symbols.py" "${SCAN_ARGS[@]}" > "$WORK_DIR/new.json"
|
|
|
|
echo ""
|
|
echo "=== Available repos ==="
|
|
dnf repolist --all
|
|
|
|
# Discover packages dynamically from the installed source RPM so we don't need
|
|
# to hardcode subpackage names — works regardless of which subpackages were built.
|
|
readarray -t PKGS < <(
|
|
rpm -qa --qf '%{SOURCERPM} %{NAME}\n' |
|
|
awk -v src="python${PYVER}" '$1 ~ "^" src "-[0-9]" { print $2 }' |
|
|
sort -u
|
|
)
|
|
echo "Packages to install from stable repos: ${PKGS[*]}"
|
|
|
|
# Install the stable version from distribution repos, excluding the artifact repo
|
|
# that carries the PR build, so we always compare against what is publicly available.
|
|
#
|
|
# Strategy:
|
|
# 1. dnf reinstall — works when the PR did not bump NVR (same version in stable repos)
|
|
# 2. dnf distro-sync — fallback when the PR bumped NVR; installs the latest stable NVR
|
|
echo ""
|
|
echo "=== Installing stable version from repos ==="
|
|
if ! dnf reinstall -y --disablerepo=test-artifacts "${PKGS[@]}" 2>&1; then
|
|
echo "INFO: reinstall failed (NVR not in stable repos), falling back to distro-sync" >&2
|
|
if ! dnf distro-sync -y --disablerepo=test-artifacts "${PKGS[@]}" 2>&1; then
|
|
echo "INFO: distro-sync failed; no stable version available, skipping comparison." >&2
|
|
exit 0
|
|
fi
|
|
fi
|
|
PKGS_MODIFIED=true
|
|
|
|
echo ""
|
|
echo "=== Collecting stable version symbols ==="
|
|
python${PYVER} "$SCRIPT_DIR/collect_symbols.py" "${SCAN_ARGS[@]}" > "$WORK_DIR/old.json"
|
|
|
|
echo ""
|
|
echo "=== Comparing PR build against stable ==="
|
|
python${PYVER} "$SCRIPT_DIR/compare_symbols.py" "$WORK_DIR/old.json" "$WORK_DIR/new.json"
|