diff --git a/.github/workflows/test-build.yml b/.github/workflows/test-build.yml index 03d7994..b1a0e2f 100644 --- a/.github/workflows/test-build.yml +++ b/.github/workflows/test-build.yml @@ -99,6 +99,7 @@ jobs: - name: Archive VM test results uses: actions/upload-artifact@v4 + if: always() with: name: vm-results-${{matrix.host_release}}-${{matrix.release}}-${{matrix.debootstrap}} if-no-files-found: error diff --git a/tests/build-vm-and-test.sh b/tests/build-vm-and-test.sh index 1fb604d..c88c6c5 100755 --- a/tests/build-vm-and-test.sh +++ b/tests/build-vm-and-test.sh @@ -34,6 +34,8 @@ fi if [ "$1" == "setup" ]; then sudo apt-get update sudo apt-get -qq -y install curl qemu-system-x86 kpartx python3-pexpect python3-serial + # vncsnapshot might not be available, though we don't want to abort execution then + sudo apt-get -qq -y install vncsnapshot || true [ -x ./tests/goss ] || curl -fsSL https://goss.rocks/install | GOSS_DST="$(pwd)/tests" sh # TODO: docker.io exit 0 diff --git a/tests/serial-console-connection b/tests/serial-console-connection index 8778e6e..b232c46 100755 --- a/tests/serial-console-connection +++ b/tests/serial-console-connection @@ -1,6 +1,9 @@ #!/usr/bin/env python import argparse import serial +import os +import shutil +import subprocess import sys import time from pexpect import fdpexpect @@ -25,6 +28,11 @@ parser.add_argument( type=int, help="Maximum time for finding the login prompt, in seconds", ) +parser.add_argument( + "--screenshot", + default="screenshot.jpg", + help="file name for screenshot captured via VNC on error", +) parser.add_argument( "--tries", default="12", @@ -74,6 +82,21 @@ def login(ser, hostname, user, password, timeout=5): child.expect("%s@%s" % (user, hostname), timeout=timeout) +def capture_vnc_screenshot(screenshot_file): + if not shutil.which("vncsnapshot"): + print("WARN: vncsnapshot not available, skipping vnc snapshot capturing.") + return + + print("Trying to capture screenshot via vncsnapshot to", screenshot_file) + + proc = subprocess.Popen(["vncsnapshot", "localhost", screenshot_file]) + proc.wait() + if proc.returncode != 0: + print("WARN: failed to capture vnc snapshot :(") + else: + print("Screenshot file '%s' available" % os.path.abspath(screenshot_file)) + + def main(): args = parser.parse_args() hostname = args.hostname @@ -81,6 +104,7 @@ def main(): port = args.port user = args.user commands = args.command + screenshot_file = args.screenshot ser = serial.Serial(port, 115200) ser.flushInput() @@ -116,6 +140,7 @@ def main(): # after poweroff, the serial device will probably vanish. do not attempt reading from it anymore. if not success: + capture_vnc_screenshot(screenshot_file) sys.exit(1) diff --git a/tests/test-vm.sh b/tests/test-vm.sh index 85e46c5..969709d 100755 --- a/tests/test-vm.sh +++ b/tests/test-vm.sh @@ -114,12 +114,14 @@ if [ "$success" = "0" ] ; then exit 1 fi +RC=0 "$TEST_PWD"/tests/serial-console-connection \ --tries 180 \ + --screenshot "$TEST_PWD/tests/screenshot.jpg" \ --port "$serial_port" \ --hostname "$VM_HOSTNAME" \ --poweroff \ - "mount -t 9p -o trans=virtio,version=9p2000.L,rw $MOUNT_TAG /mnt && cd /mnt && ./testrunner" + "mount -t 9p -o trans=virtio,version=9p2000.L,rw $MOUNT_TAG /mnt && cd /mnt && ./testrunner" || RC=$? if [ ! -d results ] || [ ! -f ./results/goss.tap ] || [ ! -f ./results/goss.exitcode ]; then echo "Running tests inside VM failed for unknown reason" >&2 @@ -133,7 +135,14 @@ fi echo "Finished serial console connection [timeout=${timeout}]." -mv results/* "$TESTS_RESULTSDIR/" +# in case of errors we might have captured a screenshot via VNC +if [ -r "${TEST_PWD}"/tests/screenshot.jpg ] ; then + cp "${TEST_PWD}"/tests/screenshot.jpg "${TESTS_RESULTSDIR}" +fi + +if [ -d results ] ; then + mv results/* "$TESTS_RESULTSDIR/" +fi bailout $RC