#!/usr/bin/env bash set -euox pipefail IMAGE="$1" VERSION="$2" ROOTFS="${GITHUB_WORKSPACE}/images/${IMAGE}/rootfs" CHANGELOG_DIR="changelogs/${IMAGE}" mkdir -p "${CHANGELOG_DIR}" PKG_CUR="${CHANGELOG_DIR}/packages-current.txt" PKG_PREV="${CHANGELOG_DIR}/packages-latest.txt" BUILD_ID="$(cat .buildid)" CHANGELOG_FILE="${CHANGELOG_DIR}/${VERSION}.${BUILD_ID}.json" # Ensure rpmdb exists if [[ ! -f "${ROOTFS}/usr/lib/sysimage/rpm/Packages" ]]; then echo "WARNING: rpmdb missing in rootfs (${ROOTFS})" echo "Skipping changelog generation." exit 0 fi # Extract package list rpm -qa --root "${ROOTFS}" --qf '%{NAME} %{EVR}\n' | sort > "${PKG_CUR}" # Prepare safe temp files CUR_NAMES_FILE="$(mktemp)" PREV_NAMES_FILE="$(mktemp)" cut -d' ' -f1 "${PKG_CUR}" | sort > "${CUR_NAMES_FILE}" if [[ -f "${PKG_PREV}" ]]; then cut -d' ' -f1 "${PKG_PREV}" | sort > "${PREV_NAMES_FILE}" else cp "${CUR_NAMES_FILE}" "${PREV_NAMES_FILE}" fi # Safe comm operations ADDED_NAMES="$(comm -13 "${PREV_NAMES_FILE}" "${CUR_NAMES_FILE}" || true)" REMOVED_NAMES="$(comm -23 "${PREV_NAMES_FILE}" "${CUR_NAMES_FILE}" || true)" COMMON_NAMES="$(comm -12 "${PREV_NAMES_FILE}" "${CUR_NAMES_FILE}" || true)" # Helper: get version from file using awk (exact match) get_ver() { local pkg="$1" local file="$2" awk -v p="$pkg" '$1 == p {print $2}' "$file" } # Build lists ADDED_LIST=() while read -r name; do [[ -z "$name" ]] && continue ver="$(get_ver "$name" "$PKG_CUR")" ADDED_LIST+=("${name} ${ver}") done <<< "${ADDED_NAMES}" REMOVED_LIST=() while read -r name; do [[ -z "$name" ]] && continue ver="$(get_ver "$name" "$PKG_PREV")" REMOVED_LIST+=("${name} ${ver}") done <<< "${REMOVED_NAMES}" UPDATED_LIST=() while read -r name; do [[ -z "$name" ]] && continue old_ver="$(get_ver "$name" "$PKG_PREV")" new_ver="$(get_ver "$name" "$PKG_CUR")" # Skip if either version is missing [[ -z "$old_ver" || -z "$new_ver" ]] && continue if [[ "$old_ver" != "$new_ver" ]]; then UPDATED_LIST+=("${name} ${old_ver} -> ${new_ver}") fi done <<< "${COMMON_NAMES}" ADDED_COUNT="${#ADDED_LIST[@]}" REMOVED_COUNT="${#REMOVED_LIST[@]}" UPDATED_COUNT="${#UPDATED_LIST[@]}" # Write JSON { echo "{" echo " \"image\": \"${IMAGE}\"," echo " \"version\": \"${VERSION}\"," echo " \"build_id\": \"${BUILD_ID}\"," echo " \"added_count\": ${ADDED_COUNT}," echo " \"removed_count\": ${REMOVED_COUNT}," echo " \"updated_count\": ${UPDATED_COUNT}," echo " \"added\": [" for i in "${!ADDED_LIST[@]}"; do sep=$([[ $i -lt $((ADDED_COUNT-1)) ]] && echo "," || echo "") printf ' "%s"%s\n' "${ADDED_LIST[$i]}" "${sep}" done echo " ]," echo " \"removed\": [" for i in "${!REMOVED_LIST[@]}"; do sep=$([[ $i -lt $((REMOVED_COUNT-1)) ]] && echo "," || echo "") printf ' "%s"%s\n' "${REMOVED_LIST[$i]}" "${sep}" done echo " ]," echo " \"updated\": [" for i in "${!UPDATED_LIST[@]}"; do sep=$([[ $i -lt $((UPDATED_COUNT-1)) ]] && echo "," || echo "") printf ' "%s"%s\n' "${UPDATED_LIST[$i]}" "${sep}" done echo " ]" echo "}" } > "${CHANGELOG_FILE}" mv "${PKG_CUR}" "${PKG_PREV}" echo "Changelog written to ${CHANGELOG_FILE}"