Skip to content

Commit 6f15e8a

Browse files
ArrayBolt3zeha
authored andcommitted
Add RPi image CI testing
1 parent fe244d7 commit 6f15e8a

5 files changed

Lines changed: 101 additions & 21 deletions

File tree

.github/workflows/test-build.yml

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,18 @@ jobs:
5858
- ubuntu-latest
5959
- ubuntu-24.04-arm
6060

61+
target:
62+
- VM
63+
- RPI
64+
65+
exclude:
66+
# don't try to do raspi tests on amd64
67+
- runner: ubuntu-latest
68+
target: RPI
69+
# don't do raspi tests on <= bookworm hosts, needs at least QEMU 9.x
70+
- host_release: bookworm
71+
target: RPI
72+
6173
# We want a working shell, qemu, python and docker. Specific version should not matter (much).
6274
runs-on: ${{ matrix.runner }}
6375

@@ -73,22 +85,24 @@ jobs:
7385
name: "Setup test environment"
7486

7587
- run: ./tests/build-vm-and-test.sh run
76-
name: "Build VM image using grml-debootstrap on host ${{matrix.host_release}} for ${{matrix.release}}"
88+
name: "Build ${{matrix.target}} image using grml-debootstrap on host ${{matrix.host_release}} for ${{matrix.release}}"
7789
env:
7890
HOST_RELEASE: ${{matrix.host_release}}
7991
RELEASE: ${{matrix.release}}
92+
TARGET: ${{matrix.target}}
8093

8194
- run: ./tests/build-vm-and-test.sh test
8295
id: build_vm_and_test_test
83-
name: "Test built VM image for ${{matrix.release}}"
96+
name: "Test built ${{matrix.target}} image for ${{matrix.release}}"
8497
env:
8598
RELEASE: ${{matrix.release}}
99+
TARGET: ${{matrix.target}}
86100

87101
- name: Archive VM image on failure
88102
uses: actions/upload-artifact@v6
89103
if: always() && (steps.build_vm_and_test_test.outcome == 'failure')
90104
with:
91-
name: vm-image-${{matrix.host_release}}-${{matrix.release}}-${{matrix.runner}}
105+
name: vm-image-${{matrix.host_release}}-${{matrix.release}}-${{matrix.runner}}-${{matrix.target}}
92106
if-no-files-found: error
93107
path: qemu.img
94108
retention-days: 5
@@ -97,6 +111,6 @@ jobs:
97111
uses: actions/upload-artifact@v6
98112
if: always()
99113
with:
100-
name: vm-results-${{matrix.host_release}}-${{matrix.release}}-${{matrix.runner}}
114+
name: vm-results-${{matrix.host_release}}-${{matrix.release}}-${{matrix.runner}}-${{matrix.target}}
101115
if-no-files-found: error
102116
path: tests/results/

tests/build-vm-and-test.sh

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,9 @@ fi
5050
# Debian version to install using grml-debootstrap
5151
RELEASE="${RELEASE:-trixie}"
5252

53-
TARGET="${TARGET:-qemu.img}"
53+
RASPI="${RASPI:-no}"
54+
55+
QEMU_IMG="${QEMU_IMG:-qemu.img}"
5456

5557
if [ "$1" == "run" ]; then
5658
# Debian version on which grml-debootstrap will *run*
@@ -68,11 +70,11 @@ if [ "$1" == "run" ]; then
6870
-e TERM="$TERM" \
6971
-w /code \
7072
debian:"$HOST_RELEASE" \
71-
bash -c './tests/docker-install-deb.sh '"$DEB_NAME"' && ./tests/docker-build-vm.sh '"$(id -u)"' '"/code/$TARGET"' '"$RELEASE"
73+
bash -c './tests/docker-install-deb.sh '"$DEB_NAME"' && ./tests/docker-build-vm.sh '"$(id -u)"' '"/code/$QEMU_IMG"' '"$RELEASE"' '"$TARGET"
7274

7375
elif [ "$1" == "test" ]; then
7476
# run tests from inside Debian system
75-
exec ./tests/test-vm.sh "$PWD/$TARGET" "$RELEASE"
77+
exec ./tests/test-vm.sh "$PWD/$QEMU_IMG" "$RELEASE" "$RASPI"
7678

7779
else
7880
echo "$0: unknown parameters, see --help" >&2

tests/docker-build-vm.sh

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,15 @@
66

77
set -eu -o pipefail
88

9-
if [ "$#" -ne 3 ]; then
9+
if [ "$#" -ne 4 ]; then
1010
echo "$0: Invalid arguments" >&2
11-
echo "Expect: $0 HOST_UID TARGET RELEASE" >&2
11+
echo "Expect: $0 HOST_UID TARGET_FILE RELEASE TARGET" >&2
1212
exit 1
1313
fi
1414
HOST_UID="$1"
15-
TARGET="$2"
15+
TARGET_FILE="$2"
1616
RELEASE="$3"
17+
TARGET="$4"
1718

1819
set -x
1920

@@ -23,16 +24,22 @@ MIRROR='https://deb.debian.org/debian'
2324
echo " ****************************************************************** "
2425
echo " * Running grml-debootstrap"
2526

27+
if [ "$TARGET" = 'RPI' ]; then
28+
extra_buildopts=(--rpifile --non-free)
29+
else
30+
extra_buildopts=(--vmfile)
31+
fi
32+
2633
grml-debootstrap \
2734
--debug \
2835
--force \
29-
--vmfile \
30-
--vmsize 3G \
31-
--target "$TARGET" \
36+
"${extra_buildopts[@]}" \
37+
--imagesize 3G \
38+
--target "$TARGET_FILE" \
3239
--bootappend "console=ttyS0,115200 console=tty0 vga=791" \
3340
--password grml \
3441
--release "$RELEASE" \
3542
--hostname "$RELEASE" \
3643
--mirror "$MIRROR"
3744

38-
chown "$HOST_UID" "$TARGET"
45+
chown "$HOST_UID" "$TARGET_FILE"

tests/extract-rpi-bootdata.sh

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
#!/bin/bash
2+
VM_IMAGE="$1"
3+
WORK_DIR="${WORK_DIR:-./rpi-work}"
4+
KERN_DIR="${KERN_DIR:-./rpi-kernel}"
5+
6+
bail_noremove() {
7+
echo "$1" >&2
8+
exit 1
9+
}
10+
11+
cleanup() {
12+
if mountpoint "$WORK_DIR" >/dev/null 2>&1; then
13+
umount "$WORK_DIR" >/dev/null 2>&1
14+
fi
15+
rmdir "$WORK_DIR" >/dev/null 2>&1
16+
kpartx -d -s -v "$VM_IMAGE" >/dev/null 2>&1
17+
}
18+
19+
bail() {
20+
cleanup
21+
bail_noremove "$1"
22+
}
23+
24+
mkdir --parents "$WORK_DIR" || bail_noremove "Could not create work dir!"
25+
mkdir --parents "$KERN_DIR" || bail_noremove "Could not create kernel dir!"
26+
[ "$(cd "$WORK_DIR"; find '.')" = '.' ] || bail_noremove "Work dir is not empty!"
27+
[ "$(cd "$KERN_DIR"; find '.')" = '.' ] || bail_noremove "Kernel dir is not empty!"
28+
29+
kpartx_info="$(kpartx -a -s -v "$VM_IMAGE")"
30+
readarray -t kpartx_part_list < <(awk '{ print $3 }' <<< "$kpartx_info")
31+
[ "${#kpartx_part_list[@]}" = '2' ] || bail "VM image has wrong number of partitions!"
32+
mount /dev/mapper/"${kpartx_part_list[0]}" "$WORK_DIR"
33+
config_txt_cont="$(cat "${WORK_DIR}/config.txt")"
34+
kernel_name="$(grep '^kernel=' <<< "$config_txt_cont" | cut -d'=' -f2 | head -n1)"
35+
[ -z "$kernel_name" ] && bail 'Could not detect kernel name!'
36+
initramfs_name="$(grep '^initramfs ' <<< "$config_txt_cont" | cut -d' ' -f2 | head -n1)"
37+
[ -z "$initramfs_name" ] && bail 'Could not detect initramfs name!'
38+
cp "${WORK_DIR}/${kernel_name}" "$KERN_DIR"/
39+
cp "${WORK_DIR}/${initramfs_name}" "$KERN_DIR"/
40+
umount "$WORK_DIR"
41+
root_part_uuid="$(grep "${kpartx_part_list[1]}" < <(lsblk -f) | awk '{ print $4 }')"
42+
cleanup
43+
echo "${KERN_DIR}/${kernel_name}|${KERN_DIR}/${initramfs_name}|root=UUID=${root_part_uuid} rw"

tests/test-vm.sh

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,16 @@
66

77
set -eu -o pipefail
88

9-
if [ "$#" -ne 2 ]; then
9+
if [ "$#" -ne 3 ]; then
1010
echo "$0: Invalid arguments" >&2
11-
echo "Expect: $0 VM_IMAGE VM_HOSTNAME" >&2
11+
echo "Expect: $0 VM_IMAGE VM_HOSTNAME RASPI" >&2
1212
exit 1
1313
fi
1414
set -x
1515

1616
VM_IMAGE="$1"
1717
VM_HOSTNAME="$2"
18+
RASPI="$3"
1819

1920
TEST_PWD="$PWD"
2021
TEST_TMPDIR=$(mktemp -d)
@@ -28,7 +29,7 @@ bailout() {
2829
ps --pid="${QEMU_PID}" -o pid= | grep -q '.' && kill "${QEMU_PID:-}"
2930
fi
3031

31-
rm -rf "${TEST_TMPDIR}"
32+
sudo rm -rf "${TEST_TMPDIR}"
3233

3334
[ -n "${1:-}" ] && EXIT_CODE="$1" || EXIT_CODE=1
3435
exit "$EXIT_CODE"
@@ -72,17 +73,30 @@ declare -a qemu_command
7273

7374
DPKG_ARCHITECTURE=$(dpkg --print-architecture)
7475
if [ "${DPKG_ARCHITECTURE}" = "amd64" ]; then
75-
qemu_command=( qemu-system-x86_64 )
76-
qemu_command+=( -machine q35 )
76+
qemu_command=( qemu-system-x86_64 )
77+
qemu_command+=( -machine q35 )
7778
elif [ "${DPKG_ARCHITECTURE}" = "arm64" ]; then
79+
if [ "$RASPI" = 'yes' ]; then
80+
if ! rpi_bootdata="$(sudo "$TEST_PWD"/tests/extract-rpi-bootdata.sh "$VM_IMAGE")"; then
81+
echo "E: could not extract RPi boot data" >&2
82+
exit 1
83+
fi
84+
IFS='|' read rpi_kern rpi_initrd rpi_kerncmd <<< "$rpi_bootdata"
85+
qemu_command=( qemu-system-aarch64 )
86+
qemu_command+=( -machine "type=virt,gic-version=max,accel=kvm:tcg,highmem=off" )
87+
qemu_command+=( -kernel "$rpi_kern" )
88+
qemu_command+=( -initrd "$rpi_initrd" )
89+
qemu_command+=( -append "$rpi_kerncmd" )
90+
else
7891
cp /usr/share/AAVMF/AAVMF_VARS.fd efi_vars.fd
7992
qemu_command=( qemu-system-aarch64 )
8093
qemu_command+=( -machine "type=virt,gic-version=max,accel=kvm:tcg" )
8194
qemu_command+=( -drive "if=pflash,format=raw,unit=0,file.filename=/usr/share/AAVMF/AAVMF_CODE.no-secboot.fd,file.locking=off,readonly=on" )
8295
qemu_command+=( -drive "if=pflash,format=raw,unit=1,file=efi_vars.fd" )
96+
fi
8397
else
84-
echo "E: unsupported ${DPKG_ARCHITECTURE}"
85-
exit 1
98+
echo "E: unsupported ${DPKG_ARCHITECTURE}" >&2
99+
exit 1
86100
fi
87101
qemu_command+=( -cpu max )
88102
qemu_command+=( -smp 2 )

0 commit comments

Comments
 (0)