GitHub Actions: build and test grml-debootstrap in PRs
authorChris Hofstaedtler <chris@hofstaedtler.name>
Sun, 12 Nov 2023 01:43:28 +0000 (02:43 +0100)
committerChris Hofstaedtler <chris@hofstaedtler.name>
Thu, 16 Nov 2023 09:47:11 +0000 (10:47 +0100)
14 files changed:
.github/workflows/test-build.yml [new file with mode: 0644]
.gitignore
.travis.yml [deleted file]
tests/build-vm-and-test.sh [new file with mode: 0755]
tests/docker-build-deb.sh [new file with mode: 0755]
tests/docker-build-vm.sh [new file with mode: 0755]
tests/docker-install-deb.sh [new file with mode: 0755]
tests/gha-build-deb.sh [new file with mode: 0755]
tests/goss.yaml [moved from travis/goss.yaml with 100% similarity]
tests/serial-console-connection [new file with mode: 0755]
tests/test-vm.sh [new file with mode: 0755]
travis/build-vm.sh [deleted file]
travis/execute.sh [deleted file]
travis/serial-console-connection [deleted file]

diff --git a/.github/workflows/test-build.yml b/.github/workflows/test-build.yml
new file mode 100644 (file)
index 0000000..e5cc365
--- /dev/null
@@ -0,0 +1,100 @@
+name: test-build
+on:
+  pull_request:
+concurrency:
+  group: "${{ github.ref }}"
+  cancel-in-progress: true
+jobs:
+  build-debian:
+    strategy:
+      # Keep other matrix jobs running, even if one fails.
+      fail-fast: false
+      matrix:
+        host_release:
+        - unstable
+        - trixie
+        - bookworm
+        - bullseye
+
+    # We want a working shell, qemu, python and docker. Specific version should not matter (much).
+    runs-on: ubuntu-latest
+
+    steps:
+    - uses: actions/checkout@v4
+
+    - run: ./tests/gha-build-deb.sh
+      name: "Build .deb for ${{matrix.host_release}}"
+      env:
+        HOST_RELEASE: ${{matrix.host_release}}
+
+    - name: Archive built .deb
+      uses: actions/upload-artifact@v3
+      with:
+        name: deb-${{matrix.host_release}}
+        if-no-files-found: error
+        path: |
+          *.deb
+
+  test-debian:
+    needs: build-debian
+    strategy:
+      # Keep other matrix jobs running, even if one fails.
+      fail-fast: false
+      matrix:
+        host_release:
+        - unstable
+        - trixie
+        - bookworm
+        - bullseye
+
+        release:
+        - trixie
+        - bookworm
+        - bullseye
+        - buster
+        - stretch
+
+        debootstrap:
+        - ''
+        - mmdebstrap
+
+        exclude:
+          # debootstrap in bullseye is too old.
+          - host_release: bullseye
+            release: trixie
+          # unclear how to pass --no-check-gpg to mmdebstrap
+          - release: stretch
+            debootstrap: mmdebstrap
+
+    # We want a working shell, qemu, python and docker. Specific version should not matter (much).
+    runs-on: ubuntu-latest
+
+    steps:
+    - uses: actions/checkout@v4
+
+    - name: Download built deb
+      uses: actions/download-artifact@v3
+      with:
+        name: deb-${{matrix.host_release}}
+
+    - run: ./tests/build-vm-and-test.sh setup
+      name: "Setup test environment"
+
+    - run: ./tests/build-vm-and-test.sh run
+      name: "Build VM image using grml-debootstrap on host ${{matrix.host_release}} for ${{matrix.release}} using debootstrap=${{matrix.debootstrap}}"
+      env:
+        HOST_RELEASE: ${{matrix.host_release}}
+        RELEASE: ${{matrix.release}}
+        DEBOOTSTRAP: ${{matrix.debootstrap}}
+
+    - run: ./tests/build-vm-and-test.sh test
+      name: "Test built VM image for ${{matrix.release}}"
+      env:
+        RELEASE: ${{matrix.release}}
+
+    - name: Archive VM test results
+      uses: actions/upload-artifact@v3
+      with:
+        name: vm-results-${{matrix.host_release}}-${{matrix.release}}-${{matrix.debootstrap}}
+        if-no-files-found: error
+        path: tests/results/
index 74c16de..06e1213 100644 (file)
@@ -1,3 +1,6 @@
 *.box
 packer_cache
 *_output
+qemu.img
+tests/dgoss
+tests/goss
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644 (file)
index 98b0e4b..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-language: generic
-sudo: required
-
-services:
-  - docker
-
-env:
-  - TRAVIS_DEBIAN_DISTRIBUTION=buster
-  - TRAVIS_DEBIAN_DISTRIBUTION=unstable TRAVIS_DEBIAN_INCREMENT_VERSION_NUMBER=true
-
-script:
-  - ./travis/execute.sh
-
-matrix:
-  fast_finish: true
diff --git a/tests/build-vm-and-test.sh b/tests/build-vm-and-test.sh
new file mode 100755 (executable)
index 0000000..1dc4bbc
--- /dev/null
@@ -0,0 +1,78 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0-or-later
+#
+# Install an already built grml-debootstrap.deb in docker and use it to
+# build a test VM image. Then run this VM image in qemu and check if it
+# boots.
+
+set -eu -o pipefail
+
+usage() {
+  echo "Usage: $0 setup"
+  echo " then: $0 run"
+  echo " then: $0 test"
+  echo "WARNING: $0 is potentially dangerous and may destroy the host system and/or any data."
+  exit 0
+}
+
+if [ "${1:-}" == "--help" ] || [ "${1:-}" == "help" ]; then
+  usage
+fi
+
+if [ -z "${1:-}" ]; then
+  echo "$0: unknown parameters, see --help" >&2
+  exit 1
+fi
+
+set -x
+
+if [ ! -d ./tests ]; then
+  echo "$0: Started from incorrect working directory" >&2
+  exit 1
+fi
+
+if [ "$1" == "setup" ]; then
+  [ -x ./tests/goss ] || curl -fsSL https://goss.rocks/install | GOSS_DST="$(pwd)/tests" sh
+  sudo apt-get update
+  sudo apt-get -y install qemu-system-x86 kpartx python3-pexpect python3-serial
+  # TODO: docker.io
+  exit 0
+fi
+
+# Debian version to install using grml-debootstrap
+RELEASE="${RELEASE:-bookworm}"
+
+TARGET="${TARGET:-qemu.img}"
+
+# debootstrap to use, default empty (let grml-debootstrap decide)
+DEBOOTSTRAP="${DEBOOTSTRAP:-}"
+
+if [ "$1" == "run" ]; then
+  # Debian version on which grml-debootstrap will *run*
+  HOST_RELEASE="${HOST_RELEASE:-bookworm}"
+
+  DEB_NAME=$(ls ./grml-debootstrap*.deb || true)
+  if [ -z "$DEB_NAME" ]; then
+    echo "$0: No grml-debootstrap*.deb found, aborting" >&2
+    exit 1
+  fi
+
+  # we need to run in privileged mode to be able to use loop devices
+  exec docker run --privileged --rm -i \
+    -v "$(pwd)":/code \
+    -e TERM="$TERM" \
+    -e DEBOOTSTRAP="$DEBOOTSTRAP" \
+    -w /code \
+    debian:"$HOST_RELEASE" \
+    bash -c './tests/docker-install-deb.sh '"$DEB_NAME"' && ./tests/docker-build-vm.sh '"$(id -u)"' '"/code/$TARGET"' '"$RELEASE"
+
+elif [ "$1" == "test" ]; then
+  # run tests from inside Debian system
+  exec ./tests/test-vm.sh "$PWD/$TARGET" "$RELEASE"
+
+else
+  echo "$0: unknown parameters, see --help" >&2
+  exit 1
+fi
+
+# EOF
diff --git a/tests/docker-build-deb.sh b/tests/docker-build-deb.sh
new file mode 100755 (executable)
index 0000000..f9a8c8d
--- /dev/null
@@ -0,0 +1,44 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0-or-later
+#
+# Build a grml-debootstrap.deb.
+# To be run inside docker, as this script assumes it can modify the running OS.
+
+set -eu -o pipefail
+set -x
+
+if [ "${1:-}" != "--autobuild" ]; then
+  echo "$0: Only intended for CI scenarios, will destroy source files and modify running OS." >&2
+  exit 1
+fi
+BUILD_NUMBER="${2:-}"
+if [ -z "$BUILD_NUMBER" ]; then
+  echo "$0: missing build number in arguments" >&2
+  exit 1
+fi
+
+apt-get update
+apt-get install --no-install-recommends -y build-essential devscripts equivs
+
+SOURCEDIR=$PWD
+
+cd /tmp
+mk-build-deps -ir -t 'apt-get -o Debug::pkgProblemResolver=yes --no-install-recommends -y' "$SOURCEDIR"/debian/control
+
+dpkg-source -b "$SOURCEDIR"
+dpkg-source -x ./*.dsc builddir
+cd builddir
+
+OLD_VERSION=$(dpkg-parsechangelog -SVersion)
+
+cat > debian/changelog <<EOT
+grml-debootstrap (${OLD_VERSION}+autobuild${BUILD_NUMBER}) UNRELEASED; urgency=medium
+
+  * Automated Build
+
+ -- Automated Build <builder@localhost>  $(date -R)
+EOT
+
+dpkg-buildpackage -b --no-sign
+
+mv ../*deb "$SOURCEDIR"/
diff --git a/tests/docker-build-vm.sh b/tests/docker-build-vm.sh
new file mode 100755 (executable)
index 0000000..07578f7
--- /dev/null
@@ -0,0 +1,51 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0-or-later
+#
+# Use an already installed grml-debootstrap to build a VM image, then
+# run it in qemu. Installs goss inside the VM.
+
+set -eu -o pipefail
+
+if [ "$#" -ne 3 ]; then
+  echo "$0: Invalid arguments" >&2
+  echo "Expect: $0 HOST_UID TARGET RELEASE" >&2
+  exit 1
+fi
+HOST_UID="$1"
+TARGET="$2"
+RELEASE="$3"
+
+if [ -n "${DEBOOTSTRAP:-}" ] && [ "${DEBOOTSTRAP:-}" != "debootstrap" ]; then
+  apt-get install -y "${DEBOOTSTRAP}"
+fi
+
+set -x
+
+case "${RELEASE:-}" in
+  stretch)
+    MIRROR='http://archive.debian.org/debian'
+    EXTRAOPT=--debopt=--no-check-gpg
+  ;;
+  *)
+    MIRROR='http://deb.debian.org/debian'
+    EXTRAOPT=''
+  ;;
+esac
+
+
+echo " ****************************************************************** "
+echo " * Running grml-debootstrap"
+
+grml-debootstrap \
+  --force \
+  --vmfile \
+  --vmsize 3G \
+  --target "$TARGET" \
+  --bootappend "console=ttyS0,115200 console=tty0 vga=791" \
+  --password grml \
+  --release  "$RELEASE" \
+  --hostname "$RELEASE" \
+  --mirror "$MIRROR" \
+  $EXTRAOPT
+
+chown "$HOST_UID" "$TARGET"
diff --git a/tests/docker-install-deb.sh b/tests/docker-install-deb.sh
new file mode 100755 (executable)
index 0000000..9ba38d0
--- /dev/null
@@ -0,0 +1,19 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0-or-later
+#
+# Install an already built grml-debootstrap.deb.
+# Wrapper around apt-get install for usage inside docker.
+
+set -eu -o pipefail
+
+if [ "$#" -ne 1 ]; then
+  echo "$0: Invalid arguments" >&2
+  echo "Expect: $0 DEB_NAME" >&2
+  exit 1
+fi
+DEB_NAME="$1"
+
+apt-get update
+# docker images can be relatively old, especially for unstable.
+apt-get -y upgrade
+apt-get -y install "$DEB_NAME"
diff --git a/tests/gha-build-deb.sh b/tests/gha-build-deb.sh
new file mode 100755 (executable)
index 0000000..a031c96
--- /dev/null
@@ -0,0 +1,15 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0-or-later
+#
+# Entrypoint for GitHub Actions to build a grml-debootstrap.deb.
+
+set -eu -o pipefail
+set -x
+
+if [ -z "${CI:-}" ] || [ -z "${GITHUB_RUN_NUMBER:-}" ]; then
+  echo "Running outside of CI pipeline." >&2
+  exit 1
+fi
+
+docker run --privileged -v "$(pwd)":/code --rm -i debian:"$HOST_RELEASE" \
+    bash -c 'TERM='"$TERM"' cd /code && ./tests/docker-build-deb.sh --autobuild '"$GITHUB_RUN_NUMBER"
similarity index 100%
rename from travis/goss.yaml
rename to tests/goss.yaml
diff --git a/tests/serial-console-connection b/tests/serial-console-connection
new file mode 100755 (executable)
index 0000000..97c623b
--- /dev/null
@@ -0,0 +1,105 @@
+#!/usr/bin/env python
+import argparse
+import pexpect
+import serial
+import sys
+import time
+from pexpect import fdpexpect, TIMEOUT
+
+parser = argparse.ArgumentParser(description='Connect to serial console ' +
+                                 'to execute stuff')
+parser.add_argument('--port', required=True,
+                    help='serial console device to connect ' +
+                    'to (e.g. /dev/pts/X)')
+parser.add_argument('--hostname', default="buster",
+                    help='hostname of the system for login process ' +
+                    '(default: buster)')
+parser.add_argument('--user', default="root",
+                    help='user name to use for login (default: root)')
+parser.add_argument('--password', default="grml",
+                    help='password for login (default: grml)')
+parser.add_argument('--tries', default="12", type=int,
+                    help='Number of retries for finding the login prompt')
+parser.add_argument('--poweroff', action="store_true", default=False,
+                    help='send "poweroff" command after all other commands')
+parser.add_argument('command', nargs='+',
+                    help='command to execute after logging in')
+
+
+
+def print_ser_lines(ser):
+    for line in ser.readlines():
+        print("<<", line)  # line will be a binary string
+
+
+def write_ser_line(ser, text):
+    print(">>", text)
+    ser.write(("%s\n" % text).encode())
+    ser.flush()
+
+
+def login(ser, hostname, user, password, timeout=5):
+
+    child = fdpexpect.fdspawn(ser.fileno())
+    child.sendline("\n")
+
+    try:
+        child.expect("%s@%s" % (user, hostname), timeout=timeout)
+        return
+    except:
+        pass
+
+    print("Waiting for login prompt...")
+    child.expect("%s login:" % hostname, timeout=timeout)
+    print("Logging in...")
+    write_ser_line(ser, user)
+    time.sleep(1)
+    write_ser_line(ser, password)
+    time.sleep(1)
+
+    print("Waiting for shell prompt...")
+    child.expect("%s@%s" % (user, hostname), timeout=timeout)
+
+
+def main():
+    args = parser.parse_args()
+    hostname = args.hostname
+    password = args.password
+    port = args.port
+    user = args.user
+    commands = args.command
+
+    ser = serial.Serial(port, 115200)
+    ser.flushInput()
+    ser.flushOutput()
+
+    success = False
+    for i in range(args.tries):
+        try:
+            print("Logging into %s via serial console [try %s]" % (port, i))
+            login(ser, hostname, user, password)
+            success = True
+            break
+        except Exception as except_inst:
+            print("Login failure (try %s):" % (i, ), except_inst, file=sys.stderr)
+            time.sleep(5)
+
+    if success:
+        write_ser_line(ser, "")
+        ser.timeout = 5
+        print_ser_lines(ser)
+        print("Running commands...")
+        for command in commands:
+            write_ser_line(ser, command)
+            print_ser_lines(ser)
+        if args.poweroff:
+            print("Sending final poweroff command...")
+            write_ser_line(ser, "poweroff")
+            ser.flush()
+            # after poweroff, the serial device will probably vanish. do not attempt reading from it anymore.
+
+    if not success:
+        sys.exit(1)
+
+if __name__ == "__main__":
+    main()
diff --git a/tests/test-vm.sh b/tests/test-vm.sh
new file mode 100755 (executable)
index 0000000..85e46c5
--- /dev/null
@@ -0,0 +1,140 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0-or-later
+#
+# Run previously built VM image in qemu and check if it boots.
+# Requires virtiofs support in VM.
+
+set -eu -o pipefail
+
+if [ "$#" -ne 2 ]; then
+  echo "$0: Invalid arguments" >&2
+  echo "Expect: $0 VM_IMAGE VM_HOSTNAME" >&2
+  exit 1
+fi
+set -x
+
+VM_IMAGE="$1"
+VM_HOSTNAME="$2"
+
+TEST_PWD="$PWD"
+TEST_TMPDIR=$(mktemp -d)
+TESTS_RESULTSDIR="$PWD/tests/results"
+echo "Working in $TEST_TMPDIR, writing results to $TESTS_RESULTSDIR"
+mkdir -p "$TESTS_RESULTSDIR"
+
+bailout() {
+  if [ -n "${QEMU_PID:-}" ] ; then
+    # shellcheck disable=SC2009
+    ps --pid="${QEMU_PID}" -o pid= | grep -q '.' && kill "${QEMU_PID:-}"
+  fi
+
+  rm -rf "${TEST_TMPDIR}"
+
+  [ -n "${1:-}" ] && EXIT_CODE="$1" || EXIT_CODE=1
+  exit "$EXIT_CODE"
+}
+trap bailout 1 2 3 6 14 15
+
+# Setup test runner
+cp ./tests/goss "$TEST_TMPDIR"/
+cp ./tests/goss.yaml "$TEST_TMPDIR"/
+cat <<EOT > "$TEST_TMPDIR"/testrunner
+#!/bin/bash
+# Do not set -eu, we want to continue even if individual commands fail.
+set -x
+echo "INSIDE_VM $0 running"
+mkdir results
+
+# Collect information from VM first
+lsb_release -a > results/lsb_release.txt
+uname -a > results/uname-a.txt
+systemctl list-units > results/systemctl_list-units.txt
+systemctl status > results/systemctl_status.txt
+fdisk -l > results/fdisk-l.txt
+hostname -f > results/hostname-f.txt 2>&1
+journalctl -b > results/journalctl-b.txt
+dpkg -l > results/dpkg-l.txt
+
+# Run tests
+./goss --gossfile goss.yaml validate --format tap > results/goss.tap
+# Detection of testrunner success hinges on goss.exitcode file.
+echo \$? > results/goss.exitcode
+
+echo "INSIDE_VM $0 finished"
+EOT
+chmod a+rx "$TEST_TMPDIR"/testrunner
+
+cd "$TEST_TMPDIR"
+
+MOUNT_TAG=host0
+qemu-system-x86_64 -hda "${VM_IMAGE}" -m 2048 \
+                   -display none -vnc :0 \
+                   -virtfs local,path="$TEST_TMPDIR",mount_tag="$MOUNT_TAG",security_model=none,id=host0 \
+                   -serial pty &>qemu.log &
+QEMU_PID="$!"
+
+timeout=30
+success=0
+while [ "$timeout" -gt 0 ] ; do
+  ((timeout--))
+  if grep -q 'char device redirected to ' qemu.log ; then
+    success=1
+    sleep 1
+    break
+  else
+    echo "No serial console from Qemu found yet [$timeout retries left]"
+    sleep 1
+  fi
+done
+
+if [ "$success" = "1" ] ; then
+  serial_port=$(awk '/char device redirected/ {print $5}' qemu.log)
+else
+  echo "Error: Failed to identify serial console port." >&2
+  cat qemu.log
+  exit 1
+fi
+
+timeout=30
+success=0
+while [ "$timeout" -gt 0 ] ; do
+  ((timeout--))
+  if [ -c "$serial_port" ] ; then
+    success=1
+    sleep 1
+    break
+  else
+    echo "No block device for serial console found yet [$timeout retries left]"
+    sleep 1
+  fi
+done
+
+if [ "$success" = "0" ] ; then
+  echo "Error: can't access serial console block device." >&2
+  exit 1
+fi
+
+"$TEST_PWD"/tests/serial-console-connection \
+  --tries 180 \
+  --port "$serial_port" \
+  --hostname "$VM_HOSTNAME" \
+  --poweroff \
+  "mount -t 9p -o trans=virtio,version=9p2000.L,rw $MOUNT_TAG /mnt && cd /mnt && ./testrunner"
+
+if [ ! -d results ] || [ ! -f ./results/goss.tap ] || [ ! -f ./results/goss.exitcode ]; then
+  echo "Running tests inside VM failed for unknown reason" >&2
+  RC=1
+else
+  RC=$(cat results/goss.exitcode)
+  echo "goss exitcode: $RC"
+
+  cat results/goss.tap
+fi
+
+echo "Finished serial console connection [timeout=${timeout}]."
+
+mv results/* "$TESTS_RESULTSDIR/"
+
+bailout $RC
+
+# EOF
diff --git a/travis/build-vm.sh b/travis/build-vm.sh
deleted file mode 100755 (executable)
index 217813b..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-#!/bin/bash
-
-set -eu -o pipefail
-
-TARGET="${TARGET:-/code/qemu.img}"
-RELEASE="${RELEASE:-buster}"
-
-cd "$(dirname "$TARGET")"
-apt update
-apt -y install ./grml-debootstrap*.deb
-
-grml-debootstrap \
-  --force \
-  --vmfile \
-  --vmsize 3G \
-  --target "$TARGET" \
-  --bootappend "console=ttyS0,115200 console=tty0 vga=791" \
-  --password grml \
-  --release  "$RELEASE" \
-  --hostname "$RELEASE" \
-  # EOF
diff --git a/travis/execute.sh b/travis/execute.sh
deleted file mode 100755 (executable)
index 5b4f47a..0000000
+++ /dev/null
@@ -1,172 +0,0 @@
-#!/bin/bash
-
-set -eu -o pipefail
-set -x
-
-if [ -z "${TRAVIS:-}" ] ; then
-  echo "Running outside of Travis."
-
-  if [ "$#" -ne 1 ] ; then
-    echo "Usage: $(basename "$0") ./grml-debootstrap*.deb" >&2
-    exit 1
-  else
-    GRML_DEBOOTSTRAP_DEB="$1"
-    if [ "$(dirname "$(realpath "$GRML_DEBOOTSTRAP_DEB")")" != "$(pwd)" ] ; then
-      echo "Error: the grml-debootstrap*.deb needs to be inside $(pwd) to be shared with docker container." >&2
-      exit 1
-    fi
-  fi
-fi
-
-RELEASE="${RELEASE:-buster}"
-export RELEASE
-
-TARGET="${TARGET:-qemu.img}"
-
-bailout() {
-  if [ -n "${QEMU_PID:-}" ] ; then
-    # shellcheck disable=SC2009
-    ps --pid="${QEMU_PID}" -o pid= | grep -q '.' && kill "${QEMU_PID:-}"
-  fi
-
-  if [ -f "${TARGET:-}" ] ; then
-    sudo kpartx -dv "$(realpath "${TARGET}")"
-  fi
-
-  if [ -n "${LOOP_DISK:-}" ] ; then
-    if sudo dmsetup ls | grep -q "${LOOP_DISK}"; then
-      sudo kpartx -d "/dev/${LOOP_DISK}"
-    fi
-  fi
-
-  local loopmount
-  loopmount="$(sudo losetup -a | grep "$(realpath "${TARGET}")" | cut -f1 -d: || true)"
-
-  if [ -n "${loopmount:-}" ] ; then
-    sudo losetup -d "${loopmount}"
-  fi
-
-  [ -n "${1:-}" ] && EXIT_CODE="$1" || EXIT_CODE=1
-  exit "$EXIT_CODE"
-}
-trap bailout 1 2 3 6 14 15
-
-# run shellcheck tests
-docker run koalaman/shellcheck:stable --version
-docker run --rm -v "$(pwd)":/code koalaman/shellcheck:stable -e SC2181 -e SC2001 /code/chroot-script /code/grml-debootstrap
-
-# build Debian package
-if [ -z "${TRAVIS:-}" ] ; then
-  echo "Not running under Travis, installing local grml-debootstrap package ${GRML_DEBOOTSTRAP_DEB}."
-else
-  if ! [ "${TRAVIS_DEBIAN_DISTRIBUTION:-}" = "unstable" ] ; then
-    echo "TRAVIS_DEBIAN_DISTRIBUTION is $TRAVIS_DEBIAN_DISTRIBUTION and not unstable, skipping VM build tests."
-    exit 0
-  fi
-  wget -O- https://travis.debian.net/script.sh | sh -
-  # copy only the binary from the TRAVIS_DEBIAN_INCREMENT_VERSION_NUMBER=true build
-  cp ../grml-debootstrap_*travis*deb .
-fi
-
-# we need to run in privileged mode to be able to use loop devices
-docker run --privileged -v "$(pwd)":/code --rm -i -t debian:buster /code/travis/build-vm.sh
-
-[ -x ./goss ] || curl -fsSL https://goss.rocks/install | GOSS_DST="$(pwd)" sh
-
-# Ubuntu trusty (14.04LTS) doesn't have realpath in coreutils yet
-if ! command -v realpath &>/dev/null ; then
-  REALPATH_PACKAGE=realpath
-fi
-
-sudo apt-get update
-sudo apt-get -y install qemu-system-x86 kpartx python-pexpect python-serial ${REALPATH_PACKAGE:-}
-
-# run tests from inside Debian system
-DEVINFO=$(sudo kpartx -asv "${TARGET}")
-LOOP_PART="${DEVINFO##add map }"
-LOOP_PART="${LOOP_PART// */}"
-LOOP_DISK="${LOOP_PART%p*}"
-IMG_FILE="/dev/mapper/$LOOP_PART"
-
-MNTPOINT="$(mktemp -d)"
-sudo mount "$IMG_FILE" "${MNTPOINT}"
-
-sudo cp ./goss "${MNTPOINT}"/usr/local/bin/goss
-sudo cp ./travis/goss.yaml "${MNTPOINT}"/root/goss.yaml
-
-sudo umount "${MNTPOINT}"
-sudo kpartx -dv "$(realpath "${TARGET}")"
-if sudo dmsetup ls | grep -q "${LOOP_DISK}"; then
-  sudo kpartx -d "/dev/${LOOP_DISK}"
-fi
-
-rmdir "$MNTPOINT"
-
-sudo chown "$(id -un)" qemu.img
-rm -f ./serial0
-mkfifo ./serial0
-qemu-system-x86_64 -hda qemu.img -display none -vnc :0 \
-                   -device virtio-serial-pci \
-                   -chardev pipe,id=ch0,path=./serial0 \
-                   -device virtserialport,chardev=ch0,name=serial0 \
-                   -serial pty &>qemu.log &
-QEMU_PID="$!"
-
-timeout=30
-success=0
-while [ "$timeout" -gt 0 ] ; do
-  ((timeout--))
-  if grep -q 'char device redirected to ' qemu.log ; then
-    success=1
-    sleep 1
-    break
-  else
-    echo "No serial console from Qemu found yet [$timeout retries left]"
-    sleep 1
-  fi
-done
-
-if [ "$success" = "1" ] ; then
-  serial_port=$(awk '/char device redirected/ {print $5}' qemu.log)
-else
-  echo "Error: Failed to identify serial console port." >&2
-  exit 1
-fi
-
-timeout=30
-success=0
-while [ "$timeout" -gt 0 ] ; do
-  ((timeout--))
-  if [ -c "$serial_port" ] ; then
-    success=1
-    sleep 1
-    break
-  else
-    echo "No block device for serial console found yet [$timeout retries left]"
-    sleep 1
-  fi
-done
-
-if [ "$success" = "0" ] ; then
-  echo "Error: can't access serial console block device." >&2
-  exit 1
-fi
-
-sudo chown "$(id -un)" "$serial_port"
-./travis/serial-console-connection --port "$serial_port" --hostname "$RELEASE" --pipefile "serial0" --vmoutput "vm-output.txt"
-
-cat vm-output.txt
-
-RC=0
-if grep -q '^failure_exit' vm-output.txt ; then
-  echo "We noticed failing tests."
-  RC=1
-else
-  echo "All tests passed."
-fi
-
-echo "Finished serial console connection [timeout=${timeout}]."
-
-bailout $RC
-
-# EOF
diff --git a/travis/serial-console-connection b/travis/serial-console-connection
deleted file mode 100755 (executable)
index ff3fbd0..0000000
+++ /dev/null
@@ -1,112 +0,0 @@
-#!/usr/bin/env python
-
-from __future__ import print_function
-import argparse
-import pexpect
-import serial
-import sys
-import time
-from pexpect import fdpexpect
-
-parser = argparse.ArgumentParser(description='Connect to serial console ' +
-                                 'to execute stuff')
-parser.add_argument('--port', required=True,
-                    help='serial console device to connect ' +
-                    'to (e.g. /dev/pts/X)')
-parser.add_argument('--hostname', default="buster",
-                    help='hostname of the system for login process ' +
-                    '(default: buster)')
-parser.add_argument('--pipefile', default="./serial0",
-                    help='file name for named pipe file (for ' +
-                    'interacting between host + VM via QEMU ' +
-                    '(default: ./serial0)')
-parser.add_argument('--vmoutput', default="vm-output.log",
-                    help='filename for VM output (default: vm-output.log)')
-parser.add_argument('--user', default="root",
-                    help='user name to use for login (default: root)')
-parser.add_argument('--password', default="grml",
-                    help='password for login (default: grml)')
-args = parser.parse_args()
-
-
-def execute(port, hostname, user, baudrate=115200, timeout=5):
-    ser = serial.Serial(port, baudrate)
-    ser.flushInput()
-    ser.flushOutput()
-    ser.write("\n")
-    ser.flush()
-
-    child = fdpexpect.fdspawn(ser.fileno())
-    child.sendline("")
-    try:
-        print("Begin of execution inside VM")
-        child.expect("%s@%s" % (user, hostname), timeout=timeout)
-        child.sendline("/usr/local/bin/goss --gossfile /root/goss.yaml " +
-                       "validate --format tap > /root/goss.tap ; " +
-                       "echo $? > /root/goss.exitcode\n")
-        # NOTE - the serial0 is hardcoded here
-        child.sendline("cat /root/goss.tap > /dev/virtio-ports/serial0\n")
-        child.sendline("grep -q '^0' /root/goss.exitcode && " +
-                       "echo clean_exit > /dev/virtio-ports/serial0\n")
-        child.sendline("grep -q '^0' /root/goss.exitcode || " +
-                       "echo failure_exit > /dev/virtio-ports/serial0\n")
-        child.sendline("poweroff\n")
-        print("End of execution inside VM")
-    except Exception as except_inst:
-        print("Execution inside VM failed: ", except_inst)
-
-
-def login(port, hostname, user, password,
-          baudrate=115200, timeout=5):
-    ser = serial.Serial(port, baudrate)
-    ser.flushInput()
-    ser.flushOutput()
-
-    child = fdpexpect.fdspawn(ser.fileno())
-    child.sendline("\n")
-
-    try:
-        child.expect("root@%s" % hostname, timeout=timeout)
-        return
-    except:
-        pass
-
-    print("Checking for login prompt...")
-    child.expect("%s login:" % hostname, timeout=timeout)
-    ser.write("%s\n" % user)
-    ser.flush()
-    time.sleep(1)
-    ser.write("%s\n" % password)
-    ser.flush()
-    time.sleep(1)
-    print("login ok...")
-
-
-if __name__ == "__main__":
-    hostname = args.hostname
-    password = args.password
-    pipefile = args.pipefile
-    port = args.port
-    user = args.user
-    vmoutput = args.vmoutput
-
-    with open(pipefile, 'r') as output_pipe:
-        success = False
-        for i in range(12):
-            try:
-                print("Logging into {0} via serial "
-                      "console [try {1}]".format(port, i))
-                login(port, hostname, user, password)
-                success = True
-                break
-            except Exception as except_inst:
-                print("Login failure (try {0}):".format(i),
-                      except_inst, file=sys.stderr)
-                time.sleep(5)
-
-        if success:
-            execute(port, hostname, user)
-            with open(vmoutput, 'w') as fp:
-                output = output_pipe.read()
-                print(output)
-                fp.write(output)