From f05409e23a107eef3f21ac7f6da826c048341e7e Mon Sep 17 00:00:00 2001 From: Micah Abbott Date: Fri, 7 Aug 2026 13:37:53 -0400 Subject: [PATCH 1/4] test(fedora-iot-raw): scope greenboot download to Copr repo Listing greenboot/greenboot-default-health-checks by name after enabling the per-PR Copr repo isn't enough: dnf resolves the highest NEVRA across all enabled repos, and Copr snapshot builds conventionally use a Release starting at "0....", the same convention official pre-GA/ rebuilt packages use. Whenever Fedora ships a greenboot release that outranks the current Copr build, dnf silently downloads the stock package and the test exercises unpatched code -- the same class of bug eb7d75c fixed for the ostree/osbuild-composer flow, just unpropagated to this script's SSH-based dnf5 download. Assisted-by: OpenCode (Claude Sonnet 5) --- tests/greenboot-fedora-iot-raw.sh | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/tests/greenboot-fedora-iot-raw.sh b/tests/greenboot-fedora-iot-raw.sh index 7a48d036..7e3abcab 100755 --- a/tests/greenboot-fedora-iot-raw.sh +++ b/tests/greenboot-fedora-iot-raw.sh @@ -308,9 +308,21 @@ if [[ $copr_result != 0 ]]; then exit 1 fi +# Listing greenboot/greenboot-default-health-checks by name isn't enough to +# guarantee the Copr build gets picked: dnf always resolves to the highest +# NEVRA across all enabled repos, and Copr snapshot builds conventionally use +# a Release starting at "0....", the same convention official +# pre-GA/rebuilt packages use. Whenever BaseOS/AppStream/Fedora ships a +# greenboot release that outranks the current Copr build, an unscoped +# download would silently fetch the stock package instead. Restrict +# resolution to just the just-enabled Copr repo so there is only one +# candidate regardless of what other repos offer (see commit eb7d75c, which +# fixed the same class of bug for the ostree/osbuild-composer flow). +GREENBOOT_COPR_REPO_ID="copr:copr.fedorainfracloud.org:packit:fedora-iot-greenboot-rs-${PR_NUMBER}" + greenprint "📦 Downloading greenboot RPMs from Copr" ssh "${SSH_OPTIONS[@]}" -i "${SSH_KEY}" "${SSH_USER}@${GUEST_ADDRESS}" \ - "dnf download --destdir /tmp/greenboot-rpms greenboot greenboot-default-health-checks" + "dnf download --from-repo='${GREENBOOT_COPR_REPO_ID}' --destdir /tmp/greenboot-rpms greenboot greenboot-default-health-checks" greenprint "📦 Replacing greenboot packages with PR build" ssh "${SSH_OPTIONS[@]}" -i "${SSH_KEY}" "${SSH_USER}@${GUEST_ADDRESS}" \ From d281446209997ee0d4d61be3f50bce453b96828d Mon Sep 17 00:00:00 2001 From: Micah Abbott Date: Fri, 7 Aug 2026 13:37:59 -0400 Subject: [PATCH 2/4] test(bootc-anaconda-iso): scope greenboot install to Copr repo Same dnf NEVRA-precedence issue eb7d75c fixed for the ostree/osbuild- composer flow applies here: the generated Containerfile's dnf5 reinstall/ install calls resolve greenboot/greenboot-default-health-checks against every enabled repo, so a base-repo greenboot release that outranks the Copr snapshot's "0...." release silently wins and the test exercises unpatched code. Assisted-by: OpenCode (Claude Sonnet 5) --- tests/greenboot-bootc-anaconda-iso.sh | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/tests/greenboot-bootc-anaconda-iso.sh b/tests/greenboot-bootc-anaconda-iso.sh index 0c7e4a93..cbfa5c40 100755 --- a/tests/greenboot-bootc-anaconda-iso.sh +++ b/tests/greenboot-bootc-anaconda-iso.sh @@ -302,6 +302,18 @@ EOF ;; esac +# Listing greenboot/greenboot-default-health-checks by name isn't enough to +# guarantee the Copr build gets picked: dnf always resolves to the highest +# NEVRA across all enabled repos, and Copr snapshot builds conventionally use +# a Release starting at "0....", the same convention official +# pre-GA/rebuilt packages use. Whenever a base repo ships a greenboot release +# that outranks the current Copr build, an unscoped reinstall/install would +# silently fall back to the stock package instead. Restrict resolution to +# just the just-enabled Copr repo so there is only one candidate regardless +# of what other repos offer (see commit eb7d75c, which fixed the same class +# of bug for the ostree/osbuild-composer flow). +GREENBOOT_COPR_REPO_ID="copr:copr.fedorainfracloud.org:packit:fedora-iot-greenboot-rs-${PR_NUMBER}" + if [[ "${USE_COMPOSE_RPMS}" == true && -n "${GREENBOOT_PACKAGES_URL}" ]]; then tee -a Containerfile > /dev/null << EOF COPY greenboot-*.rpm /tmp/ @@ -314,7 +326,7 @@ else RUN (dnf install -y 'dnf5-command(copr)' || dnf install -y 'dnf-command(copr)') && \ dnf copr enable -y packit/fedora-iot-greenboot-rs-${PR_NUMBER} ${COPR_CHROOT} && \ dnf clean metadata && \ - (dnf reinstall -y greenboot greenboot-default-health-checks || dnf install -y greenboot greenboot-default-health-checks) && \ + (dnf reinstall -y --from-repo='${GREENBOOT_COPR_REPO_ID}' greenboot greenboot-default-health-checks || dnf install -y --from-repo='${GREENBOOT_COPR_REPO_ID}' greenboot greenboot-default-health-checks) && \ systemctl enable greenboot-healthcheck.service EOF fi From 49f8b3e3572fb2b3d0d29a60c0bdfcabf6cfd198 Mon Sep 17 00:00:00 2001 From: Micah Abbott Date: Fri, 7 Aug 2026 13:38:02 -0400 Subject: [PATCH 3/4] test(bootc-qcow2): scope greenboot install to Copr repo Identical fix to the anaconda-iso sibling script: the generated Containerfile's dnf5 reinstall/install calls need to be scoped to the just-enabled Copr repo so a competing base-repo greenboot release can't outrank the Copr snapshot build and silently install unpatched code. Assisted-by: OpenCode (Claude Sonnet 5) --- tests/greenboot-bootc-qcow2.sh | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/tests/greenboot-bootc-qcow2.sh b/tests/greenboot-bootc-qcow2.sh index 474a619c..c234eda3 100755 --- a/tests/greenboot-bootc-qcow2.sh +++ b/tests/greenboot-bootc-qcow2.sh @@ -302,6 +302,18 @@ EOF ;; esac +# Listing greenboot/greenboot-default-health-checks by name isn't enough to +# guarantee the Copr build gets picked: dnf always resolves to the highest +# NEVRA across all enabled repos, and Copr snapshot builds conventionally use +# a Release starting at "0....", the same convention official +# pre-GA/rebuilt packages use. Whenever a base repo ships a greenboot release +# that outranks the current Copr build, an unscoped reinstall/install would +# silently fall back to the stock package instead. Restrict resolution to +# just the just-enabled Copr repo so there is only one candidate regardless +# of what other repos offer (see commit eb7d75c, which fixed the same class +# of bug for the ostree/osbuild-composer flow). +GREENBOOT_COPR_REPO_ID="copr:copr.fedorainfracloud.org:packit:fedora-iot-greenboot-rs-${PR_NUMBER}" + if [[ "${USE_COMPOSE_RPMS}" == true && -n "${GREENBOOT_PACKAGES_URL}" ]]; then tee -a Containerfile > /dev/null << EOF COPY greenboot-*.rpm /tmp/ @@ -314,7 +326,7 @@ else RUN (dnf install -y 'dnf5-command(copr)' || dnf install -y 'dnf-command(copr)') && \ dnf copr enable -y packit/fedora-iot-greenboot-rs-${PR_NUMBER} ${COPR_CHROOT} && \ dnf clean metadata && \ - (dnf reinstall -y greenboot greenboot-default-health-checks || dnf install -y greenboot greenboot-default-health-checks) && \ + (dnf reinstall -y --from-repo='${GREENBOOT_COPR_REPO_ID}' greenboot greenboot-default-health-checks || dnf install -y --from-repo='${GREENBOOT_COPR_REPO_ID}' greenboot greenboot-default-health-checks) && \ systemctl enable greenboot-healthcheck.service EOF fi From e4d1d2eddbaca6c7d9f6e508d813dc59e13f85a8 Mon Sep 17 00:00:00 2001 From: Paul Whalen Date: Thu, 13 Aug 2026 09:33:42 -0400 Subject: [PATCH 4/4] test(bootc): use dnf download for Copr install to handle NEVR mismatch dnf reinstall --from-repo requires the exact same NEVR in the target repo, which fails when the base image ships a different Release than the Copr snapshot build. dnf install --from-repo won't replace an already-installed package. Switch to dnf download + local install, matching the ostree and compose-RPM patterns. Assisted-by: Claude (Anthropic) Signed-off-by: Paul Whalen --- tests/greenboot-bootc-anaconda-iso.sh | 4 +++- tests/greenboot-bootc-qcow2.sh | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/tests/greenboot-bootc-anaconda-iso.sh b/tests/greenboot-bootc-anaconda-iso.sh index cbfa5c40..887defe4 100755 --- a/tests/greenboot-bootc-anaconda-iso.sh +++ b/tests/greenboot-bootc-anaconda-iso.sh @@ -326,7 +326,9 @@ else RUN (dnf install -y 'dnf5-command(copr)' || dnf install -y 'dnf-command(copr)') && \ dnf copr enable -y packit/fedora-iot-greenboot-rs-${PR_NUMBER} ${COPR_CHROOT} && \ dnf clean metadata && \ - (dnf reinstall -y --from-repo='${GREENBOOT_COPR_REPO_ID}' greenboot greenboot-default-health-checks || dnf install -y --from-repo='${GREENBOOT_COPR_REPO_ID}' greenboot greenboot-default-health-checks) && \ + dnf download --from-repo='${GREENBOOT_COPR_REPO_ID}' --destdir /tmp/copr-rpms greenboot greenboot-default-health-checks && \ + dnf install -y /tmp/copr-rpms/*.rpm && \ + rm -rf /tmp/copr-rpms && \ systemctl enable greenboot-healthcheck.service EOF fi diff --git a/tests/greenboot-bootc-qcow2.sh b/tests/greenboot-bootc-qcow2.sh index c234eda3..fe558a61 100755 --- a/tests/greenboot-bootc-qcow2.sh +++ b/tests/greenboot-bootc-qcow2.sh @@ -326,7 +326,9 @@ else RUN (dnf install -y 'dnf5-command(copr)' || dnf install -y 'dnf-command(copr)') && \ dnf copr enable -y packit/fedora-iot-greenboot-rs-${PR_NUMBER} ${COPR_CHROOT} && \ dnf clean metadata && \ - (dnf reinstall -y --from-repo='${GREENBOOT_COPR_REPO_ID}' greenboot greenboot-default-health-checks || dnf install -y --from-repo='${GREENBOOT_COPR_REPO_ID}' greenboot greenboot-default-health-checks) && \ + dnf download --from-repo='${GREENBOOT_COPR_REPO_ID}' --destdir /tmp/copr-rpms greenboot greenboot-default-health-checks && \ + dnf install -y /tmp/copr-rpms/*.rpm && \ + rm -rf /tmp/copr-rpms && \ systemctl enable greenboot-healthcheck.service EOF fi