joininbox/ci/amd64/test.amd64-image-bats.sh
openoms 16fc83f47d
Some checks are pending
amd64-image-build / amd64-image-build (push) Waiting to run
arm64-rpi-image-build / arm64-rpi-image-build (push) Waiting to run
Test Shellcheck / Run Shellcheck (push) Waiting to run
chore: migrate the watch-only Bitcoin Core wallet to use descriptors (#177)
* chore: update wallet creation to use watch-only-descriptor-wallet

* remove duplicate version check

* fix: update release URL in install script and correct typo in wallet import message

* ci: test amd64 image descriptor wallet migration with Bats

* ci: boot amd64 image tests with OVMF pflash

* fix: gate descriptor wallet migration on Bitcoin Core v30

Detect the connected Bitcoin Core version over RPC before migrating.
Keep wallet.dat for v29.x or when the version cannot be determined.

Add regression coverage for both migration and compatibility paths.

* ci: make amd64 image tests independent of guest apt

Inject a pinned bats-core checkout into the temporary VM instead of
installing Bats through the guest package repositories.

Remove the duplicate pull request trigger and simplify artifact lookup.

* ci: harden image build run

* docs(FAQ): how automatic migration works
2026-08-13 11:57:42 +02:00

138 lines
3.9 KiB
Bash
Executable file

#!/usr/bin/env bash
set -euo pipefail
image="${1:-${GITHUB_WORKSPACE:-$(pwd)}/ci/amd64/builds/joininbox-amd64-debian-qemu/joininbox-amd64-debian.qcow2}"
ssh_port="${SSH_PORT:-2222}"
ssh_password="${SSH_PASSWORD:-joininbox}"
qemu_pid_file="${RUNNER_TEMP:-/tmp}/joininbox-qemu.pid"
bats_core_dir="${BATS_CORE_DIR:-${GITHUB_WORKSPACE:-$(pwd)}/.bats-core}"
if [ ! -f "${image}" ]; then
echo "Missing image: ${image}" >&2
exit 1
fi
if [ ! -x "${bats_core_dir}/bin/bats" ]; then
echo "Missing bats-core checkout: ${bats_core_dir}" >&2
exit 1
fi
sudo apt-get update
sudo apt-get install -y ovmf qemu-system-x86 sshpass
ssh_opts=(
-o StrictHostKeyChecking=no
-o UserKnownHostsFile=/dev/null
-o ConnectTimeout=5
-p "${ssh_port}"
)
ovmf_code="${OVMF_CODE:-${OVMF_BIOS:-}}"
ovmf_vars_template="${OVMF_VARS:-}"
ovmf_vars="${RUNNER_TEMP:-/tmp}/joininbox-ovmf-vars.fd"
qemu_firmware_args=()
if [ -z "${ovmf_code}" ]; then
for candidate in \
/usr/share/OVMF/OVMF_CODE_4M.fd \
/usr/share/OVMF/OVMF_CODE_4M.secboot.fd \
/usr/share/OVMF/OVMF_CODE_4M.ms.fd \
/usr/share/OVMF/OVMF_CODE.fd \
/usr/share/OVMF/OVMF.fd \
/usr/share/ovmf/OVMF_CODE_4M.fd \
/usr/share/ovmf/OVMF_CODE_4M.secboot.fd \
/usr/share/ovmf/OVMF_CODE_4M.ms.fd \
/usr/share/ovmf/OVMF_CODE.fd \
/usr/share/ovmf/OVMF.fd \
OVMF.fd; do
if [ -f "${candidate}" ]; then
ovmf_code="${candidate}"
break
fi
done
fi
if [ -z "${ovmf_code}" ] || [ ! -f "${ovmf_code}" ]; then
echo "No OVMF firmware found. Set OVMF_CODE or OVMF_BIOS to the firmware path." >&2
find /usr/share/OVMF /usr/share/ovmf -maxdepth 1 -type f -name '*.fd' -print 2>/dev/null || true
exit 1
fi
case "${ovmf_code##*/}" in
*CODE*)
if [ -z "${ovmf_vars_template}" ]; then
for candidate in \
"${ovmf_code/CODE/VARS}" \
/usr/share/OVMF/OVMF_VARS_4M.fd \
/usr/share/OVMF/OVMF_VARS.fd \
/usr/share/ovmf/OVMF_VARS_4M.fd \
/usr/share/ovmf/OVMF_VARS.fd; do
if [ -f "${candidate}" ]; then
ovmf_vars_template="${candidate}"
break
fi
done
fi
if [ -z "${ovmf_vars_template}" ] || [ ! -f "${ovmf_vars_template}" ]; then
echo "No OVMF VARS template found for ${ovmf_code}. Set OVMF_VARS to the template path." >&2
find /usr/share/OVMF /usr/share/ovmf -maxdepth 1 -type f -name '*.fd' -print 2>/dev/null || true
exit 1
fi
cp "${ovmf_vars_template}" "${ovmf_vars}"
qemu_firmware_args=(
-drive "if=pflash,format=raw,readonly=on,file=${ovmf_code}"
-drive "if=pflash,format=raw,file=${ovmf_vars}"
)
;;
*)
qemu_firmware_args=(-bios "${ovmf_code}")
;;
esac
cleanup() {
if [ -f "${qemu_pid_file}" ]; then
qemu_pid="$(cat "${qemu_pid_file}")"
if kill -0 "${qemu_pid}" 2>/dev/null; then
kill "${qemu_pid}" 2>/dev/null || true
timeout 30s tail --pid="${qemu_pid}" -f /dev/null 2>/dev/null ||
kill -9 "${qemu_pid}" 2>/dev/null ||
true
fi
fi
}
trap cleanup EXIT
rm -f "${qemu_pid_file}"
qemu-system-x86_64 \
-m 2048 \
-smp 2 \
"${qemu_firmware_args[@]}" \
-drive "file=${image},format=qcow2" \
-netdev "user,id=net0,hostfwd=tcp:127.0.0.1:${ssh_port}-:22" \
-device e1000,netdev=net0 \
-display none \
-snapshot \
-pidfile "${qemu_pid_file}" \
-daemonize
echo "Waiting for SSH in the booted image"
for attempt in {1..120}; do
if sshpass -p "${ssh_password}" ssh "${ssh_opts[@]}" joinmarket@127.0.0.1 "true" 2>/dev/null; then
break
fi
if [ "${attempt}" -eq 120 ]; then
echo "Timed out waiting for SSH" >&2
exit 1
fi
sleep 5
done
tar -C "${bats_core_dir}" -cf - . |
sshpass -p "${ssh_password}" ssh "${ssh_opts[@]}" joinmarket@127.0.0.1 \
"mkdir -p /tmp/bats-core && tar -C /tmp/bats-core -xf -"
sshpass -p "${ssh_password}" ssh "${ssh_opts[@]}" joinmarket@127.0.0.1 \
"PATH=/tmp/bats-core/bin:\$PATH /home/joinmarket/joininbox/test/run-bats-local.sh"