From a1b5f23490025f9f37ba24b33dce2e31d98503ab Mon Sep 17 00:00:00 2001 From: Paul Whalen Date: Thu, 16 Jul 2026 12:53:20 -0400 Subject: [PATCH 01/14] ci: allow PR checkout in make-rpm job for pull_request_target actions/checkout@v7 refuses to check out PR code from a pull_request_target workflow by default. This is safe because the check-pull-request job already gates on write/admin permission. Assisted-by: Claude Opus 4.6 Signed-off-by: Paul Whalen --- .github/workflows/comment-ci.yaml | 1 + .github/workflows/greenboot-ci.yaml | 1 + 2 files changed, 2 insertions(+) diff --git a/.github/workflows/comment-ci.yaml b/.github/workflows/comment-ci.yaml index e55d498..bf0b8ea 100644 --- a/.github/workflows/comment-ci.yaml +++ b/.github/workflows/comment-ci.yaml @@ -52,6 +52,7 @@ jobs: uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: ref: ${{ needs.check-pull-request.outputs.sha }} + allow-unsafe-pr-checkout: true - name: Build RPMs run: | diff --git a/.github/workflows/greenboot-ci.yaml b/.github/workflows/greenboot-ci.yaml index bfd2a4b..f73b130 100644 --- a/.github/workflows/greenboot-ci.yaml +++ b/.github/workflows/greenboot-ci.yaml @@ -52,6 +52,7 @@ jobs: uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: ref: ${{ needs.check-pull-request.outputs.sha }} + allow-unsafe-pr-checkout: true - name: Build RPMs run: | From c6c5996b07505049dc1b2b8d64e0850f3e82718f Mon Sep 17 00:00:00 2001 From: Paul Whalen Date: Thu, 16 Jul 2026 12:55:44 -0400 Subject: [PATCH 02/14] fix: use dnf5 copr plugin on Fedora 44+ Fedora 44 ships dnf5 where 'dnf-command(copr)' installs the dnf4 plugin but 'dnf copr' invokes dnf5. Try dnf5-command(copr) first, falling back to dnf-command(copr) for CentOS/RHEL. Assisted-by: Claude Opus 4.6 Signed-off-by: Paul Whalen --- tests/greenboot-bootc-anaconda-iso.sh | 2 +- tests/greenboot-bootc-qcow2.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/greenboot-bootc-anaconda-iso.sh b/tests/greenboot-bootc-anaconda-iso.sh index 6d80d63..732230a 100755 --- a/tests/greenboot-bootc-anaconda-iso.sh +++ b/tests/greenboot-bootc-anaconda-iso.sh @@ -193,7 +193,7 @@ podman login quay.io -u ${QUAY_USERNAME} -p ${QUAY_PASSWORD} podman login registry.stage.redhat.io -u ${STAGE_REDHAT_IO_USERNAME} -p ${STAGE_REDHAT_IO_TOKEN} tee Containerfile > /dev/null << EOF FROM ${BASE_IMAGE_URL} -RUN dnf install -y 'dnf-command(copr)' && \ +RUN (dnf install -y 'dnf5-command(copr)' || dnf install -y 'dnf-command(copr)') && \ dnf copr enable -y packit/fedora-iot-greenboot-rs-${PR_NUMBER} && \ dnf install -y greenboot greenboot-default-health-checks && \ systemctl enable greenboot-healthcheck.service diff --git a/tests/greenboot-bootc-qcow2.sh b/tests/greenboot-bootc-qcow2.sh index 23130d8..fc1e04e 100755 --- a/tests/greenboot-bootc-qcow2.sh +++ b/tests/greenboot-bootc-qcow2.sh @@ -193,7 +193,7 @@ podman login quay.io -u ${QUAY_USERNAME} -p ${QUAY_PASSWORD} podman login registry.stage.redhat.io -u ${STAGE_REDHAT_IO_USERNAME} -p ${STAGE_REDHAT_IO_TOKEN} tee Containerfile > /dev/null << EOF FROM ${BASE_IMAGE_URL} -RUN dnf install -y 'dnf-command(copr)' && \ +RUN (dnf install -y 'dnf5-command(copr)' || dnf install -y 'dnf-command(copr)') && \ dnf copr enable -y packit/fedora-iot-greenboot-rs-${PR_NUMBER} && \ dnf install -y greenboot greenboot-default-health-checks && \ systemctl enable greenboot-healthcheck.service From 5aee9a5717e306c1161d5570e19e1518f426203d Mon Sep 17 00:00:00 2001 From: Paul Whalen Date: Thu, 16 Jul 2026 13:12:24 -0400 Subject: [PATCH 03/14] fix: move Copr source add after osbuild-composer.socket start composer-cli requires osbuild-composer.socket to be running. The Copr source block was placed before the socket start, causing the retry loop to fail for 15+ minutes waiting on a socket that hadn't been started yet. Assisted-by: Claude Opus 4.6 Signed-off-by: Paul Whalen --- tests/greenboot-ostree.sh | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/tests/greenboot-ostree.sh b/tests/greenboot-ostree.sh index 537a78e..fbab8a0 100755 --- a/tests/greenboot-ostree.sh +++ b/tests/greenboot-ostree.sh @@ -109,6 +109,22 @@ case "${ID}-${VERSION_ID}" in exit 1;; esac +# Check ostree_key permissions +KEY_PERMISSION_PRE=$(stat -L -c "%a %G %U" key/ostree_key | grep -oP '\d+' | head -n 1) +echo -e "${KEY_PERMISSION_PRE}" +if [[ "${KEY_PERMISSION_PRE}" != "600" ]]; then + greenprint "๐Ÿ’ก File permissions too open...Changing to 600" + chmod 600 ./key/ostree_key +fi + +# Start httpd server as prod ostree repo +greenprint "Start httpd service" +sudo systemctl enable --now httpd.service + +# Start osbuild-composer.socket +greenprint "Start osbuild-composer.socket" +sudo systemctl enable --now osbuild-composer.socket + # Add Copr repo as osbuild-composer source for greenboot PR builds greenprint "Adding Copr source for greenboot PR #${PR_NUMBER}" sudo tee /tmp/greenboot-copr.toml > /dev/null << EOF @@ -134,22 +150,6 @@ if [ "$copr_added" = false ]; then exit 1 fi -# Check ostree_key permissions -KEY_PERMISSION_PRE=$(stat -L -c "%a %G %U" key/ostree_key | grep -oP '\d+' | head -n 1) -echo -e "${KEY_PERMISSION_PRE}" -if [[ "${KEY_PERMISSION_PRE}" != "600" ]]; then - greenprint "๐Ÿ’ก File permissions too open...Changing to 600" - chmod 600 ./key/ostree_key -fi - -# Start httpd server as prod ostree repo -greenprint "Start httpd service" -sudo systemctl enable --now httpd.service - -# Start osbuild-composer.socket -greenprint "Start osbuild-composer.socket" -sudo systemctl enable --now osbuild-composer.socket - # Start firewalld greenprint "Start firewalld" sudo systemctl enable --now firewalld From 501bda750349e536670fd6418c644ffb411cf57a Mon Sep 17 00:00:00 2001 From: Paul Whalen Date: Thu, 16 Jul 2026 14:42:46 -0400 Subject: [PATCH 04/14] fix: remove stale local packages repo from osbuild-composer configs The packages source at http://192.168.100.1/packages/ was used by the old make-rpm flow to serve locally-built RPMs. Now that greenboot packages come from Copr, this repo is never populated, causing blueprints depsolve to fail on ostree CI runs. Assisted-by: Claude Opus 4.6 Signed-off-by: Paul Whalen --- tests/files/centos-stream-9.json | 6 +----- tests/files/rhel-9-8-0.json | 4 ---- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/tests/files/centos-stream-9.json b/tests/files/centos-stream-9.json index 9800f32..9b0d9d2 100644 --- a/tests/files/centos-stream-9.json +++ b/tests/files/centos-stream-9.json @@ -31,10 +31,6 @@ "baseurl": "https://composes.stream.centos.org/production/latest-CentOS-Stream/compose/RT/x86_64/os/", "gpgkey": "-----BEGIN PGP PUBLIC KEY BLOCK-----\nVersion: GnuPG v2.0.22 (GNU/Linux)\n\nmQINBFzMWxkBEADHrskpBgN9OphmhRkc7P/YrsAGSvvl7kfu+e9KAaU6f5MeAVyn\nrIoM43syyGkgFyWgjZM8/rur7EMPY2yt+2q/1ZfLVCRn9856JqTIq0XRpDUe4nKQ\n8BlA7wDVZoSDxUZkSuTIyExbDf0cpw89Tcf62Mxmi8jh74vRlPy1PgjWL5494b3X\n5fxDidH4bqPZyxTBqPrUFuo+EfUVEqiGF94Ppq6ZUvrBGOVo1V1+Ifm9CGEK597c\naevcGc1RFlgxIgN84UpuDjPR9/zSndwJ7XsXYvZ6HXcKGagRKsfYDWGPkA5cOL/e\nf+yObOnC43yPUvpggQ4KaNJ6+SMTZOKikM8yciyBwLqwrjo8FlJgkv8Vfag/2UR7\nJINbyqHHoLUhQ2m6HXSwK4YjtwidF9EUkaBZWrrskYR3IRZLXlWqeOi/+ezYOW0m\nvufrkcvsh+TKlVVnuwmEPjJ8mwUSpsLdfPJo1DHsd8FS03SCKPaXFdD7ePfEjiYk\nnHpQaKE01aWVSLUiygn7F7rYemGqV9Vt7tBw5pz0vqSC72a5E3zFzIIuHx6aANry\nGat3aqU3qtBXOrA/dPkX9cWE+UR5wo/A2UdKJZLlGhM2WRJ3ltmGT48V9CeS6N9Y\nm4CKdzvg7EWjlTlFrd/8WJ2KoqOE9leDPeXRPncubJfJ6LLIHyG09h9kKQARAQAB\ntDpDZW50T1MgKENlbnRPUyBPZmZpY2lhbCBTaWduaW5nIEtleSkgPHNlY3VyaXR5\nQGNlbnRvcy5vcmc+iQI3BBMBAgAhBQJczFsZAhsDBgsJCAcDAgYVCAIJCgsDFgIB\nAh4BAheAAAoJEAW1VbOEg8ZdjOsP/2ygSxH9jqffOU9SKyJDlraL2gIutqZ3B8pl\nGy/Qnb9QD1EJVb4ZxOEhcY2W9VJfIpnf3yBuAto7zvKe/G1nxH4Bt6WTJQCkUjcs\nN3qPWsx1VslsAEz7bXGiHym6Ay4xF28bQ9XYIokIQXd0T2rD3/lNGxNtORZ2bKjD\nvOzYzvh2idUIY1DgGWJ11gtHFIA9CvHcW+SMPEhkcKZJAO51ayFBqTSSpiorVwTq\na0cB+cgmCQOI4/MY+kIvzoexfG7xhkUqe0wxmph9RQQxlTbNQDCdaxSgwbF2T+gw\nbyaDvkS4xtR6Soj7BKjKAmcnf5fn4C5Or0KLUqMzBtDMbfQQihn62iZJN6ZZ/4dg\nq4HTqyVpyuzMXsFpJ9L/FqH2DJ4exGGpBv00ba/Zauy7GsqOc5PnNBsYaHCply0X\n407DRx51t9YwYI/ttValuehq9+gRJpOTTKp6AjZn/a5Yt3h6jDgpNfM/EyLFIY9z\nV6CXqQQ/8JRvaik/JsGCf+eeLZOw4koIjZGEAg04iuyNTjhx0e/QHEVcYAqNLhXG\nrCTTbCn3NSUO9qxEXC+K/1m1kaXoCGA0UWlVGZ1JSifbbMx0yxq/brpEZPUYm+32\no8XfbocBWljFUJ+6aljTvZ3LQLKTSPW7TFO+GXycAOmCGhlXh2tlc6iTc41PACqy\nyy+mHmSv\n=kkH7\n-----END PGP PUBLIC KEY BLOCK-----\n", "check_gpg": true - }, - { - "name": "packages", - "baseurl": "http://192.168.100.1/packages/" } ] -} \ No newline at end of file +} diff --git a/tests/files/rhel-9-8-0.json b/tests/files/rhel-9-8-0.json index 7acb0f5..f5072e7 100644 --- a/tests/files/rhel-9-8-0.json +++ b/tests/files/rhel-9-8-0.json @@ -26,10 +26,6 @@ "name": "rt", "baseurl": "http://REPLACE_ME_HERE/rhel-9/nightly/RHEL-9/latest-RHEL-9.8.0/compose/RT/x86_64/os/", "gpgkey": "-----BEGIN PGP PUBLIC KEY BLOCK-----\n\nmQINBErgSTsBEACh2A4b0O9t+vzC9VrVtL1AKvUWi9OPCjkvR7Xd8DtJxeeMZ5eF\n0HtzIG58qDRybwUe89FZprB1ffuUKzdE+HcL3FbNWSSOXVjZIersdXyH3NvnLLLF\n0DNRB2ix3bXG9Rh/RXpFsNxDp2CEMdUvbYCzE79K1EnUTVh1L0Of023FtPSZXX0c\nu7Pb5DI5lX5YeoXO6RoodrIGYJsVBQWnrWw4xNTconUfNPk0EGZtEnzvH2zyPoJh\nXGF+Ncu9XwbalnYde10OCvSWAZ5zTCpoLMTvQjWpbCdWXJzCm6G+/hx9upke546H\n5IjtYm4dTIVTnc3wvDiODgBKRzOl9rEOCIgOuGtDxRxcQkjrC+xvg5Vkqn7vBUyW\n9pHedOU+PoF3DGOM+dqv+eNKBvh9YF9ugFAQBkcG7viZgvGEMGGUpzNgN7XnS1gj\n/DPo9mZESOYnKceve2tIC87p2hqjrxOHuI7fkZYeNIcAoa83rBltFXaBDYhWAKS1\nPcXS1/7JzP0ky7d0L6Xbu/If5kqWQpKwUInXtySRkuraVfuK3Bpa+X1XecWi24JY\nHVtlNX025xx1ewVzGNCTlWn1skQN2OOoQTV4C8/qFpTW6DTWYurd4+fE0OJFJZQF\nbuhfXYwmRlVOgN5i77NTIJZJQfYFj38c/Iv5vZBPokO6mffrOTv3MHWVgQARAQAB\ntDNSZWQgSGF0LCBJbmMuIChyZWxlYXNlIGtleSAyKSA8c2VjdXJpdHlAcmVkaGF0\nLmNvbT6JAjYEEwECACAFAkrgSTsCGwMGCwkIBwMCBBUCCAMEFgIDAQIeAQIXgAAK\nCRAZni+R/UMdUWzpD/9s5SFR/ZF3yjY5VLUFLMXIKUztNN3oc45fyLdTI3+UClKC\n2tEruzYjqNHhqAEXa2sN1fMrsuKec61Ll2NfvJjkLKDvgVIh7kM7aslNYVOP6BTf\nC/JJ7/ufz3UZmyViH/WDl+AYdgk3JqCIO5w5ryrC9IyBzYv2m0HqYbWfphY3uHw5\nun3ndLJcu8+BGP5F+ONQEGl+DRH58Il9Jp3HwbRa7dvkPgEhfFR+1hI+Btta2C7E\n0/2NKzCxZw7Lx3PBRcU92YKyaEihfy/aQKZCAuyfKiMvsmzs+4poIX7I9NQCJpyE\nIGfINoZ7VxqHwRn/d5mw2MZTJjbzSf+Um9YJyA0iEEyD6qjriWQRbuxpQXmlAJbh\n8okZ4gbVFv1F8MzK+4R8VvWJ0XxgtikSo72fHjwha7MAjqFnOq6eo6fEC/75g3NL\nGht5VdpGuHk0vbdENHMC8wS99e5qXGNDued3hlTavDMlEAHl34q2H9nakTGRF5Ki\nJUfNh3DVRGhg8cMIti21njiRh7gyFI2OccATY7bBSr79JhuNwelHuxLrCFpY7V25\nOFktl15jZJaMxuQBqYdBgSay2G0U6D1+7VsWufpzd/Abx1/c3oi9ZaJvW22kAggq\ndzdA27UUYjWvx42w9menJwh/0jeQcTecIUd0d0rFcw/c1pvgMMl/Q73yzKgKYw==\n=zbHE\n-----END PGP PUBLIC KEY BLOCK-----\n-----BEGIN PGP PUBLIC KEY BLOCK-----\n\nmQINBFsy23UBEACUKSphFEIEvNpy68VeW4Dt6qv+mU6am9a2AAl10JANLj1oqWX+\noYk3en1S6cVe2qehSL5DGVa3HMUZkP3dtbD4SgzXzxPodebPcr4+0QNWigkUisri\nXGL5SCEcOP30zDhZvg+4mpO2jMi7Kc1DLPzBBkgppcX91wa0L1pQzBcvYMPyV/Dh\nKbQHR75WdkP6OA2JXdfC94nxYq+2e0iPqC1hCP3Elh+YnSkOkrawDPmoB1g4+ft/\nxsiVGVy/W0ekXmgvYEHt6si6Y8NwXgnTMqxeSXQ9YUgVIbTpsxHQKGy76T5lMlWX\n4LCOmEVomBJg1SqF6yi9Vu8TeNThaDqT4/DddYInd0OO69s0kGIXalVgGYiW2HOD\nx2q5R1VGCoJxXomz+EbOXY+HpKPOHAjU0DB9MxbU3S248LQ69nIB5uxysy0PSco1\nsdZ8sxRNQ9Dw6on0Nowx5m6Thefzs5iK3dnPGBqHTT43DHbnWc2scjQFG+eZhe98\nEll/kb6vpBoY4bG9/wCG9qu7jj9Z+BceCNKeHllbezVLCU/Hswivr7h2dnaEFvPD\nO4GqiWiwOF06XaBMVgxA8p2HRw0KtXqOpZk+o+sUvdPjsBw42BB96A1yFX4jgFNA\nPyZYnEUdP6OOv9HSjnl7k/iEkvHq/jGYMMojixlvXpGXhnt5jNyc4GSUJQARAQAB\ntDNSZWQgSGF0LCBJbmMuIChhdXhpbGlhcnkga2V5KSA8c2VjdXJpdHlAcmVkaGF0\nLmNvbT6JAjkEEwECACMFAlsy23UCGwMHCwkIBwMCAQYVCAIJCgsEFgIDAQIeAQIX\ngAAKCRD3b2bD1AgnknqOD/9fB2ASuG2aJIiap4kK58R+RmOVM4qgclAnaG57+vjI\nnKvyfV3NH/keplGNRxwqHekfPCqvkpABwhdGEXIE8ILqnPewIMr6PZNZWNJynZ9i\neSMzVuCG7jDoGyQ5/6B0f6xeBtTeBDiRl7+Alehet1twuGL1BJUYG0QuLgcEzkaE\n/gkuumeVcazLzz7L12D22nMk66GxmgXfqS5zcbqOAuZwaA6VgSEgFdV2X2JU79zS\nBQJXv7NKc+nDXFG7M7EHjY3Rma3HXkDbkT8bzh9tJV7Z7TlpT829pStWQyoxKCVq\nsEX8WsSapTKA3P9YkYCwLShgZu4HKRFvHMaIasSIZWzLu+RZH/4yyHOhj0QB7XMY\neHQ6fGSbtJ+K6SrpHOOsKQNAJ0hVbSrnA1cr5+2SDfel1RfYt0W9FA6DoH/S5gAR\ndzT1u44QVwwp3U+eFpHphFy//uzxNMtCjjdkpzhYYhOCLNkDrlRPb+bcoL/6ePSr\n016PA7eEnuC305YU1Ml2WcCn7wQV8x90o33klJmEkWtXh3X39vYtI4nCPIvZn1eP\nVy+F+wWt4vN2b8oOdlzc2paOembbCo2B+Wapv5Y9peBvlbsDSgqtJABfK8KQq/jK\nYl3h5elIa1I3uNfczeHOnf1enLOUOlq630yeM/yHizz99G1g+z/guMh5+x/OHraW\niA==\n=+Gxh\n-----END PGP PUBLIC KEY BLOCK-----" - }, - { - "name": "packages", - "baseurl": "http://192.168.100.1/packages/" } ] } From 6951a2163c045bcbb5b9de99db480d21ebe76a0b Mon Sep 17 00:00:00 2001 From: Paul Whalen Date: Thu, 16 Jul 2026 14:58:11 -0400 Subject: [PATCH 05/14] fix: specify Copr chroot for CentOS/RHEL bootc builds On CentOS Stream 10, dnf copr defaults to epel-10-x86_64 which does not exist in the Copr project. Similarly RHEL maps to non-existent chroots. Explicitly pass the correct centos-stream chroot name for CentOS and RHEL builds. Initialize COPR_CHROOT to empty for Fedora where auto-detection works. Assisted-by: Claude Opus 4.6 Signed-off-by: Paul Whalen --- tests/greenboot-bootc-anaconda-iso.sh | 6 +++++- tests/greenboot-bootc-qcow2.sh | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/tests/greenboot-bootc-anaconda-iso.sh b/tests/greenboot-bootc-anaconda-iso.sh index 732230a..e9d12cb 100755 --- a/tests/greenboot-bootc-anaconda-iso.sh +++ b/tests/greenboot-bootc-anaconda-iso.sh @@ -34,6 +34,7 @@ EDGE_USER=core EDGE_USER_PASSWORD=foobar CONSOLE_LOG=/tmp/vm-console.log +COPR_CHROOT="" case "${ID}-${VERSION_ID}" in "fedora-43") OS_VARIANT="fedora-unknown" @@ -58,12 +59,14 @@ case "${ID}-${VERSION_ID}" in BASE_IMAGE_URL="quay.io/centos-bootc/centos-bootc:stream10" BIB_URL="quay.io/centos-bootc/bootc-image-builder:latest" BOOT_ARGS="uefi,firmware.feature0.name=secure-boot,firmware.feature0.enabled=no" + COPR_CHROOT="centos-stream-10-${ARCH}" ;; "rhel-9.8") OS_VARIANT="rhel9-unknown" BASE_IMAGE_URL="registry.stage.redhat.io/rhel9/rhel-bootc:9.8" BIB_URL="registry.stage.redhat.io/rhel9/bootc-image-builder:9.8" BOOT_ARGS="uefi" + COPR_CHROOT="centos-stream-9-${ARCH}" sed -i "s/REPLACE_ME_HERE/${DOWNLOAD_NODE}/g" files/rhel-9-8.repo ;; "rhel-10.2") @@ -71,6 +74,7 @@ case "${ID}-${VERSION_ID}" in BASE_IMAGE_URL="registry.stage.redhat.io/rhel10/rhel-bootc:10.2" BIB_URL="registry.stage.redhat.io/rhel10/bootc-image-builder:10.2" BOOT_ARGS="uefi" + COPR_CHROOT="centos-stream-10-${ARCH}" sed -i "s/REPLACE_ME_HERE/${DOWNLOAD_NODE}/g" files/rhel-10-2.repo ;; *) @@ -194,7 +198,7 @@ podman login registry.stage.redhat.io -u ${STAGE_REDHAT_IO_USERNAME} -p ${STAGE_ tee Containerfile > /dev/null << EOF FROM ${BASE_IMAGE_URL} RUN (dnf install -y 'dnf5-command(copr)' || dnf install -y 'dnf-command(copr)') && \ - dnf copr enable -y packit/fedora-iot-greenboot-rs-${PR_NUMBER} && \ + dnf copr enable -y packit/fedora-iot-greenboot-rs-${PR_NUMBER} ${COPR_CHROOT} && \ dnf install -y greenboot greenboot-default-health-checks && \ systemctl enable greenboot-healthcheck.service RUN sed -i "s/GREENBOOT_MAX_BOOT_ATTEMPTS=3/GREENBOOT_MAX_BOOT_ATTEMPTS=5/g" /etc/greenboot/greenboot.conf diff --git a/tests/greenboot-bootc-qcow2.sh b/tests/greenboot-bootc-qcow2.sh index fc1e04e..ca9d356 100755 --- a/tests/greenboot-bootc-qcow2.sh +++ b/tests/greenboot-bootc-qcow2.sh @@ -34,6 +34,7 @@ EDGE_USER=core EDGE_USER_PASSWORD=foobar CONSOLE_LOG=/tmp/vm-console.log +COPR_CHROOT="" case "${ID}-${VERSION_ID}" in "fedora-43") OS_VARIANT="fedora-unknown" @@ -58,12 +59,14 @@ case "${ID}-${VERSION_ID}" in BASE_IMAGE_URL="quay.io/centos-bootc/centos-bootc:stream10" BIB_URL="quay.io/centos-bootc/bootc-image-builder:latest" BOOT_ARGS="uefi,firmware.feature0.name=secure-boot,firmware.feature0.enabled=no" + COPR_CHROOT="centos-stream-10-${ARCH}" ;; "rhel-9.8") OS_VARIANT="rhel9-unknown" BASE_IMAGE_URL="registry.stage.redhat.io/rhel9/rhel-bootc:9.8" BIB_URL="registry.stage.redhat.io/rhel9/bootc-image-builder:9.8" BOOT_ARGS="uefi" + COPR_CHROOT="centos-stream-9-${ARCH}" sed -i "s/REPLACE_ME_HERE/${DOWNLOAD_NODE}/g" files/rhel-9-8.repo ;; "rhel-10.2") @@ -71,6 +74,7 @@ case "${ID}-${VERSION_ID}" in BASE_IMAGE_URL="registry.stage.redhat.io/rhel10/rhel-bootc:10.2" BIB_URL="registry.stage.redhat.io/rhel10/bootc-image-builder:10.2" BOOT_ARGS="uefi" + COPR_CHROOT="centos-stream-10-${ARCH}" sed -i "s/REPLACE_ME_HERE/${DOWNLOAD_NODE}/g" files/rhel-10-2.repo ;; *) @@ -194,7 +198,7 @@ podman login registry.stage.redhat.io -u ${STAGE_REDHAT_IO_USERNAME} -p ${STAGE_ tee Containerfile > /dev/null << EOF FROM ${BASE_IMAGE_URL} RUN (dnf install -y 'dnf5-command(copr)' || dnf install -y 'dnf-command(copr)') && \ - dnf copr enable -y packit/fedora-iot-greenboot-rs-${PR_NUMBER} && \ + dnf copr enable -y packit/fedora-iot-greenboot-rs-${PR_NUMBER} ${COPR_CHROOT} && \ dnf install -y greenboot greenboot-default-health-checks && \ systemctl enable greenboot-healthcheck.service RUN sed -i "s/GREENBOOT_MAX_BOOT_ATTEMPTS=3/GREENBOOT_MAX_BOOT_ATTEMPTS=5/g" /etc/greenboot/greenboot.conf From 9971e27157b6a3f75e27f9c43fb7f65267f9c258 Mon Sep 17 00:00:00 2001 From: Paul Whalen Date: Fri, 17 Jul 2026 14:24:04 -0400 Subject: [PATCH 06/14] tests(anaconda-iso): replace mkksiso with BIB custom kickstart MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove the mkksiso post-processing step and use BIB's customizations.installer.kickstart to control the anaconda installation directly. This simplifies the test by eliminating the ISO rewrite step and its lorax dependency. Custom kickstart provides: - text --non-interactive for unattended install - zerombr, clearpart, autopart for disk initialization - network for DHCP configuration - bootloader --append for serial console on installed system - poweroff for clean shutdown (compatible with --wait=-1) The Users module is disabled since user creation is handled in the Containerfile โ€” BIB does not support customizations.user alongside customizations.installer.kickstart, and anaconda cannot set passwords on the ostreecontainer filesystem. Assisted-by: Claude Opus 4.6 Signed-off-by: Paul Whalen --- tests/greenboot-bootc-anaconda-iso.sh | 63 ++++++++------------------- 1 file changed, 19 insertions(+), 44 deletions(-) diff --git a/tests/greenboot-bootc-anaconda-iso.sh b/tests/greenboot-bootc-anaconda-iso.sh index e9d12cb..f7da8ce 100755 --- a/tests/greenboot-bootc-anaconda-iso.sh +++ b/tests/greenboot-bootc-anaconda-iso.sh @@ -216,6 +216,13 @@ COPY failing_script.sh /etc/greenboot/red.d COPY passing_binary /etc/greenboot/check/required.d/ COPY failing_binary /etc/greenboot/check/wanted.d/ + +RUN useradd -m -G wheel ${EDGE_USER} && echo '${EDGE_USER}:${EDGE_USER_PASSWORD}' | chpasswd +RUN mkdir -p /home/${EDGE_USER}/.ssh && \ + echo '${SSH_KEY_PUB}' > /home/${EDGE_USER}/.ssh/authorized_keys && \ + chmod 700 /home/${EDGE_USER}/.ssh && \ + chmod 600 /home/${EDGE_USER}/.ssh/authorized_keys && \ + chown -R ${EDGE_USER}:${EDGE_USER} /home/${EDGE_USER}/.ssh EOF if [[ "${ID}-${VERSION_ID}" == "rhel-9.8" ]]; then @@ -257,18 +264,16 @@ podman push quay.io/${QUAY_USERNAME}/greenboot-bootc:${TEST_UUID} greenprint "Using BIB to convert container to anaconda iso" tee config.json > /dev/null << EOF { - "blueprint": { - "customizations": { - "user": [ - { - "name": "${EDGE_USER}", - "password": "${EDGE_USER_PASSWORD}", - "key": "${SSH_KEY_PUB}", - "groups": [ - "wheel" - ] - } - ] + "customizations": { + "installer": { + "kickstart": { + "contents": "text --non-interactive\nzerombr\nclearpart --all --initlabel --disklabel=gpt\nautopart --nohome --type=plain --fstype=xfs\nnetwork --bootproto=dhcp --device=link --activate --onboot=on\nbootloader --append=\"console=ttyS0,115200\"\npoweroff\n" + }, + "modules": { + "disable": [ + "org.fedoraproject.Anaconda.Modules.Users" + ] + } } } } @@ -290,38 +295,8 @@ podman run \ --use-librepo=true \ quay.io/${QUAY_USERNAME}/greenboot-bootc:${TEST_UUID} -########################################################### -## -## Generate kickstart file and mkksiso -## -########################################################### -ISOMOUNT=$(mktemp -d) -greenprint "Mounting install.iso -> $ISOMOUNT" -sudo mount -v -o ro "output/bootiso/install.iso" "$ISOMOUNT" -NEW_KS_FILE="${TEMPDIR}/bib.ks" -greenprint "Default osbuild-base.ks" -cat "${ISOMOUNT}/osbuild-base.ks" -greenprint "Default osbuild.ks" -cat "${ISOMOUNT}/osbuild.ks" - -greenprint "Preparing modified kickstart file" -cat > "$NEW_KS_FILE" << EOFKS -text -$(cat "${ISOMOUNT}/osbuild-base.ks") -$(cat "${ISOMOUNT}/osbuild.ks") -EOFKS -sed -i '/%include/d' "$NEW_KS_FILE" - -greenprint "Writing new ISO" -sudo mkksiso -c "console=ttyS0,115200" --ks "$NEW_KS_FILE" "output/bootiso/install.iso" "/var/lib/libvirt/images/install.iso" - -greenprint "==== NEW KICKSTART FILE ====" -cat "$NEW_KS_FILE" -greenprint "============================" - -greenprint "Clean up ISO building environment" -sudo umount -v "$ISOMOUNT" -rm -rf "$ISOMOUNT" +greenprint "Copying BIB ISO to libvirt images" +sudo cp output/bootiso/install.iso /var/lib/libvirt/images/install.iso ########################################################### ## From 0b607cd54a8e7003cf1c6b3d133049939fc3474d Mon Sep 17 00:00:00 2001 From: Paul Whalen Date: Fri, 17 Jul 2026 14:38:07 -0400 Subject: [PATCH 07/14] ci: increase Testing Farm timeout for slow jobs Bump centos-9-ostree, rhel-9.8-ostree, and rhel-10.2-bootc from 90 to 120 minutes. These jobs consistently hit the 90-minute limit due to osbuild-composer compose times and nested VM installs. Assisted-by: Claude Opus 4.6 Signed-off-by: Paul Whalen --- .github/workflows/greenboot-ci.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/greenboot-ci.yaml b/.github/workflows/greenboot-ci.yaml index f73b130..f4ff86c 100644 --- a/.github/workflows/greenboot-ci.yaml +++ b/.github/workflows/greenboot-ci.yaml @@ -155,7 +155,7 @@ jobs: tmt_context: "arch=x86_64;distro=cs-9" tmt_plan_regex: ostree variables: "ARCH=x86_64;PR_NUMBER=${{ needs.check-pull-request.outputs.pr_number }}" - timeout: 90 + timeout: 120 secrets: "QUAY_USERNAME=${{ secrets.QUAY_USERNAME }};QUAY_PASSWORD=${{ secrets.QUAY_PASSWORD }};STAGE_REDHAT_IO_USERNAME=${{ secrets.STAGE_REDHAT_IO_USERNAME }};STAGE_REDHAT_IO_TOKEN=${{ secrets.STAGE_REDHAT_IO_TOKEN }};DOWNLOAD_NODE=${{ secrets.DOWNLOAD_NODE }}" rhel-9-8-ostree: @@ -179,7 +179,7 @@ jobs: tmt_context: "arch=x86_64;distro=rhel-9-8" tmt_plan_regex: ostree variables: "ARCH=x86_64;PR_NUMBER=${{ needs.check-pull-request.outputs.pr_number }}" - timeout: 90 + timeout: 120 secrets: "QUAY_USERNAME=${{ secrets.QUAY_USERNAME }};QUAY_PASSWORD=${{ secrets.QUAY_PASSWORD }};STAGE_REDHAT_IO_USERNAME=${{ secrets.STAGE_REDHAT_IO_USERNAME }};STAGE_REDHAT_IO_TOKEN=${{ secrets.STAGE_REDHAT_IO_TOKEN }};DOWNLOAD_NODE=${{ secrets.DOWNLOAD_NODE }}" rhel-10-2-bootc: @@ -203,5 +203,5 @@ jobs: tmt_context: "arch=x86_64;distro=rhel-10-2" tmt_plan_regex: bootc variables: "ARCH=x86_64;PR_NUMBER=${{ needs.check-pull-request.outputs.pr_number }}" - timeout: 90 + timeout: 120 secrets: "QUAY_USERNAME=${{ secrets.QUAY_USERNAME }};QUAY_PASSWORD=${{ secrets.QUAY_PASSWORD }};STAGE_REDHAT_IO_USERNAME=${{ secrets.STAGE_REDHAT_IO_USERNAME }};STAGE_REDHAT_IO_TOKEN=${{ secrets.STAGE_REDHAT_IO_TOKEN }};DOWNLOAD_NODE=${{ secrets.DOWNLOAD_NODE }}" From 2ad1567e87118da1ed0cea1ea403d10fe4425f4f Mon Sep 17 00:00:00 2001 From: Paul Whalen Date: Fri, 17 Jul 2026 15:30:39 -0400 Subject: [PATCH 08/14] tests(bootc): use fedora-iot base image for Fedora bootc tests Switch BASE_IMAGE_URL from quay.io/fedora/fedora-bootc to quay.io/fedora/fedora-iot for Fedora 44, and rawhide in both qcow2 and anaconda-iso test scripts. Assisted-by: Claude Opus 4.6 Signed-off-by: Paul Whalen --- tests/greenboot-bootc-anaconda-iso.sh | 10 ++-------- tests/greenboot-bootc-qcow2.sh | 10 ++-------- 2 files changed, 4 insertions(+), 16 deletions(-) diff --git a/tests/greenboot-bootc-anaconda-iso.sh b/tests/greenboot-bootc-anaconda-iso.sh index f7da8ce..e516d98 100755 --- a/tests/greenboot-bootc-anaconda-iso.sh +++ b/tests/greenboot-bootc-anaconda-iso.sh @@ -36,21 +36,15 @@ CONSOLE_LOG=/tmp/vm-console.log COPR_CHROOT="" case "${ID}-${VERSION_ID}" in - "fedora-43") - OS_VARIANT="fedora-unknown" - BASE_IMAGE_URL="quay.io/fedora/fedora-bootc:43" - BIB_URL="quay.io/centos-bootc/bootc-image-builder:latest" - BOOT_ARGS="uefi" - ;; "fedora-44") OS_VARIANT="fedora-unknown" - BASE_IMAGE_URL="quay.io/fedora/fedora-bootc:44" + BASE_IMAGE_URL="quay.io/fedora/fedora-iot:44" BIB_URL="quay.io/centos-bootc/bootc-image-builder:latest" BOOT_ARGS="uefi" ;; "fedora-45") OS_VARIANT="fedora-rawhide" - BASE_IMAGE_URL="quay.io/fedora/fedora-bootc:rawhide" + BASE_IMAGE_URL="quay.io/fedora/fedora-iot:rawhide" BIB_URL="quay.io/centos-bootc/bootc-image-builder:latest" BOOT_ARGS="uefi" ;; diff --git a/tests/greenboot-bootc-qcow2.sh b/tests/greenboot-bootc-qcow2.sh index ca9d356..e013c9f 100755 --- a/tests/greenboot-bootc-qcow2.sh +++ b/tests/greenboot-bootc-qcow2.sh @@ -36,21 +36,15 @@ CONSOLE_LOG=/tmp/vm-console.log COPR_CHROOT="" case "${ID}-${VERSION_ID}" in - "fedora-43") - OS_VARIANT="fedora-unknown" - BASE_IMAGE_URL="quay.io/fedora/fedora-bootc:43" - BIB_URL="quay.io/centos-bootc/bootc-image-builder:latest" - BOOT_ARGS="uefi" - ;; "fedora-44") OS_VARIANT="fedora-unknown" - BASE_IMAGE_URL="quay.io/fedora/fedora-bootc:44" + BASE_IMAGE_URL="quay.io/fedora/fedora-iot:44" BIB_URL="quay.io/centos-bootc/bootc-image-builder:latest" BOOT_ARGS="uefi" ;; "fedora-45") OS_VARIANT="fedora-rawhide" - BASE_IMAGE_URL="quay.io/fedora/fedora-bootc:rawhide" + BASE_IMAGE_URL="quay.io/fedora/fedora-iot:rawhide" BIB_URL="quay.io/centos-bootc/bootc-image-builder:latest" BOOT_ARGS="uefi" ;; From 800b5aedbc37941b00e1adc249ca59d3efb15d93 Mon Sep 17 00:00:00 2001 From: Paul Whalen Date: Sun, 19 Jul 2026 12:25:25 -0400 Subject: [PATCH 09/14] tests(anaconda-iso): use --location for direct kernel boot Switch virt-install from --cdrom to --location with explicit kernel/initrd paths to enable direct kernel boot and serial console output during anaconda installation. Extract the ISO label dynamically with blkid for inst.stage2 and inst.ks arguments. This fixes the issue where --cdrom boot through the ISO GRUB gave no serial console visibility and anaconda silently failed to install in CI environments. Assisted-by: Claude Opus 4.6 " Signed-off-by: Paul Whalen --- tests/greenboot-bootc-anaconda-iso.sh | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tests/greenboot-bootc-anaconda-iso.sh b/tests/greenboot-bootc-anaconda-iso.sh index e516d98..0d2a2ae 100755 --- a/tests/greenboot-bootc-anaconda-iso.sh +++ b/tests/greenboot-bootc-anaconda-iso.sh @@ -302,6 +302,9 @@ greenprint "๐Ÿ’พ Create vm qcow2 files for ISO installation" LIBVIRT_IMAGE_PATH_UEFI=/var/lib/libvirt/images/${TEST_UUID}-disk.qcow2 sudo qemu-img create -f qcow2 "/var/lib/libvirt/images/${TEST_UUID}-disk.qcow2" 10G sudo restorecon -Rv /var/lib/libvirt/images/ +ISO_LABEL=$(blkid -o value -s LABEL /var/lib/libvirt/images/install.iso) +[[ -n "$ISO_LABEL" ]] || { greenprint "โŒ ISO label is empty"; exit 1; } +greenprint "ISO label: ${ISO_LABEL}" sudo virt-install --name="${TEST_UUID}-uefi"\ --disk path="${LIBVIRT_IMAGE_PATH_UEFI}",format=qcow2 \ --ram 3072 \ @@ -309,7 +312,8 @@ sudo virt-install --name="${TEST_UUID}-uefi"\ --network network=integration,mac=34:49:22:B0:83:30 \ --os-type linux \ --os-variant ${OS_VARIANT} \ - --cdrom "/var/lib/libvirt/images/install.iso" \ + --location "/var/lib/libvirt/images/install.iso",kernel=images/pxeboot/vmlinuz,initrd=images/pxeboot/initrd.img \ + --extra-args "console=ttyS0,115200 inst.stage2=hd:LABEL=${ISO_LABEL} inst.ks=hd:LABEL=${ISO_LABEL}:/osbuild.ks" \ --boot ${BOOT_ARGS} \ --graphics none \ --serial file,path=${CONSOLE_LOG} \ From b3561ddddf0266a6c249b484362272235580ead5 Mon Sep 17 00:00:00 2001 From: Paul Whalen Date: Mon, 20 Jul 2026 09:05:59 -0400 Subject: [PATCH 10/14] fix(tests): copy RHEL repo file before dnf install in Containerfile MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The RHEL repo COPY was appended after the main Containerfile heredoc, placing it as the last instruction โ€” after the RUN dnf install that needs it. The RHEL base image has no enabled repos without this file, so dnf fails immediately on rhel-10.2 and rhel-9.8 bootc jobs. Split the Containerfile construction so the repo file COPY comes between FROM and the first RUN, ensuring repos are available when dnf runs. Assisted-by: Claude Opus 4.6 " Signed-off-by: Paul Whalen --- tests/greenboot-bootc-anaconda-iso.sh | 27 +++++++++++++++------------ tests/greenboot-bootc-qcow2.sh | 27 +++++++++++++++------------ 2 files changed, 30 insertions(+), 24 deletions(-) diff --git a/tests/greenboot-bootc-anaconda-iso.sh b/tests/greenboot-bootc-anaconda-iso.sh index 0d2a2ae..58b02a3 100755 --- a/tests/greenboot-bootc-anaconda-iso.sh +++ b/tests/greenboot-bootc-anaconda-iso.sh @@ -191,6 +191,21 @@ podman login quay.io -u ${QUAY_USERNAME} -p ${QUAY_PASSWORD} podman login registry.stage.redhat.io -u ${STAGE_REDHAT_IO_USERNAME} -p ${STAGE_REDHAT_IO_TOKEN} tee Containerfile > /dev/null << EOF FROM ${BASE_IMAGE_URL} +EOF + +if [[ "${ID}-${VERSION_ID}" == "rhel-9.8" ]]; then + tee -a Containerfile >> /dev/null << EOF +COPY files/rhel-9-8.repo /etc/yum.repos.d/rhel-9-8.repo +EOF +fi + +if [[ "${ID}-${VERSION_ID}" == "rhel-10.2" ]]; then + tee -a Containerfile >> /dev/null << EOF +COPY files/rhel-10-2.repo /etc/yum.repos.d/rhel-10-2.repo +EOF +fi + +tee -a Containerfile >> /dev/null << EOF 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 install -y greenboot greenboot-default-health-checks && \ @@ -219,18 +234,6 @@ RUN mkdir -p /home/${EDGE_USER}/.ssh && \ chown -R ${EDGE_USER}:${EDGE_USER} /home/${EDGE_USER}/.ssh EOF -if [[ "${ID}-${VERSION_ID}" == "rhel-9.8" ]]; then - tee -a Containerfile >> /dev/null << EOF -COPY files/rhel-9-8.repo /etc/yum.repos.d/rhel-9-8.repo -EOF -fi - -if [[ "${ID}-${VERSION_ID}" == "rhel-10.2" ]]; then - tee -a Containerfile >> /dev/null << EOF -COPY files/rhel-10-2.repo /etc/yum.repos.d/rhel-10-2.repo -EOF -fi - greenprint "Building container (retrying until Copr build is available)" build_success=false for attempt in $(seq 1 10); do diff --git a/tests/greenboot-bootc-qcow2.sh b/tests/greenboot-bootc-qcow2.sh index e013c9f..d3b3ba1 100755 --- a/tests/greenboot-bootc-qcow2.sh +++ b/tests/greenboot-bootc-qcow2.sh @@ -191,6 +191,21 @@ podman login quay.io -u ${QUAY_USERNAME} -p ${QUAY_PASSWORD} podman login registry.stage.redhat.io -u ${STAGE_REDHAT_IO_USERNAME} -p ${STAGE_REDHAT_IO_TOKEN} tee Containerfile > /dev/null << EOF FROM ${BASE_IMAGE_URL} +EOF + +if [[ "${ID}-${VERSION_ID}" == "rhel-9.8" ]]; then + tee -a Containerfile >> /dev/null << EOF +COPY files/rhel-9-8.repo /etc/yum.repos.d/rhel-9-8.repo +EOF +fi + +if [[ "${ID}-${VERSION_ID}" == "rhel-10.2" ]]; then + tee -a Containerfile >> /dev/null << EOF +COPY files/rhel-10-2.repo /etc/yum.repos.d/rhel-10-2.repo +EOF +fi + +tee -a Containerfile >> /dev/null << EOF 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 install -y greenboot greenboot-default-health-checks && \ @@ -212,18 +227,6 @@ COPY passing_binary /etc/greenboot/check/required.d/ COPY failing_binary /etc/greenboot/check/wanted.d/ EOF -if [[ "${ID}-${VERSION_ID}" == "rhel-9.8" ]]; then - tee -a Containerfile >> /dev/null << EOF -COPY files/rhel-9-8.repo /etc/yum.repos.d/rhel-9-8.repo -EOF -fi - -if [[ "${ID}-${VERSION_ID}" == "rhel-10.2" ]]; then - tee -a Containerfile >> /dev/null << EOF -COPY files/rhel-10-2.repo /etc/yum.repos.d/rhel-10-2.repo -EOF -fi - greenprint "Building container (retrying until Copr build is available)" build_success=false for attempt in $(seq 1 10); do From 149aa107e85a4046ded4f3b5fe6b2c84753173fb Mon Sep 17 00:00:00 2001 From: Paul Whalen Date: Mon, 20 Jul 2026 12:18:10 -0400 Subject: [PATCH 11/14] fix(tests): wait for firewalld D-Bus readiness before libvirt setup Since firewalld 2.4.1 removed Type=dbus from its systemd unit, the service reports active before its D-Bus interface is registered. Poll firewall-cmd --state to ensure firewalld is ready before virsh net-start sets zone='trusted' on the integration bridge. See: https://github.com/virt-s1/rhel-edge/commit/3858a65125984d87ac952c6fef7de579b9753d0a Assisted-by: Claude Opus 4.6 Signed-off-by: Paul Whalen --- tests/greenboot-bootc-anaconda-iso.sh | 17 +++++++++++++++++ tests/greenboot-bootc-qcow2.sh | 17 +++++++++++++++++ tests/greenboot-ostree.sh | 17 +++++++++++++++++ 3 files changed, 51 insertions(+) diff --git a/tests/greenboot-bootc-anaconda-iso.sh b/tests/greenboot-bootc-anaconda-iso.sh index 58b02a3..68ca43a 100755 --- a/tests/greenboot-bootc-anaconda-iso.sh +++ b/tests/greenboot-bootc-anaconda-iso.sh @@ -114,6 +114,23 @@ ansible-galaxy collection install community.general greenprint "Start firewalld" sudo systemctl enable --now firewalld +greenprint "Waiting for firewalld D-Bus interface to be ready" +fw_timeout=30 +fw_elapsed=0 +until sudo firewall-cmd --state >/dev/null 2>&1; do + sleep 1 + fw_elapsed=$((fw_elapsed + 1)) + if ! systemctl is-active --quiet firewalld; then + echo "firewalld systemd unit is not active" >&2 + sudo systemctl status firewalld --no-pager >&2 || true + exit 1 + fi + if [[ ${fw_elapsed} -ge ${fw_timeout} ]]; then + echo "firewalld did not become ready after ${fw_timeout} seconds" >&2 + exit 1 + fi +done + # Check ostree_key permissions KEY_PERMISSION_PRE=$(stat -L -c "%a %G %U" key/ostree_key | grep -oP '\d+' | head -n 1) echo -e "${KEY_PERMISSION_PRE}" diff --git a/tests/greenboot-bootc-qcow2.sh b/tests/greenboot-bootc-qcow2.sh index d3b3ba1..3875a82 100755 --- a/tests/greenboot-bootc-qcow2.sh +++ b/tests/greenboot-bootc-qcow2.sh @@ -114,6 +114,23 @@ ansible-galaxy collection install community.general greenprint "Start firewalld" sudo systemctl enable --now firewalld +greenprint "Waiting for firewalld D-Bus interface to be ready" +fw_timeout=30 +fw_elapsed=0 +until sudo firewall-cmd --state >/dev/null 2>&1; do + sleep 1 + fw_elapsed=$((fw_elapsed + 1)) + if ! systemctl is-active --quiet firewalld; then + echo "firewalld systemd unit is not active" >&2 + sudo systemctl status firewalld --no-pager >&2 || true + exit 1 + fi + if [[ ${fw_elapsed} -ge ${fw_timeout} ]]; then + echo "firewalld did not become ready after ${fw_timeout} seconds" >&2 + exit 1 + fi +done + # Check ostree_key permissions KEY_PERMISSION_PRE=$(stat -L -c "%a %G %U" key/ostree_key | grep -oP '\d+' | head -n 1) echo -e "${KEY_PERMISSION_PRE}" diff --git a/tests/greenboot-ostree.sh b/tests/greenboot-ostree.sh index fbab8a0..7d0e3e5 100755 --- a/tests/greenboot-ostree.sh +++ b/tests/greenboot-ostree.sh @@ -154,6 +154,23 @@ fi greenprint "Start firewalld" sudo systemctl enable --now firewalld +greenprint "Waiting for firewalld D-Bus interface to be ready" +fw_timeout=30 +fw_elapsed=0 +until sudo firewall-cmd --state >/dev/null 2>&1; do + sleep 1 + fw_elapsed=$((fw_elapsed + 1)) + if ! systemctl is-active --quiet firewalld; then + echo "firewalld systemd unit is not active" >&2 + sudo systemctl status firewalld --no-pager >&2 || true + exit 1 + fi + if [[ ${fw_elapsed} -ge ${fw_timeout} ]]; then + echo "firewalld did not become ready after ${fw_timeout} seconds" >&2 + exit 1 + fi +done + # Start libvirtd and test it. greenprint "๐Ÿš€ Starting libvirt daemon" sudo systemctl start libvirtd From a4ebdca1284ce758ed3e7d8612272235acc2ee36 Mon Sep 17 00:00:00 2001 From: Paul Whalen Date: Mon, 20 Jul 2026 13:09:00 -0400 Subject: [PATCH 12/14] tests(bootc): collect diagnostics on SSH failure Add network and VM diagnostics to the SSH failure block in both bootc test scripts to help debug intermittent connectivity issues. Diagnostics only run when SSH fails, not on every execution. Assisted-by: Claude Opus 4.6 Signed-off-by: Paul Whalen --- tests/greenboot-bootc-anaconda-iso.sh | 6 ++++++ tests/greenboot-bootc-qcow2.sh | 8 ++++++++ 2 files changed, 14 insertions(+) diff --git a/tests/greenboot-bootc-anaconda-iso.sh b/tests/greenboot-bootc-anaconda-iso.sh index 68ca43a..27775d5 100755 --- a/tests/greenboot-bootc-anaconda-iso.sh +++ b/tests/greenboot-bootc-anaconda-iso.sh @@ -357,7 +357,13 @@ done if [[ $RESULTS != 1 ]]; then greenprint "SSH failed on initial boot โ€” collecting VM diagnostics" sudo virsh domstate "${TEST_UUID}-uefi" || true + sudo virsh domiflist "${TEST_UUID}-uefi" || true sudo virsh net-dhcp-leases integration || true + sudo ip addr show integration || true + greenprint "Firewall zone for integration bridge:" + sudo firewall-cmd --get-zone-of-interface=integration || true + greenprint "Connectivity test:" + ping -c 2 -W 2 192.168.100.50 || true greenprint "VM console output (last 100 lines):" sudo tail -100 ${CONSOLE_LOG} 2>/dev/null || true fi diff --git a/tests/greenboot-bootc-qcow2.sh b/tests/greenboot-bootc-qcow2.sh index 3875a82..9b32486 100755 --- a/tests/greenboot-bootc-qcow2.sh +++ b/tests/greenboot-bootc-qcow2.sh @@ -346,7 +346,15 @@ done if [[ $RESULTS != 1 ]]; then greenprint "SSH failed on initial boot โ€” collecting VM diagnostics" sudo virsh domstate "${TEST_UUID}-uefi" || true + sudo virsh domiflist "${TEST_UUID}-uefi" || true sudo virsh net-dhcp-leases integration || true + sudo ip addr show integration || true + greenprint "Firewall zone for integration bridge:" + sudo firewall-cmd --get-zone-of-interface=integration || true + greenprint "Connectivity test:" + ping -c 2 -W 2 192.168.100.50 || true + greenprint "Disk image info:" + qemu-img info "${LIBVIRT_IMAGE_PATH_UEFI}" || true greenprint "VM console output (last 100 lines):" sudo tail -100 ${CONSOLE_LOG} 2>/dev/null || true fi From e37fd0f9defe6d56c1f7d94013514e86403ff081 Mon Sep 17 00:00:00 2001 From: Paul Whalen Date: Mon, 20 Jul 2026 15:50:54 -0400 Subject: [PATCH 13/14] ci: run fedora-45 bootc tests on stable Fedora 44 host' MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Decouple the host OS from the test target for fedora-45 bootc tests. The Testing Farm compose is changed from Fedora-Rawhide to Fedora-44 (stable), while TARGET_DISTRO=fedora-45 is passed to select the correct container base image and OS variant. The bootc tests only need podman and libvirt on the host โ€” the actual OS under test runs inside the VM. Assisted-by: Claude Opus 4.6 Signed-off-by: Paul Whalen --- .github/workflows/comment-ci.yaml | 4 ++-- .github/workflows/greenboot-ci.yaml | 4 ++-- tests/greenboot-bootc-anaconda-iso.sh | 3 +++ tests/greenboot-bootc-qcow2.sh | 3 +++ 4 files changed, 10 insertions(+), 4 deletions(-) diff --git a/.github/workflows/comment-ci.yaml b/.github/workflows/comment-ci.yaml index bf0b8ea..99ecc14 100644 --- a/.github/workflows/comment-ci.yaml +++ b/.github/workflows/comment-ci.yaml @@ -122,7 +122,7 @@ jobs: - name: Run the tests uses: sclorg/testing-farm-as-github-action@230555baceb860aa468d216f1822974836b965d1 # v4.3.1 with: - compose: Fedora-Rawhide + compose: Fedora-44 api_key: ${{ secrets.TF_API_PUB_KEY }} git_url: ${{ needs.check-pull-request.outputs.repo_url }} git_ref: ${{ needs.check-pull-request.outputs.ref }} @@ -130,7 +130,7 @@ jobs: pull_request_status_name: fedora-45-bootc tmt_context: "arch=x86_64;distro=fedora-45" tmt_plan_regex: bootc - variables: "ARCH=x86_64;PR_NUMBER=${{ needs.check-pull-request.outputs.pr_number }}" + variables: "ARCH=x86_64;TARGET_DISTRO=fedora-45;PR_NUMBER=${{ needs.check-pull-request.outputs.pr_number }}" timeout: 90 secrets: "QUAY_USERNAME=${{ secrets.QUAY_USERNAME }};QUAY_PASSWORD=${{ secrets.QUAY_PASSWORD }};STAGE_REDHAT_IO_USERNAME=${{ secrets.STAGE_REDHAT_IO_USERNAME }};STAGE_REDHAT_IO_TOKEN=${{ secrets.STAGE_REDHAT_IO_TOKEN }};DOWNLOAD_NODE=${{ secrets.DOWNLOAD_NODE }}" diff --git a/.github/workflows/greenboot-ci.yaml b/.github/workflows/greenboot-ci.yaml index f4ff86c..7980b49 100644 --- a/.github/workflows/greenboot-ci.yaml +++ b/.github/workflows/greenboot-ci.yaml @@ -122,7 +122,7 @@ jobs: - name: Run the tests uses: sclorg/testing-farm-as-github-action@230555baceb860aa468d216f1822974836b965d1 # v4.3.1 with: - compose: Fedora-Rawhide + compose: Fedora-44 api_key: ${{ secrets.TF_API_PUB_KEY }} git_url: ${{ needs.check-pull-request.outputs.repo_url }} git_ref: ${{ needs.check-pull-request.outputs.ref }} @@ -130,7 +130,7 @@ jobs: pull_request_status_name: fedora-45-bootc tmt_context: "arch=x86_64;distro=fedora-45" tmt_plan_regex: bootc - variables: "ARCH=x86_64;PR_NUMBER=${{ needs.check-pull-request.outputs.pr_number }}" + variables: "ARCH=x86_64;TARGET_DISTRO=fedora-45;PR_NUMBER=${{ needs.check-pull-request.outputs.pr_number }}" timeout: 90 secrets: "QUAY_USERNAME=${{ secrets.QUAY_USERNAME }};QUAY_PASSWORD=${{ secrets.QUAY_PASSWORD }};STAGE_REDHAT_IO_USERNAME=${{ secrets.STAGE_REDHAT_IO_USERNAME }};STAGE_REDHAT_IO_TOKEN=${{ secrets.STAGE_REDHAT_IO_TOKEN }};DOWNLOAD_NODE=${{ secrets.DOWNLOAD_NODE }}" diff --git a/tests/greenboot-bootc-anaconda-iso.sh b/tests/greenboot-bootc-anaconda-iso.sh index 27775d5..deefe9f 100755 --- a/tests/greenboot-bootc-anaconda-iso.sh +++ b/tests/greenboot-bootc-anaconda-iso.sh @@ -22,6 +22,9 @@ echo -e "\033[0m" # Get OS info source /etc/os-release +if [[ -n "${TARGET_DISTRO:-}" ]]; then + IFS='-' read -r ID VERSION_ID <<< "${TARGET_DISTRO}" +fi # Setup variables TEST_UUID=anaconda-$((1 + RANDOM % 1000000)) diff --git a/tests/greenboot-bootc-qcow2.sh b/tests/greenboot-bootc-qcow2.sh index 9b32486..0171ea6 100755 --- a/tests/greenboot-bootc-qcow2.sh +++ b/tests/greenboot-bootc-qcow2.sh @@ -22,6 +22,9 @@ echo -e "\033[0m" # Get OS info source /etc/os-release +if [[ -n "${TARGET_DISTRO:-}" ]]; then + IFS='-' read -r ID VERSION_ID <<< "${TARGET_DISTRO}" +fi # Setup variables TEST_UUID=qcow2-$((1 + RANDOM % 1000000)) From 07c551086fdbb38222563a4a73e39e3f3a1569e6 Mon Sep 17 00:00:00 2001 From: Paul Whalen Date: Mon, 20 Jul 2026 15:53:56 -0400 Subject: [PATCH 14/14] ci: add Fedora IoT ostree testing with pre-built raw images Use pre-built daily Fedora IoT raw images from kojipkgs instead of building ostree commits with osbuild-composer. Greenboot is installed from Packit Copr PR builds via rpm-ostree override replace. This also runs fedora-45 ostree on a stable Fedora 44 host via TARGET_DISTRO. CentOS/RHEL ostree tests still use osbuild-composer. Signed-off-by: Paul Whalen --- .github/workflows/comment-ci.yaml | 48 +++ .github/workflows/greenboot-ci.yaml | 48 +++ testing_assets/failing_binary.aarch64 | Bin 0 -> 71592 bytes testing_assets/failing_binary.x86_64 | Bin 0 -> 12384 bytes testing_assets/passing_binary.aarch64 | Bin 0 -> 71592 bytes testing_assets/passing_binary.x86_64 | Bin 0 -> 12384 bytes tests/greenboot-fedora-iot-raw.sh | 409 ++++++++++++++++++++++++++ tmt/plans/greenboot-test.fmf | 5 + tmt/tests/test.sh | 2 + 9 files changed, 512 insertions(+) create mode 100755 testing_assets/failing_binary.aarch64 create mode 100755 testing_assets/failing_binary.x86_64 create mode 100755 testing_assets/passing_binary.aarch64 create mode 100755 testing_assets/passing_binary.x86_64 create mode 100755 tests/greenboot-fedora-iot-raw.sh diff --git a/.github/workflows/comment-ci.yaml b/.github/workflows/comment-ci.yaml index 99ecc14..b1c15c3 100644 --- a/.github/workflows/comment-ci.yaml +++ b/.github/workflows/comment-ci.yaml @@ -134,6 +134,54 @@ jobs: timeout: 90 secrets: "QUAY_USERNAME=${{ secrets.QUAY_USERNAME }};QUAY_PASSWORD=${{ secrets.QUAY_PASSWORD }};STAGE_REDHAT_IO_USERNAME=${{ secrets.STAGE_REDHAT_IO_USERNAME }};STAGE_REDHAT_IO_TOKEN=${{ secrets.STAGE_REDHAT_IO_TOKEN }};DOWNLOAD_NODE=${{ secrets.DOWNLOAD_NODE }}" + fedora-44-ostree: + needs: check-pull-request + if: ${{ needs.check-pull-request.outputs.allowed_user == 'true' }} + continue-on-error: true + runs-on: ubuntu-latest + permissions: + statuses: write + + steps: + - name: Run the tests + uses: sclorg/testing-farm-as-github-action@230555baceb860aa468d216f1822974836b965d1 # v4.3.1 + with: + compose: Fedora-44 + api_key: ${{ secrets.TF_API_PUB_KEY }} + git_url: ${{ needs.check-pull-request.outputs.repo_url }} + git_ref: ${{ needs.check-pull-request.outputs.ref }} + update_pull_request_status: true + pull_request_status_name: fedora-44-ostree + tmt_context: "arch=x86_64;distro=fedora-44" + tmt_plan_regex: fedora-iot-raw + variables: "ARCH=x86_64;PR_NUMBER=${{ needs.check-pull-request.outputs.pr_number }}" + timeout: 90 + secrets: "QUAY_USERNAME=${{ secrets.QUAY_USERNAME }};QUAY_PASSWORD=${{ secrets.QUAY_PASSWORD }};STAGE_REDHAT_IO_USERNAME=${{ secrets.STAGE_REDHAT_IO_USERNAME }};STAGE_REDHAT_IO_TOKEN=${{ secrets.STAGE_REDHAT_IO_TOKEN }};DOWNLOAD_NODE=${{ secrets.DOWNLOAD_NODE }}" + + fedora-45-ostree: + needs: check-pull-request + if: ${{ needs.check-pull-request.outputs.allowed_user == 'true' }} + continue-on-error: true + runs-on: ubuntu-latest + permissions: + statuses: write + + steps: + - name: Run the tests + uses: sclorg/testing-farm-as-github-action@230555baceb860aa468d216f1822974836b965d1 # v4.3.1 + with: + compose: Fedora-44 + api_key: ${{ secrets.TF_API_PUB_KEY }} + git_url: ${{ needs.check-pull-request.outputs.repo_url }} + git_ref: ${{ needs.check-pull-request.outputs.ref }} + update_pull_request_status: true + pull_request_status_name: fedora-45-ostree + tmt_context: "arch=x86_64;distro=fedora-45" + tmt_plan_regex: fedora-iot-raw + variables: "ARCH=x86_64;TARGET_DISTRO=fedora-45;PR_NUMBER=${{ needs.check-pull-request.outputs.pr_number }}" + timeout: 90 + secrets: "QUAY_USERNAME=${{ secrets.QUAY_USERNAME }};QUAY_PASSWORD=${{ secrets.QUAY_PASSWORD }};STAGE_REDHAT_IO_USERNAME=${{ secrets.STAGE_REDHAT_IO_USERNAME }};STAGE_REDHAT_IO_TOKEN=${{ secrets.STAGE_REDHAT_IO_TOKEN }};DOWNLOAD_NODE=${{ secrets.DOWNLOAD_NODE }}" + centos-9-ostree: needs: check-pull-request if: ${{ needs.check-pull-request.outputs.allowed_user == 'true' }} diff --git a/.github/workflows/greenboot-ci.yaml b/.github/workflows/greenboot-ci.yaml index 7980b49..5d86c56 100644 --- a/.github/workflows/greenboot-ci.yaml +++ b/.github/workflows/greenboot-ci.yaml @@ -134,6 +134,54 @@ jobs: timeout: 90 secrets: "QUAY_USERNAME=${{ secrets.QUAY_USERNAME }};QUAY_PASSWORD=${{ secrets.QUAY_PASSWORD }};STAGE_REDHAT_IO_USERNAME=${{ secrets.STAGE_REDHAT_IO_USERNAME }};STAGE_REDHAT_IO_TOKEN=${{ secrets.STAGE_REDHAT_IO_TOKEN }};DOWNLOAD_NODE=${{ secrets.DOWNLOAD_NODE }}" + fedora-44-ostree: + needs: check-pull-request + if: ${{ needs.check-pull-request.outputs.allowed_user == 'true' }} + continue-on-error: true + runs-on: ubuntu-latest + permissions: + statuses: write + + steps: + - name: Run the tests + uses: sclorg/testing-farm-as-github-action@230555baceb860aa468d216f1822974836b965d1 # v4.3.1 + with: + compose: Fedora-44 + api_key: ${{ secrets.TF_API_PUB_KEY }} + git_url: ${{ needs.check-pull-request.outputs.repo_url }} + git_ref: ${{ needs.check-pull-request.outputs.ref }} + update_pull_request_status: true + pull_request_status_name: fedora-44-ostree + tmt_context: "arch=x86_64;distro=fedora-44" + tmt_plan_regex: fedora-iot-raw + variables: "ARCH=x86_64;PR_NUMBER=${{ needs.check-pull-request.outputs.pr_number }}" + timeout: 90 + secrets: "QUAY_USERNAME=${{ secrets.QUAY_USERNAME }};QUAY_PASSWORD=${{ secrets.QUAY_PASSWORD }};STAGE_REDHAT_IO_USERNAME=${{ secrets.STAGE_REDHAT_IO_USERNAME }};STAGE_REDHAT_IO_TOKEN=${{ secrets.STAGE_REDHAT_IO_TOKEN }};DOWNLOAD_NODE=${{ secrets.DOWNLOAD_NODE }}" + + fedora-45-ostree: + needs: check-pull-request + if: ${{ needs.check-pull-request.outputs.allowed_user == 'true' }} + continue-on-error: true + runs-on: ubuntu-latest + permissions: + statuses: write + + steps: + - name: Run the tests + uses: sclorg/testing-farm-as-github-action@230555baceb860aa468d216f1822974836b965d1 # v4.3.1 + with: + compose: Fedora-44 + api_key: ${{ secrets.TF_API_PUB_KEY }} + git_url: ${{ needs.check-pull-request.outputs.repo_url }} + git_ref: ${{ needs.check-pull-request.outputs.ref }} + update_pull_request_status: true + pull_request_status_name: fedora-45-ostree + tmt_context: "arch=x86_64;distro=fedora-45" + tmt_plan_regex: fedora-iot-raw + variables: "ARCH=x86_64;TARGET_DISTRO=fedora-45;PR_NUMBER=${{ needs.check-pull-request.outputs.pr_number }}" + timeout: 90 + secrets: "QUAY_USERNAME=${{ secrets.QUAY_USERNAME }};QUAY_PASSWORD=${{ secrets.QUAY_PASSWORD }};STAGE_REDHAT_IO_USERNAME=${{ secrets.STAGE_REDHAT_IO_USERNAME }};STAGE_REDHAT_IO_TOKEN=${{ secrets.STAGE_REDHAT_IO_TOKEN }};DOWNLOAD_NODE=${{ secrets.DOWNLOAD_NODE }}" + centos-9-ostree: needs: check-pull-request if: ${{ needs.check-pull-request.outputs.allowed_user == 'true' }} diff --git a/testing_assets/failing_binary.aarch64 b/testing_assets/failing_binary.aarch64 new file mode 100755 index 0000000000000000000000000000000000000000..0aaac434437df88422e0862a27ab69a0594168a3 GIT binary patch literal 71592 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 literal 0 HcmV?d00001 diff --git a/testing_assets/failing_binary.x86_64 b/testing_assets/failing_binary.x86_64 new file mode 100755 index 0000000000000000000000000000000000000000..637d1ee09d404db93029915b4d88850a4310c6af GIT binary patch literal 12384 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 literal 0 HcmV?d00001 diff --git a/testing_assets/passing_binary.x86_64 b/testing_assets/passing_binary.x86_64 new file mode 100755 index 0000000000000000000000000000000000000000..ebe5e9eb7341489ca4a49c0a0e7ad0bb214f948b GIT binary patch literal 12384 zcmeHNZ)_Y_5udwr5*M80>@>v?NVe2!9Z|3E9LKee2G;-2$Vpt=O-n(7fC*AE? zck9Y75(ENmQofi!tyBqB{Zzr1s2?gd5)!yFZBhxLR05HYDWZ}oP*Tbt3qg*Vw=?Iv z?b$$u-~;=l-FY)_elxT4_Ro87-Mm-;dCraA4OYK)xO_N4PZO(u@#h2 z-<>-5-u}aXO`rd5bNU;*p1v2m`s-_6v~n$d{>RPh)i6mX`MdFpZ=6kE{AK$5uWnAx zj3n2RucxnE8ErD4a&Q`vf1K0zANiWXkpB7>yL!1fVLoxKB>Nrl|p_9GHhZp^K& z&uuC1KVrZSmHt=WQRL#y^egXtHvP(GEFF0*{l+b?wQ6AxTL|LG|G5*t{uDY|I`Cln z;#(V!S1Og)cKre+kw@3x=a2M%^Assw8TlI}OL=&7o#ZMvb=jc!!xCm7%s`ldFau!* z!VH8N2s037Ak4u3Dg)j5T&AzLJ8yU8bMDe|*K&VfS6{DQF6uohB$^M&@$bY)n6?H0 zT1L4u z-+TtAi&0#m@XPgXLse)FNwG<}Q6uLi0M!&hY;B1gihY{qq%_6p|3jr>AYDK@gY@uw zmC6EADl})L5_xj7Xf5OByOqk_q%gcEPO=0ZEoev9G)QL{k4q?1 z`5V|5eTXnqjz3@uW-sNuTgk=-TS9T8YC` zn1L_@VFtnsgc%4k5N06EK$w9r1OMk4Fq#aNfjCo{chDS+N{dh6{+OX^dzpWj^*_qI z{6{^+yv%Vv#=OD*P31qZwEyW=rAR7T+)$b_f4ac@ZY2dUnEw#-_c8r2({`o@nF`s% zl?}#=Uz&4Kxy>ga_*)e}o~x{nKh0Epl9!vzuW>uW|7%44J2!GTHZ+vdI&l_wR7)P$ z6M9nXN%R~~^d|eY&MC*%(w4^!U5TSmubmX_<2}hbZEWc3ISK=3QoW1Gp8kHAI+H3b zxo*y#*XFa?peGnSld@d5n8~>fo5vnXC6@2A`x3|ddNf_{F0YhrXR+Lk>lNKrCfDT_ zJx9;N^knK7Ob?}!Ff^L#-$8M7B9+*od29epOpd2|VR|H$fZQ~m>O#o5IS>6QFI-n9 zxn8G>YZ_iI+f{P%#jGD=LJP>0oq$Z)3&?=(Lz=hK#C>d_BXZ12R`+T=!OvPFou|1? zXd@kYR;PBbBhT+FKgW&iJkNOg!A+%+j@S|UL3Je7hjxfrVs$tk71TDT2+Et_-Ab^T z;)`JBgZm=dw$Z0`rzozdNG`jh7wVHRA}8Pf-7wD zepEs{eGw1xEAMBKKZ%tHw1T{EMg9U-8eQ+DZR9U2JNw{8-nSukh&HnGs?t9I!S~Nk z6>u-ez7NIX=}o175H@&SPUL^V3gtRj?!ts(|b5T4$s32+HHwkF+nNwwy(ITQml%F<&m< zv3p34{W#0=yBYKt%E?afy1vT#^2|xDoj!m2%9GEaqkB&}{%$PF+gA*f&2(CUG zwQJ6fZFv@`i0NXG@fVH%%QHCDVN!%TKhK5nUh0uHFWs^dU>VbSsA2W$)^iaQy;&1cS+AIS*06{B5ei=J)txSpt*tYGC#P=c#WL} z<7Y8^2`khmf|vQo2ICW~DE@=je*xR+nglQ3rFPzb$!6HfR{lh=8oth$7SA z{qtM^Kgr+4N%n6C@Djg>zlW9D=kGG(WuL1dicEv}9|Z6+ev|#KS^yu6|8;ENhX+4y z)$x<;Ck^@&Ug*yeyT1l6<28f#1&bc4s3N@3H&IIWnE01*lAFLr*94Yha~mu)a!p0n-n^nR+vSI1YHj|k?QbZg5kWGEJiU&cL6 zny>ZG@G&$/dev/null 2>&1; do + sleep 1 + fw_elapsed=$((fw_elapsed + 1)) + if ! systemctl is-active --quiet firewalld; then + echo "firewalld systemd unit is not active" >&2 + sudo systemctl status firewalld --no-pager >&2 || true + exit 1 + fi + if [[ ${fw_elapsed} -ge ${fw_timeout} ]]; then + echo "firewalld did not become ready after ${fw_timeout} seconds" >&2 + exit 1 + fi +done + +# Start libvirtd and test it. +greenprint "๐Ÿš€ Starting libvirt daemon" +sudo systemctl start libvirtd +sudo virsh list --all > /dev/null + +# Set a customized dnsmasq configuration for libvirt so we always get the +# same address on boot up. +greenprint "๐Ÿ’ก Setup libvirt network" +sudo tee /tmp/integration.xml > /dev/null << EOF + + integration + 1c8fe98c-b53a-4ca4-bbdb-deb0f26b3579 + + + + + + + + + + + + + + +EOF +if ! sudo virsh net-info integration > /dev/null 2>&1; then + sudo virsh net-define /tmp/integration.xml +fi +if [[ $(sudo virsh net-info integration | grep 'Active' | awk '{print $2}') == 'no' ]]; then + sudo virsh net-start integration +fi + +# Allow anyone in the wheel group to talk to libvirt. +greenprint "๐Ÿšช Allowing users in wheel group to talk to libvirt" +sudo tee /etc/polkit-1/rules.d/50-libvirt.rules > /dev/null << EOF +polkit.addRule(function(action, subject) { + if (action.id == "org.libvirt.unix.manage" && + subject.isInGroup("adm")) { + return polkit.Result.YES; + } +}); +EOF + +# Wait for the ssh server up to be. +wait_for_ssh_up () { + SSH_STATUS=$(sudo ssh "${SSH_OPTIONS[@]}" -i "${SSH_KEY}" "${SSH_USER}@${1}" '/bin/bash -c "echo -n READY"') + if [[ $SSH_STATUS == READY ]]; then + echo 1 + else + echo 0 + fi +} + +# Clean up our mess. +clean_up () { + greenprint "๐Ÿงผ Cleaning up" + sudo virsh destroy "${IMAGE_KEY}" + sudo virsh undefine "${IMAGE_KEY}" --nvram + sudo rm -f "/var/lib/libvirt/images/${IMAGE_KEY}.raw" + # Remove tmp dir. + sudo rm -rf "$TEMPDIR" +} + +# Test result checking +check_result () { + greenprint "Checking for test result" + if [[ $RESULTS == 1 ]]; then + greenprint "๐Ÿ’š Success" + else + greenprint "โŒ Failed" + clean_up + exit 1 + fi +} + +################################################## +## +## Download and prepare Fedora IoT raw image +## +################################################## + +greenprint "๐Ÿ“ฅ Downloading Fedora IoT ${FEDORA_VERSION} raw image" +COMPOSE_URL="https://kojipkgs.fedoraproject.org/compose/iot/latest-Fedora-IoT-${FEDORA_VERSION}/compose/IoT/${ARCH}/images/" +RAW_IMAGE_FILENAME=$(curl -sSf "${COMPOSE_URL}" | grep -oP "Fedora-IoT-raw-${FEDORA_VERSION}-[^\"]+\.${ARCH}\.raw\.xz" | head -1) + +if [[ -z "${RAW_IMAGE_FILENAME}" ]]; then + echo "Failed to find raw image at ${COMPOSE_URL}" + exit 1 +fi + +curl -L -o "${TEMPDIR}/${RAW_IMAGE_FILENAME}" "${COMPOSE_URL}${RAW_IMAGE_FILENAME}" + +greenprint "๐Ÿ“ฆ Decompressing raw image" +xz -d "${TEMPDIR}/${RAW_IMAGE_FILENAME}" +RAW_IMAGE="${TEMPDIR}/${RAW_IMAGE_FILENAME%.xz}" + +greenprint "๐Ÿ“ฆ Preparing raw image" +LIBVIRT_IMAGE_PATH=/var/lib/libvirt/images/${IMAGE_KEY}.raw +sudo cp "${RAW_IMAGE}" "${LIBVIRT_IMAGE_PATH}" +rm -f "${RAW_IMAGE}" +sudo qemu-img resize "${LIBVIRT_IMAGE_PATH}" +10G + +greenprint "๐Ÿ”ง Resizing root partition" +echo ", +" | sudo sfdisk -N 3 "${LIBVIRT_IMAGE_PATH}" + +greenprint "๐Ÿ”‘ Injecting SSH key via kpartx" +sudo kpartx -av "${LIBVIRT_IMAGE_PATH}" +LOOP_DEV=$(sudo kpartx -l "${LIBVIRT_IMAGE_PATH}" | head -1 | awk '{print $1}' | sed 's/p[0-9]*$//') +ROOT_PART="/dev/mapper/${LOOP_DEV}p3" + +sudo e2fsck -f "${ROOT_PART}" -y +sudo resize2fs "${ROOT_PART}" + +MOUNT_DIR="${TEMPDIR}/root" +mkdir -p "${MOUNT_DIR}" +sudo mount "${ROOT_PART}" "${MOUNT_DIR}" + +sudo mkdir -p "${MOUNT_DIR}/ostree/deploy/fedora-iot/var/roothome/.ssh" +cat "${SSH_KEY}.pub" | sudo tee -a "${MOUNT_DIR}/ostree/deploy/fedora-iot/var/roothome/.ssh/authorized_keys" +sudo chmod -R u=rwX,o=,g= "${MOUNT_DIR}/ostree/deploy/fedora-iot/var/roothome/.ssh/" + +sudo umount "${MOUNT_DIR}" +sudo kpartx -dv "${LIBVIRT_IMAGE_PATH}" + +################################################## +## +## Boot VM from raw image +## +################################################## + +greenprint "๐Ÿš€ Installing VM from raw image" +sudo virt-install --name="${IMAGE_KEY}"\ + --disk path="${LIBVIRT_IMAGE_PATH}",format=raw \ + --ram 4096 \ + --vcpus 2 \ + --network network=integration,mac=34:49:22:B0:83:30 \ + --os-variant ${OS_VARIANT} \ + --boot ${BOOT_ARGS} \ + --graphics none \ + --serial file,path=${CONSOLE_LOG} \ + --noautoconsole \ + --wait=-1 \ + --import \ + --noreboot + +greenprint "Start VM" +sudo virsh start "${IMAGE_KEY}" + +# Check for ssh ready to go. +greenprint "๐Ÿ›ƒ Checking for SSH is ready to go" +for _ in $(seq 0 30); do + RESULTS="$(wait_for_ssh_up $GUEST_ADDRESS)" + if [[ $RESULTS == 1 ]]; then + echo "SSH is ready now! ๐Ÿฅณ" + break + fi + sleep 10 +done + +if [[ $RESULTS != 1 ]]; then + greenprint "SSH failed โ€” collecting VM diagnostics" + sudo virsh domstate "${IMAGE_KEY}" || true + sudo virsh net-dhcp-leases integration || true + greenprint "VM console output (last 100 lines):" + sudo tail -100 ${CONSOLE_LOG} 2>/dev/null || true +fi +check_result + +################################################## +## +## Install greenboot from Copr PR build +## +################################################## + +greenprint "๐Ÿ“ฆ Enabling Packit Copr repo for PR #${PR_NUMBER}" +for _ in $(seq 0 30); do + ssh "${SSH_OPTIONS[@]}" -i "${SSH_KEY}" "${SSH_USER}@${GUEST_ADDRESS}" \ + "sudo dnf copr enable -y packit/fedora-iot-greenboot-rs-${PR_NUMBER}" + copr_result=$? + if [[ $copr_result == 0 ]]; then + break + fi + greenprint "Copr repo not ready yet, retrying in 30 seconds..." + sleep 30 +done + +if [[ $copr_result != 0 ]]; then + greenprint "โŒ Failed to enable Copr repo after retries" + clean_up + exit 1 +fi + +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" + +greenprint "๐Ÿ“ฆ Replacing greenboot packages with PR build" +ssh "${SSH_OPTIONS[@]}" -i "${SSH_KEY}" "${SSH_USER}@${GUEST_ADDRESS}" \ + "sudo rpm-ostree override replace /tmp/greenboot-rpms/*.rpm" + +greenprint "๐Ÿ”„ Rebooting to activate new deployment" +ssh "${SSH_OPTIONS[@]}" -i "${SSH_KEY}" "${SSH_USER}@${GUEST_ADDRESS}" \ + "nohup sudo systemctl reboot &>/dev/null & exit" + +sleep 30 + +# Check for ssh ready to go after reboot. +greenprint "๐Ÿ›ƒ Checking for SSH after greenboot upgrade reboot" +for _ in $(seq 0 30); do + RESULTS="$(wait_for_ssh_up $GUEST_ADDRESS)" + if [[ $RESULTS == 1 ]]; then + echo "SSH is ready now! ๐Ÿฅณ" + break + fi + sleep 10 +done + +if [[ $RESULTS != 1 ]]; then + greenprint "SSH failed after greenboot upgrade โ€” collecting VM diagnostics" + sudo virsh domstate "${IMAGE_KEY}" || true + sudo virsh net-dhcp-leases integration || true + greenprint "VM console output (last 100 lines):" + sudo tail -100 ${CONSOLE_LOG} 2>/dev/null || true +fi +check_result + +################################################## +## +## Configure greenboot and deploy test assets +## +################################################## + +greenprint "๐Ÿ”ง Configuring greenboot on VM" +ssh "${SSH_OPTIONS[@]}" -i "${SSH_KEY}" "${SSH_USER}@${GUEST_ADDRESS}" \ + "sudo sed -i 's/GREENBOOT_MAX_BOOT_ATTEMPTS=3/GREENBOOT_MAX_BOOT_ATTEMPTS=5/g' /etc/greenboot/greenboot.conf" +ssh "${SSH_OPTIONS[@]}" -i "${SSH_KEY}" "${SSH_USER}@${GUEST_ADDRESS}" \ + "sudo sed -i 's#DISABLED_HEALTHCHECKS=()#DISABLED_HEALTHCHECKS=(\"01_repository_dns_check.sh\" \"not_exit.sh\")#g' /etc/greenboot/greenboot.conf" + +greenprint "๐Ÿ›ƒ Copying binary and script files to VM" + +# Create red.d and green.d directories if they don't exist +ssh "${SSH_OPTIONS[@]}" -i "${SSH_KEY}" "${SSH_USER}@${GUEST_ADDRESS}" "sudo mkdir -p /etc/greenboot/red.d /etc/greenboot/green.d" + +# Copy all files to temp directory first +scp "${SSH_OPTIONS[@]}" -i "${SSH_KEY}" ../testing_assets/failing_binary."${ARCH}" "${SSH_USER}@${GUEST_ADDRESS}":/tmp/failing_binary +scp "${SSH_OPTIONS[@]}" -i "${SSH_KEY}" ../testing_assets/passing_binary."${ARCH}" "${SSH_USER}@${GUEST_ADDRESS}":/tmp/passing_binary +scp "${SSH_OPTIONS[@]}" -i "${SSH_KEY}" ../testing_assets/failing_script.sh "${SSH_USER}@${GUEST_ADDRESS}":/tmp/ +scp "${SSH_OPTIONS[@]}" -i "${SSH_KEY}" ../testing_assets/passing_script.sh "${SSH_USER}@${GUEST_ADDRESS}":/tmp/ + +# Setup all directories +greenprint "๐Ÿ›ƒ Setting up red.d directory files" +ssh "${SSH_OPTIONS[@]}" -i "${SSH_KEY}" "${SSH_USER}@${GUEST_ADDRESS}" "sudo cp /tmp/failing_binary /etc/greenboot/red.d/" +ssh "${SSH_OPTIONS[@]}" -i "${SSH_KEY}" "${SSH_USER}@${GUEST_ADDRESS}" "sudo cp /tmp/passing_binary /etc/greenboot/red.d/" +ssh "${SSH_OPTIONS[@]}" -i "${SSH_KEY}" "${SSH_USER}@${GUEST_ADDRESS}" "sudo cp /tmp/failing_script.sh /etc/greenboot/red.d/" +ssh "${SSH_OPTIONS[@]}" -i "${SSH_KEY}" "${SSH_USER}@${GUEST_ADDRESS}" "sudo cp /tmp/passing_script.sh /etc/greenboot/red.d/" + +greenprint "๐Ÿ›ƒ Setting up green.d directory files" +ssh "${SSH_OPTIONS[@]}" -i "${SSH_KEY}" "${SSH_USER}@${GUEST_ADDRESS}" "sudo cp /tmp/failing_binary /etc/greenboot/green.d/" +ssh "${SSH_OPTIONS[@]}" -i "${SSH_KEY}" "${SSH_USER}@${GUEST_ADDRESS}" "sudo cp /tmp/passing_binary /etc/greenboot/green.d/" +ssh "${SSH_OPTIONS[@]}" -i "${SSH_KEY}" "${SSH_USER}@${GUEST_ADDRESS}" "sudo cp /tmp/failing_script.sh /etc/greenboot/green.d/" +ssh "${SSH_OPTIONS[@]}" -i "${SSH_KEY}" "${SSH_USER}@${GUEST_ADDRESS}" "sudo cp /tmp/passing_script.sh /etc/greenboot/green.d/" + +# Setup check directories +greenprint "๐Ÿ›ƒ Copying binary check files to VM" +ssh "${SSH_OPTIONS[@]}" -i "${SSH_KEY}" "${SSH_USER}@${GUEST_ADDRESS}" "sudo mv /tmp/failing_binary /etc/greenboot/check/wanted.d/" +ssh "${SSH_OPTIONS[@]}" -i "${SSH_KEY}" "${SSH_USER}@${GUEST_ADDRESS}" "sudo mv /tmp/passing_binary /etc/greenboot/check/required.d/" + +# Clean up remaining temp files +ssh "${SSH_OPTIONS[@]}" -i "${SSH_KEY}" "${SSH_USER}@${GUEST_ADDRESS}" "sudo rm -f /tmp/failing_script.sh /tmp/passing_script.sh" + +# Add instance IP address into /etc/ansible/hosts +tee "${TEMPDIR}"/inventory > /dev/null << EOF +[ostree_guest] +${GUEST_ADDRESS} +[ostree_guest:vars] +ansible_python_interpreter=/usr/bin/python3 +ansible_user=${SSH_USER} +ansible_private_key_file=${SSH_KEY} +ansible_ssh_common_args="-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null" +EOF + +# Test IoT/Edge OS +ansible-playbook -v -i "${TEMPDIR}/inventory" greenboot-ostree.yaml || RESULTS=0 + +# Check test result +check_result + +# Final success clean up +clean_up + +exit 0 diff --git a/tmt/plans/greenboot-test.fmf b/tmt/plans/greenboot-test.fmf index 2669f33..562979d 100644 --- a/tmt/plans/greenboot-test.fmf +++ b/tmt/plans/greenboot-test.fmf @@ -27,3 +27,8 @@ provision: environment+: TEST_CASE: ostree-commit +/fedora-iot-raw: + summary: Test greenboot with pre-built Fedora IoT raw image + environment+: + TEST_CASE: fedora-iot-raw + diff --git a/tmt/tests/test.sh b/tmt/tests/test.sh index 2137c62..c8a410e 100755 --- a/tmt/tests/test.sh +++ b/tmt/tests/test.sh @@ -10,6 +10,8 @@ function run_tests() { ./greenboot-bootc-anaconda-iso.sh elif [ "$TEST_CASE" = "ostree-commit" ]; then ./greenboot-ostree.sh + elif [ "$TEST_CASE" = "fedora-iot-raw" ]; then + ./greenboot-fedora-iot-raw.sh else echo "Error: Test case $TEST_CASE not found!" exit 1