Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 77 additions & 0 deletions .github/workflows/debian-iso-e2e.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
# Builds the unattended Debian ISO and installs it from UEFI USB media in QEMU.
# It completes the required reboots and verifies the installed DAppNode system.
name: Debian unattended USB ISO end-to-end

on:
workflow_dispatch:
pull_request:
# Weekly run against master to catch breakage from upstream package changes.
schedule:
- cron: "0 7 * * 1"
timezone: "Europe/Madrid"

permissions:
contents: read

concurrency:
group: debian-iso-e2e-${{ github.ref }}
cancel-in-progress: true

jobs:
install:
name: Install Debian unattended ISO via UEFI USB
runs-on: ubuntu-latest
timeout-minutes: 90

steps:
- name: Checkout
uses: actions/checkout@v6

- name: Build Debian unattended ISO
run: |
export BASE_OS=debian
export UNATTENDED=true
# Retry so a transient mirror outage does not fail the whole E2E run.
for attempt in 1 2 3; do
docker compose up --build --abort-on-container-exit --exit-code-from dappnode_installer && break
[ "${attempt}" -lt 3 ] || exit 1
echo "::warning::ISO build attempt ${attempt} failed; retrying in 30s"
sleep 30
done
ls -lrt images/Dappnode-debian-*.iso

- name: Install QEMU test dependencies
run: |
sudo apt-get update
sudo apt-get install -y --no-install-recommends qemu-system-x86 qemu-utils ovmf socat sshpass dnsmasq-base
if [ -e /dev/kvm ]; then
sudo chmod a+rw /dev/kvm
fi

- name: Create the guest network
run: |
mkdir -p test-output/debian-e2e
sudo E2E_NETWORK_STATE_DIR="${PWD}/test-output/debian-e2e/network" bash test/e2e_network.sh up

- name: Complete Debian unattended UEFI USB installation
env:
E2E_BOOT_MODE: usb
E2E_FIRMWARE: uefi
E2E_TAP_IFACE: dne2e0
run: |
debian_iso=$(find images -maxdepth 1 -type f -name 'Dappnode-debian-*-amd64-netinst.iso' -print -quit)
test -n "${debian_iso}"
bash test/e2e_debian_iso.sh "${debian_iso}"

- name: Make network logs readable
if: always()
run: sudo chmod -R a+rX test-output || true

- name: Upload installation logs
if: always()
uses: actions/upload-artifact@v4
with:
name: debian-unattended-usb-installation-logs
path: test-output/debian-e2e/
if-no-files-found: ignore
retention-days: 7
34 changes: 0 additions & 34 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,37 +30,3 @@ jobs:
- name: Uninstall DAppNode
run: |
sudo /bin/bash ./scripts/dappnode_uninstall.sh y

iso:
name: test Debian and Ubuntu ISO
runs-on: ubuntu-latest

steps:
- name: Checkout
uses: actions/checkout@v6

# Create Debian ISO
- name: create Debian ISO
run: |
export BASE_OS=debian
export UNATTENDED=true
docker compose up --build
ls images/

# Verify Debian ISO creation
- name: verify Debian ISO
run: |
ls -lrt images/Dappnode-debian-*.iso

# Create Ubuntu ISO
- name: create Ubuntu ISO
run: |
export BASE_OS=ubuntu
export UNATTENDED=true
docker compose up --build
ls images/

# Verify Ubuntu ISO creation
- name: verify Ubuntu ISO
run: |
ls -lrt images/Dappnode-ubuntu-*.iso
77 changes: 77 additions & 0 deletions .github/workflows/ubuntu-iso-e2e.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
# Builds the unattended Ubuntu ISO and installs it from UEFI USB media in QEMU.
# It completes the required reboots and verifies the installed DAppNode system.
name: Ubuntu unattended USB ISO end-to-end

on:
workflow_dispatch:
pull_request:
# Weekly run against master to catch breakage from upstream package changes.
schedule:
- cron: "0 7 * * 1"
timezone: "Europe/Madrid"

permissions:
contents: read

concurrency:
group: ubuntu-iso-e2e-${{ github.ref }}
cancel-in-progress: true

jobs:
install:
name: Install Ubuntu unattended ISO via UEFI USB
runs-on: ubuntu-latest
timeout-minutes: 90

steps:
- name: Checkout
uses: actions/checkout@v6

- name: Build Ubuntu unattended ISO
run: |
export BASE_OS=ubuntu
export UNATTENDED=true
# Retry so a transient mirror outage does not fail the whole E2E run.
for attempt in 1 2 3; do
docker compose up --build --abort-on-container-exit --exit-code-from dappnode_installer && break
[ "${attempt}" -lt 3 ] || exit 1
echo "::warning::ISO build attempt ${attempt} failed; retrying in 30s"
sleep 30
done
ls -lrt images/Dappnode-ubuntu-*.iso

- name: Install QEMU test dependencies
run: |
sudo apt-get update
sudo apt-get install -y --no-install-recommends qemu-system-x86 qemu-utils ovmf socat sshpass dnsmasq-base
if [ -e /dev/kvm ]; then
sudo chmod a+rw /dev/kvm
fi

- name: Create the guest network
run: |
mkdir -p test-output/ubuntu-e2e
sudo E2E_NETWORK_STATE_DIR="${PWD}/test-output/ubuntu-e2e/network" bash test/e2e_network.sh up

- name: Complete Ubuntu unattended UEFI USB installation
env:
E2E_BOOT_MODE: usb
E2E_FIRMWARE: uefi
E2E_TAP_IFACE: dne2e0
run: |
ubuntu_iso=$(find images -maxdepth 1 -type f -name 'Dappnode-ubuntu-*-live-server-amd64.iso' -print -quit)
test -n "${ubuntu_iso}"
bash test/e2e_ubuntu_iso.sh "${ubuntu_iso}"

- name: Make network logs readable
if: always()
run: sudo chmod -R a+rX test-output || true

- name: Upload installation logs
if: always()
uses: actions/upload-artifact@v4
with:
name: ubuntu-unattended-usb-installation-logs
path: test-output/ubuntu-e2e/
if-no-files-found: ignore
retention-days: 7
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
docs/_build
images
images
test-output/
31 changes: 31 additions & 0 deletions test/e2e_debian_iso.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#!/bin/bash
# Runs the generated unattended Debian ISO through the complete UEFI USB test.
# It adds Debian release and package-alignment checks to the shared harness.
set -Eeuo pipefail

SCRIPT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
REPO_ROOT=$(cd "${SCRIPT_DIR}/.." && pwd)
GENERATOR="${REPO_ROOT}/iso/scripts/generate_dappnode_iso_debian.sh"
PRESEED="${REPO_ROOT}/iso/preseeds/preseed_unattended.cfg"

base_iso_name=$(sed -n 's/^BASE_ISO_NAME="\{0,1\}\([^"[:space:]]*\)"\{0,1\}$/\1/p' "${GENERATOR}")
if [[ ! "${base_iso_name}" =~ ^debian-([0-9]+)\. ]]; then
echo "[ERROR] Could not determine the Debian release from BASE_ISO_NAME=${base_iso_name}"
exit 1
fi
debian_major_version=${BASH_REMATCH[1]}

# The installed system must track the suite the preseed configures for APT.
debian_suite=$(sed -n 's|^d-i apt-setup/local0/repository string http://deb\.debian\.org/debian/ \([a-z]*\) .*|\1|p' "${PRESEED}")
if [ -z "${debian_suite}" ]; then
echo "[ERROR] Could not determine the Debian suite from ${PRESEED}"
exit 1
fi

E2E_DISTRO="debian"
E2E_EXPECTED_ID="debian"
E2E_EXPECTED_VERSION="${debian_major_version}"
E2E_EXPECTED_CODENAME="${debian_suite}"

source "${SCRIPT_DIR}/e2e_iso_install.sh"
run_e2e_iso_install "$@"
Loading
Loading