diff --git a/.gitea/workflows/build-image.yaml b/.gitea/workflows/build-image.yaml index 2cf3925..760304f 100644 --- a/.gitea/workflows/build-image.yaml +++ b/.gitea/workflows/build-image.yaml @@ -42,8 +42,8 @@ jobs: runs-on: fedora strategy: fail-fast: false - # One image at a time: each build takes loop devices, RAM and tens of GiB - max-parallel: 1 + # NB: Gitea runs every matrix entry as its own task, so `max-parallel` + # does not serialize them; build-image.sh takes a host-wide flock instead. matrix: include: - edition: phyllomeos diff --git a/build-image.sh b/build-image.sh index e37ad67..34d574c 100755 --- a/build-image.sh +++ b/build-image.sh @@ -175,8 +175,34 @@ fi resultdir="$(mktemp -u "${TMPDIR:-/tmp}/lmc-result.XXXXXX")" +# Only one livemedia-creator run per host at a time. It and anaconda use +# host-global resources (/mnt/sysroot, /mnt/sysimage, loop and device-mapper +# devices), so concurrent builds corrupt each other -- e.g. bootctl failing with +# "Couldn't find EFI system partition" when the CI matrix started both editions +# at once on a shared runner (Gitea expands each matrix entry into its own +# task, so `max-parallel` does not serialize them). A host-wide flock does. +# Under the lock, first clear mounts/devices a previously failed build left +# behind, which would otherwise poison this one. +LOCK=/run/lock/phyllomeos-build-image.lock echo "Building disk image for '$dish' (target release $releasever)..." -sudo livemedia-creator --ks "$disk_ks" --no-virt --resultdir "$resultdir" \ +echo "Waiting for the host build lock ($LOCK) if another build is running..." +sudo flock "$LOCK" env DISH="$dish" bash -c ' + for mnt in /mnt/sysimage /mnt/sysroot; do + if findmnt -rn "$mnt" >/dev/null 2>&1; then + echo "Cleaning stale mount $mnt from a failed build" + umount -R "$mnt" || true + fi + done + for dm in $(dmsetup ls 2>/dev/null | awk -v d="$DISH" "index(\$1, d) == 1 {print \$1}" | sort -r); do + echo "Removing stale device-mapper device $dm" + dmsetup remove --retry "$dm" || true + done + for lo in $(losetup -a | awk -F: "/lmc-result\\./ {print \$1}"); do + echo "Detaching stale loop device $lo" + losetup -d "$lo" || true + done + exec livemedia-creator "$@" +' _ --ks "$disk_ks" --no-virt --resultdir "$resultdir" \ --make-disk --image-name "${dish}.img" --releasever "$releasever" # livemedia-creator's exact output filename depends on the installed lorax