Skip to content

Commit e7030fd

Browse files
authored
Add unattended USB ISO end-to-end tests for Debian and Ubuntu (#731)
* add debian release tests in CI
1 parent d250882 commit e7030fd

8 files changed

Lines changed: 792 additions & 35 deletions

File tree

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
# Builds the unattended Debian ISO and installs it from UEFI USB media in QEMU.
2+
# It completes the required reboots and verifies the installed DAppNode system.
3+
name: Debian unattended USB ISO end-to-end
4+
5+
on:
6+
workflow_dispatch:
7+
pull_request:
8+
# Weekly run against master to catch breakage from upstream package changes.
9+
schedule:
10+
- cron: "0 7 * * 1"
11+
timezone: "Europe/Madrid"
12+
13+
permissions:
14+
contents: read
15+
16+
concurrency:
17+
group: debian-iso-e2e-${{ github.ref }}
18+
cancel-in-progress: true
19+
20+
jobs:
21+
install:
22+
name: Install Debian unattended ISO via UEFI USB
23+
runs-on: ubuntu-latest
24+
timeout-minutes: 90
25+
26+
steps:
27+
- name: Checkout
28+
uses: actions/checkout@v6
29+
30+
- name: Build Debian unattended ISO
31+
run: |
32+
export BASE_OS=debian
33+
export UNATTENDED=true
34+
# Retry so a transient mirror outage does not fail the whole E2E run.
35+
for attempt in 1 2 3; do
36+
docker compose up --build --abort-on-container-exit --exit-code-from dappnode_installer && break
37+
[ "${attempt}" -lt 3 ] || exit 1
38+
echo "::warning::ISO build attempt ${attempt} failed; retrying in 30s"
39+
sleep 30
40+
done
41+
ls -lrt images/Dappnode-debian-*.iso
42+
43+
- name: Install QEMU test dependencies
44+
run: |
45+
sudo apt-get update
46+
sudo apt-get install -y --no-install-recommends qemu-system-x86 qemu-utils ovmf socat sshpass dnsmasq-base
47+
if [ -e /dev/kvm ]; then
48+
sudo chmod a+rw /dev/kvm
49+
fi
50+
51+
- name: Create the guest network
52+
run: |
53+
mkdir -p test-output/debian-e2e
54+
sudo E2E_NETWORK_STATE_DIR="${PWD}/test-output/debian-e2e/network" bash test/e2e_network.sh up
55+
56+
- name: Complete Debian unattended UEFI USB installation
57+
env:
58+
E2E_BOOT_MODE: usb
59+
E2E_FIRMWARE: uefi
60+
E2E_TAP_IFACE: dne2e0
61+
run: |
62+
debian_iso=$(find images -maxdepth 1 -type f -name 'Dappnode-debian-*-amd64-netinst.iso' -print -quit)
63+
test -n "${debian_iso}"
64+
bash test/e2e_debian_iso.sh "${debian_iso}"
65+
66+
- name: Make network logs readable
67+
if: always()
68+
run: sudo chmod -R a+rX test-output || true
69+
70+
- name: Upload installation logs
71+
if: always()
72+
uses: actions/upload-artifact@v4
73+
with:
74+
name: debian-unattended-usb-installation-logs
75+
path: test-output/debian-e2e/
76+
if-no-files-found: ignore
77+
retention-days: 7

‎.github/workflows/test.yml‎

Lines changed: 0 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -30,37 +30,3 @@ jobs:
3030
- name: Uninstall DAppNode
3131
run: |
3232
sudo /bin/bash ./scripts/dappnode_uninstall.sh y
33-
34-
iso:
35-
name: test Debian and Ubuntu ISO
36-
runs-on: ubuntu-latest
37-
38-
steps:
39-
- name: Checkout
40-
uses: actions/checkout@v6
41-
42-
# Create Debian ISO
43-
- name: create Debian ISO
44-
run: |
45-
export BASE_OS=debian
46-
export UNATTENDED=true
47-
docker compose up --build
48-
ls images/
49-
50-
# Verify Debian ISO creation
51-
- name: verify Debian ISO
52-
run: |
53-
ls -lrt images/Dappnode-debian-*.iso
54-
55-
# Create Ubuntu ISO
56-
- name: create Ubuntu ISO
57-
run: |
58-
export BASE_OS=ubuntu
59-
export UNATTENDED=true
60-
docker compose up --build
61-
ls images/
62-
63-
# Verify Ubuntu ISO creation
64-
- name: verify Ubuntu ISO
65-
run: |
66-
ls -lrt images/Dappnode-ubuntu-*.iso
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
# Builds the unattended Ubuntu ISO and installs it from UEFI USB media in QEMU.
2+
# It completes the required reboots and verifies the installed DAppNode system.
3+
name: Ubuntu unattended USB ISO end-to-end
4+
5+
on:
6+
workflow_dispatch:
7+
pull_request:
8+
# Weekly run against master to catch breakage from upstream package changes.
9+
schedule:
10+
- cron: "0 7 * * 1"
11+
timezone: "Europe/Madrid"
12+
13+
permissions:
14+
contents: read
15+
16+
concurrency:
17+
group: ubuntu-iso-e2e-${{ github.ref }}
18+
cancel-in-progress: true
19+
20+
jobs:
21+
install:
22+
name: Install Ubuntu unattended ISO via UEFI USB
23+
runs-on: ubuntu-latest
24+
timeout-minutes: 90
25+
26+
steps:
27+
- name: Checkout
28+
uses: actions/checkout@v6
29+
30+
- name: Build Ubuntu unattended ISO
31+
run: |
32+
export BASE_OS=ubuntu
33+
export UNATTENDED=true
34+
# Retry so a transient mirror outage does not fail the whole E2E run.
35+
for attempt in 1 2 3; do
36+
docker compose up --build --abort-on-container-exit --exit-code-from dappnode_installer && break
37+
[ "${attempt}" -lt 3 ] || exit 1
38+
echo "::warning::ISO build attempt ${attempt} failed; retrying in 30s"
39+
sleep 30
40+
done
41+
ls -lrt images/Dappnode-ubuntu-*.iso
42+
43+
- name: Install QEMU test dependencies
44+
run: |
45+
sudo apt-get update
46+
sudo apt-get install -y --no-install-recommends qemu-system-x86 qemu-utils ovmf socat sshpass dnsmasq-base
47+
if [ -e /dev/kvm ]; then
48+
sudo chmod a+rw /dev/kvm
49+
fi
50+
51+
- name: Create the guest network
52+
run: |
53+
mkdir -p test-output/ubuntu-e2e
54+
sudo E2E_NETWORK_STATE_DIR="${PWD}/test-output/ubuntu-e2e/network" bash test/e2e_network.sh up
55+
56+
- name: Complete Ubuntu unattended UEFI USB installation
57+
env:
58+
E2E_BOOT_MODE: usb
59+
E2E_FIRMWARE: uefi
60+
E2E_TAP_IFACE: dne2e0
61+
run: |
62+
ubuntu_iso=$(find images -maxdepth 1 -type f -name 'Dappnode-ubuntu-*-live-server-amd64.iso' -print -quit)
63+
test -n "${ubuntu_iso}"
64+
bash test/e2e_ubuntu_iso.sh "${ubuntu_iso}"
65+
66+
- name: Make network logs readable
67+
if: always()
68+
run: sudo chmod -R a+rX test-output || true
69+
70+
- name: Upload installation logs
71+
if: always()
72+
uses: actions/upload-artifact@v4
73+
with:
74+
name: ubuntu-unattended-usb-installation-logs
75+
path: test-output/ubuntu-e2e/
76+
if-no-files-found: ignore
77+
retention-days: 7

‎.gitignore‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
docs/_build
2-
images
2+
images
3+
test-output/

‎test/e2e_debian_iso.sh‎

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
#!/bin/bash
2+
# Runs the generated unattended Debian ISO through the complete UEFI USB test.
3+
# It adds Debian release and package-alignment checks to the shared harness.
4+
set -Eeuo pipefail
5+
6+
SCRIPT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
7+
REPO_ROOT=$(cd "${SCRIPT_DIR}/.." && pwd)
8+
GENERATOR="${REPO_ROOT}/iso/scripts/generate_dappnode_iso_debian.sh"
9+
PRESEED="${REPO_ROOT}/iso/preseeds/preseed_unattended.cfg"
10+
11+
base_iso_name=$(sed -n 's/^BASE_ISO_NAME="\{0,1\}\([^"[:space:]]*\)"\{0,1\}$/\1/p' "${GENERATOR}")
12+
if [[ ! "${base_iso_name}" =~ ^debian-([0-9]+)\. ]]; then
13+
echo "[ERROR] Could not determine the Debian release from BASE_ISO_NAME=${base_iso_name}"
14+
exit 1
15+
fi
16+
debian_major_version=${BASH_REMATCH[1]}
17+
18+
# The installed system must track the suite the preseed configures for APT.
19+
debian_suite=$(sed -n 's|^d-i apt-setup/local0/repository string http://deb\.debian\.org/debian/ \([a-z]*\) .*|\1|p' "${PRESEED}")
20+
if [ -z "${debian_suite}" ]; then
21+
echo "[ERROR] Could not determine the Debian suite from ${PRESEED}"
22+
exit 1
23+
fi
24+
25+
E2E_DISTRO="debian"
26+
E2E_EXPECTED_ID="debian"
27+
E2E_EXPECTED_VERSION="${debian_major_version}"
28+
E2E_EXPECTED_CODENAME="${debian_suite}"
29+
30+
source "${SCRIPT_DIR}/e2e_iso_install.sh"
31+
run_e2e_iso_install "$@"

0 commit comments

Comments
 (0)