M patches/README.md => patches/README.md +20 -0
@@ 31,3 31,23 @@ git apply --check ../patches/core-go-checksum.patch
```
If `git apply --check` fails after a `sourcehut-refresh`, upstream has changed that file โ re-derive the patch against the new context and update the copy in `~/data/home/phoebe-lab/srht/patches/` first, then re-import here.
+
+### `builds-images-ubuntu-genimg.patch`
+
+**Repo:** `builds.sr.ht` ยท **File:** `images/ubuntu/genimg`
+
+Two independent bugs in the apk-shipped recipe (`builds.sr.ht-images` 0.103.12-r0; the git-tag at 0.103.12 has slight drift from the apk, see the patch header):
+
+1. **NBD settle race.** After `qemu-nbd --connect=/dev/nbd0` the kernel hasn't updated the block device's reported size yet, and the immediate `dd if=mbr.bin of=/dev/nbd0` fails with `No space left on device`. `debian/genimg` already handles this with a `partprobe` loop; ubuntu's variant is missing it. The patch is a verbatim copy of the debian fix.
+2. **Host vs chroot chown.** The recipe runs `chown build:build /mnt/home/build/.gitconfig` on the *host* near the end โ but `build` is a chroot user, not a host user. On any builder that doesn't happen to have a same-UID host `build` user, ~5 min of debootstrap work is thrown away by the failing chown. Patch routes it via `run_root chown ... /home/build/.gitconfig`, matching the rest of the script.
+
+**Status.** Applied on `work.lab.local` (the out-of-band image builder VM) at 2026-05-19; **not upstreamed yet**. Should file with sr.ht-dev when a moment opens up โ both are obvious bugs the upstream maintainers will likely take.
+
+**Verify it still applies cleanly:**
+
+```bash
+cd ~/data/home/sourcehut/builds.sr.ht
+git apply --check ../patches/builds-images-ubuntu-genimg.patch
+```
+
+Note: the patch is written against the apk-shipped baseline. `git apply --check` may complain about line offsets against the upstream submodule; the underlying logic is what matters. After a `sourcehut-refresh`, eyeball whether the two hunks still describe the same issue before trusting the patch verbatim.
A patches/builds-images-ubuntu-genimg.patch => patches/builds-images-ubuntu-genimg.patch +43 -0
@@ 0,0 1,43 @@
+From: phoebe-lab local fix
+Subject: [PATCH] builds.sr.ht-images ubuntu/genimg: fix nbd settle race + host chown
+
+Two independent fixes for the upstream `images/ubuntu/genimg` script as shipped
+in the `builds.sr.ht-images` Alpine package (last verified against 0.103.12-r0).
+Both bugs make image generation fail on any host that doesn't happen to satisfy
+their hidden assumptions.
+
+1) After `qemu-nbd --connect`, the kernel hasn't picked up the device size yet,
+ so the immediate `dd if=mbr.bin of=/dev/nbd0` fails with "No space left on
+ device". The sibling `debian/genimg` already handles this with a partprobe
+ loop; ubuntu's variant is missing it. Verbatim copy of the debian fix.
+
+2) `chown build:build /mnt/home/build/.gitconfig` runs on the *host*, not in
+ the chroot. There's no host user named `build` on a typical Arch/Debian
+ builder VM, so the script aborts at the very end after 5+ min of debootstrap
+ work. Routing the chown through `run_root` (the existing chroot helper used
+ everywhere else in the file) puts it where the user actually exists.
+
+Apply when refreshing the apk recipe tree on the image-builder host:
+
+ cd /var/lib/images
+ patch -p0 < builds-images-ubuntu-genimg.patch
+
+--- a/ubuntu/genimg
++++ b/ubuntu/genimg
+@@ -35,6 +35,7 @@
+ qemu-img create -f qcow2 $arch/root.img.qcow2 32G
+ modprobe nbd max_part=16
+ qemu-nbd --connect=/dev/nbd0 $arch/root.img.qcow2
++for i in 1 2 3 4 5; do sleep 0.$i; partprobe /dev/nbd0 && break; done
+ trap cleanup EXIT
+
+ if [ "$arch" = "amd64" ]
+@@ -163,7 +164,7 @@
+ name = builds.sr.ht
+ email = builds@sr.ht
+ EOF
+-chown build:build /mnt/home/build/.gitconfig
++run_root chown build:build /home/build/.gitconfig
+
+ if [ "$arch" != "amd64" ]
+ then