fix: complete ARM64 RPi build pipeline
Some checks failed
CI / Go Tests (push) Has been cancelled
CI / Build Go Binaries (amd64, linux, linux-amd64) (push) Has been cancelled
CI / Build Go Binaries (arm64, linux, linux-arm64) (push) Has been cancelled
CI / Shellcheck (push) Has been cancelled
Release / Test (push) Has been cancelled
Release / Build Binaries (amd64, linux, linux-amd64) (push) Has been cancelled
Release / Build Binaries (arm64, linux, linux-arm64) (push) Has been cancelled
Release / Build ISO (amd64) (push) Has been cancelled
Release / Create Release (push) Has been cancelled

- fetch-components.sh: download ARM64 KubeSolo binary (kubesolo-arm64)
- inject-kubesolo.sh: use arch-specific binaries for KubeSolo, cloud-init,
  and update agent; detect KVER from custom kernel when rootfs has none;
  cross-arch module resolution via find fallback when modprobe fails
- create-rpi-image.sh: kpartx support for Docker container builds
- Makefile: rootfs-arm64 depends on build-cross, includes pack-initramfs

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-12 17:20:04 -06:00
parent 09dcea84ef
commit ba4812f637
4 changed files with 130 additions and 22 deletions

View File

@@ -25,7 +25,11 @@ if [ ! -d "$ROOTFS" ]; then
exit 1
fi
KUBESOLO_BIN="$CACHE_DIR/kubesolo"
if [ "$INJECT_ARCH" = "arm64" ]; then
KUBESOLO_BIN="$CACHE_DIR/kubesolo-arm64"
else
KUBESOLO_BIN="$CACHE_DIR/kubesolo"
fi
if [ ! -f "$KUBESOLO_BIN" ]; then
echo "ERROR: KubeSolo binary not found: $KUBESOLO_BIN"
echo "See fetch-components.sh output for instructions."
@@ -78,23 +82,27 @@ for lib in network.sh health.sh; do
done
# Cloud-init binary (Go, built separately)
CLOUDINIT_BIN="$CACHE_DIR/kubesolo-cloudinit"
# Try arch-specific binary first, then fall back to generic
CLOUDINIT_BIN="$CACHE_DIR/kubesolo-cloudinit-linux-$INJECT_ARCH"
[ ! -f "$CLOUDINIT_BIN" ] && CLOUDINIT_BIN="$CACHE_DIR/kubesolo-cloudinit"
if [ -f "$CLOUDINIT_BIN" ]; then
cp "$CLOUDINIT_BIN" "$ROOTFS/usr/lib/kubesolo-os/kubesolo-cloudinit"
chmod +x "$ROOTFS/usr/lib/kubesolo-os/kubesolo-cloudinit"
echo " Installed cloud-init binary ($(du -h "$CLOUDINIT_BIN" | cut -f1))"
else
echo " WARN: Cloud-init binary not found (run 'make build-cloudinit' to build)"
echo " WARN: Cloud-init binary not found (run 'make build-cloudinit' or 'make build-cross' to build)"
fi
# Update agent binary (Go, built separately)
UPDATE_BIN="$CACHE_DIR/kubesolo-update"
# Try arch-specific binary first, then fall back to generic
UPDATE_BIN="$CACHE_DIR/kubesolo-update-linux-$INJECT_ARCH"
[ ! -f "$UPDATE_BIN" ] && UPDATE_BIN="$CACHE_DIR/kubesolo-update"
if [ -f "$UPDATE_BIN" ]; then
cp "$UPDATE_BIN" "$ROOTFS/usr/lib/kubesolo-os/kubesolo-update"
chmod +x "$ROOTFS/usr/lib/kubesolo-os/kubesolo-update"
echo " Installed update agent ($(du -h "$UPDATE_BIN" | cut -f1))"
else
echo " WARN: Update agent not found (run 'make build-update-agent' to build)"
echo " WARN: Update agent not found (run 'make build-update-agent' or 'make build-cross' to build)"
fi
# --- 3. Custom kernel or TCZ kernel modules ---
@@ -115,8 +123,16 @@ for d in "$ROOTFS"/lib/modules/*/; do
[ -d "$d" ] && KVER="$(basename "$d")" && break
done
# Fallback: detect from custom kernel modules directory
if [ -z "$KVER" ] && [ -d "$CUSTOM_MODULES/lib/modules" ]; then
for d in "$CUSTOM_MODULES"/lib/modules/*/; do
[ -d "$d" ] && KVER="$(basename "$d")" && break
done
echo " Detected kernel version from custom kernel: $KVER"
fi
if [ -z "$KVER" ]; then
echo " WARN: Could not detect kernel version from rootfs"
echo " WARN: Could not detect kernel version from rootfs or custom kernel"
fi
echo " Kernel version: $KVER"
@@ -145,24 +161,49 @@ if [ -f "$CUSTOM_VMLINUZ" ] && [ -d "$CUSTOM_MODULES/lib/modules/$KVER" ]; then
[ -f "$CUSTOM_MOD_DIR/$f" ] && cp "$CUSTOM_MOD_DIR/$f" "$ROOTFS/lib/modules/$KVER/"
done
# Use modprobe --show-depends to resolve each module + its transitive deps
# Resolve and install modules from modules.list + transitive deps
if [ "$INJECT_ARCH" = "arm64" ]; then
MODULES_LIST="$PROJECT_ROOT/build/config/modules-arm64.list"
else
MODULES_LIST="$PROJECT_ROOT/build/config/modules.list"
fi
NEEDED_MODS=$(mktemp)
# Try modprobe first (works for same-arch builds)
MODPROBE_WORKS=true
FIRST_MOD=$(grep -v '^#' "$MODULES_LIST" | grep -v '^$' | head -1 | xargs)
if ! modprobe -S "$KVER" -d "$CUSTOM_MODULES" --show-depends "$FIRST_MOD" >/dev/null 2>&1; then
MODPROBE_WORKS=false
echo " modprobe cannot resolve modules (cross-arch build) — using find fallback"
fi
while IFS= read -r mod; do
# Skip comments and blank lines
case "$mod" in \#*|"") continue ;; esac
mod=$(echo "$mod" | xargs) # trim whitespace
[ -z "$mod" ] && continue
# modprobe -S <ver> -d <root> --show-depends <module> lists all deps in load order
# Output format: "insmod /path/to/module.ko" — extract path with awk
modprobe -S "$KVER" -d "$CUSTOM_MODULES" --show-depends "$mod" 2>/dev/null \
| awk '/^insmod/{print $2}' >> "$NEEDED_MODS" \
|| echo " WARN: modprobe could not resolve: $mod"
if [ "$MODPROBE_WORKS" = true ]; then
# modprobe -S <ver> -d <root> --show-depends <module> lists all deps in load order
modprobe -S "$KVER" -d "$CUSTOM_MODULES" --show-depends "$mod" 2>/dev/null \
| awk '/^insmod/{print $2}' >> "$NEEDED_MODS" \
|| echo " WARN: modprobe could not resolve: $mod"
else
# Cross-arch fallback: find module by name in kernel tree
found=$(find "$CUSTOM_MOD_DIR/kernel" -name "${mod}.ko" -o -name "${mod}.ko.xz" -o -name "${mod}.ko.gz" -o -name "${mod}.ko.zst" 2>/dev/null | head -1)
if [ -n "$found" ]; then
echo "$found" >> "$NEEDED_MODS"
else
# Try replacing hyphens with underscores and vice versa
mod_alt=$(echo "$mod" | tr '-' '_')
found=$(find "$CUSTOM_MOD_DIR/kernel" -name "${mod_alt}.ko" -o -name "${mod_alt}.ko.xz" -o -name "${mod_alt}.ko.gz" -o -name "${mod_alt}.ko.zst" 2>/dev/null | head -1)
if [ -n "$found" ]; then
echo "$found" >> "$NEEDED_MODS"
else
echo " WARN: could not find module: $mod"
fi
fi
fi
done < "$MODULES_LIST"
# Deduplicate and copy each needed module