feat: add build report and first-boot diagnostics
Some checks failed
Build Archipelago ISO / build-iso (push) Has been cancelled
Some checks failed
Build Archipelago ISO / build-iso (push) Has been cancelled
CI build report: checks rootfs contents (nginx, SSL, keyboard, kiosk, lid config, backend, frontend) and ISO contents after build. Reports in the Actions log so build issues are immediately visible. First-boot diagnostics: one-shot systemd service runs 30s after first boot, logs service status, nginx test, SSL certs, LUKS, podman, kiosk, console-setup, disk, network, and journal errors to /var/log/archipelago-first-boot-diag.log. Only runs once (ConditionPathExists). SSH in and cat the log to debug any fresh install issues. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -47,11 +47,65 @@ jobs:
|
||||
ISO=$(ls image-recipe/results/archipelago-installer-unbundled-*.iso 2>/dev/null | head -1)
|
||||
if [ -n "$ISO" ]; then
|
||||
DATE=$(date +%Y%m%d-%H%M)
|
||||
sudo cp "$ISO" "/var/lib/archipelago/filebrowser/Builds/archipelago-unbundled-${DATE}.iso"
|
||||
sudo chown 1000:1000 "/var/lib/archipelago/filebrowser/Builds/archipelago-unbundled-${DATE}.iso"
|
||||
DEST="/var/lib/archipelago/filebrowser/Builds/archipelago-unbundled-${DATE}.iso"
|
||||
sudo cp "$ISO" "$DEST"
|
||||
sudo chown 1000:1000 "$DEST"
|
||||
echo "ISO: archipelago-unbundled-${DATE}.iso"
|
||||
echo "Size: $(du -h "$DEST" | cut -f1)"
|
||||
echo "SHA256: $(sha256sum "$DEST" | cut -d' ' -f1)"
|
||||
fi
|
||||
|
||||
- name: Build report
|
||||
if: always()
|
||||
run: |
|
||||
echo "══════════════════════════════════════════"
|
||||
echo "BUILD REPORT"
|
||||
echo "══════════════════════════════════════════"
|
||||
echo "Commit: $(git rev-parse --short HEAD) ($(git log -1 --format=%s))"
|
||||
echo "Branch: ${GITHUB_REF_NAME:-unknown}"
|
||||
echo "Date: $(date -u '+%Y-%m-%d %H:%M:%S UTC')"
|
||||
echo "Runner: $(hostname)"
|
||||
echo ""
|
||||
echo "── Artifacts ──"
|
||||
ls -lh image-recipe/results/*.iso 2>/dev/null || echo " No ISO produced"
|
||||
ls -lh /var/lib/archipelago/filebrowser/Builds/archipelago-unbundled-*.iso 2>/dev/null | tail -3
|
||||
echo ""
|
||||
echo "── Rootfs contents check ──"
|
||||
ROOTFS=$(ls image-recipe/build/auto-installer/rootfs.tar 2>/dev/null)
|
||||
if [ -n "$ROOTFS" ]; then
|
||||
echo " rootfs.tar: $(du -h "$ROOTFS" | cut -f1)"
|
||||
echo " nginx config: $(tar tf "$ROOTFS" ./etc/nginx/sites-available/archipelago 2>/dev/null && echo 'PRESENT' || echo 'MISSING')"
|
||||
echo " SSL cert: $(tar tf "$ROOTFS" ./etc/archipelago/ssl/archipelago.crt 2>/dev/null && echo 'PRESENT' || echo 'MISSING')"
|
||||
echo " keyboard config: $(tar tf "$ROOTFS" ./etc/default/keyboard 2>/dev/null && echo 'PRESENT' || echo 'MISSING')"
|
||||
echo " console-setup: $(tar tf "$ROOTFS" ./etc/default/console-setup 2>/dev/null && echo 'PRESENT' || echo 'MISSING')"
|
||||
echo " kiosk launcher: $(tar tf "$ROOTFS" ./usr/local/bin/archipelago-kiosk-launcher 2>/dev/null && echo 'PRESENT' || echo 'MISSING')"
|
||||
echo " logind lid: $(tar tf "$ROOTFS" ./etc/systemd/logind.conf.d/lid-ignore.conf 2>/dev/null && echo 'PRESENT' || echo 'MISSING')"
|
||||
echo " backend binary: $(tar tf "$ROOTFS" ./usr/local/bin/archipelago 2>/dev/null && echo 'PRESENT' || echo 'MISSING')"
|
||||
echo " web-ui index: $(tar tf "$ROOTFS" ./opt/archipelago/web-ui/index.html 2>/dev/null && echo 'PRESENT' || echo 'MISSING')"
|
||||
else
|
||||
echo " rootfs.tar not found in workspace"
|
||||
fi
|
||||
echo ""
|
||||
echo "── ISO contents check ──"
|
||||
ISO=$(ls image-recipe/results/archipelago-installer-unbundled-*.iso 2>/dev/null | head -1)
|
||||
if [ -n "$ISO" ]; then
|
||||
echo " ISO size: $(du -h "$ISO" | cut -f1)"
|
||||
# Check installer script is present
|
||||
ISO_MOUNT=$(mktemp -d)
|
||||
if sudo mount -o loop,ro "$ISO" "$ISO_MOUNT" 2>/dev/null; then
|
||||
echo " auto-install.sh: $([ -f "$ISO_MOUNT/archipelago/auto-install.sh" ] && echo 'PRESENT' || echo 'MISSING')"
|
||||
echo " rootfs.tar: $([ -f "$ISO_MOUNT/archipelago/rootfs.tar" ] && echo "PRESENT ($(du -h "$ISO_MOUNT/archipelago/rootfs.tar" | cut -f1))" || echo 'MISSING')"
|
||||
echo " backend bin: $([ -f "$ISO_MOUNT/archipelago/bin/archipelago" ] && echo "PRESENT ($(du -h "$ISO_MOUNT/archipelago/bin/archipelago" | cut -f1))" || echo 'MISSING')"
|
||||
echo " frontend: $([ -f "$ISO_MOUNT/archipelago/web-ui/index.html" ] && echo 'PRESENT' || echo 'MISSING')"
|
||||
echo " image-versions: $([ -f "$ISO_MOUNT/archipelago/scripts/image-versions.sh" ] && echo 'PRESENT' || echo 'MISSING')"
|
||||
sudo umount "$ISO_MOUNT" 2>/dev/null
|
||||
else
|
||||
echo " Could not mount ISO for inspection"
|
||||
fi
|
||||
rmdir "$ISO_MOUNT" 2>/dev/null
|
||||
fi
|
||||
echo "══════════════════════════════════════════"
|
||||
|
||||
- name: Fix workspace permissions
|
||||
if: always()
|
||||
run: sudo chown -R $(id -u):$(id -g) . 2>/dev/null || true
|
||||
|
||||
@@ -1040,6 +1040,10 @@ cat > "$ARCH_DIR/auto-install.sh" <<'INSTALLER_SCRIPT'
|
||||
|
||||
set -e
|
||||
|
||||
# Log everything to a file on the target disk (after mount) and to console
|
||||
INSTALL_LOG="/tmp/archipelago-install.log"
|
||||
exec > >(tee -a "$INSTALL_LOG") 2>&1
|
||||
|
||||
# Detect architecture at install time
|
||||
case "$(uname -m)" in
|
||||
x86_64|amd64)
|
||||
@@ -1853,6 +1857,92 @@ chroot /mnt/target systemctl enable archipelago-setup-tor.service 2>/dev/null ||
|
||||
chroot /mnt/target systemctl enable archipelago-first-boot-containers.service 2>/dev/null || true
|
||||
chroot /mnt/target systemctl enable archipelago-kiosk.service 2>/dev/null || true
|
||||
|
||||
# Install first-boot diagnostic script — runs once after first boot and logs system state
|
||||
cat > /mnt/target/opt/archipelago/scripts/first-boot-diag.sh <<'DIAGSCRIPT'
|
||||
#!/bin/bash
|
||||
LOG="/var/log/archipelago-first-boot-diag.log"
|
||||
exec > "$LOG" 2>&1
|
||||
echo "=== Archipelago First Boot Diagnostics ==="
|
||||
echo "Date: $(date -u)"
|
||||
echo "Hostname: $(hostname)"
|
||||
echo "Kernel: $(uname -r)"
|
||||
echo "IP: $(hostname -I 2>/dev/null | awk '{print $1}')"
|
||||
echo ""
|
||||
echo "=== Build Info ==="
|
||||
cat /opt/archipelago/build-info.txt 2>/dev/null || echo "No build-info.txt"
|
||||
echo ""
|
||||
echo "=== Services ==="
|
||||
for svc in nginx archipelago archipelago-kiosk archipelago-load-images archipelago-first-boot-containers; do
|
||||
STATUS=$(systemctl is-active "$svc" 2>/dev/null || echo "missing")
|
||||
ENABLED=$(systemctl is-enabled "$svc" 2>/dev/null || echo "missing")
|
||||
printf " %-45s active=%-10s enabled=%s\n" "$svc" "$STATUS" "$ENABLED"
|
||||
done
|
||||
echo ""
|
||||
echo "=== Nginx Test ==="
|
||||
nginx -t 2>&1
|
||||
echo ""
|
||||
echo "=== SSL Cert ==="
|
||||
ls -la /etc/archipelago/ssl/ 2>/dev/null || echo " No SSL directory"
|
||||
echo ""
|
||||
echo "=== EFI Boot ==="
|
||||
ls -la /boot/efi/EFI/BOOT/ 2>/dev/null || echo " No EFI/BOOT directory"
|
||||
echo ""
|
||||
echo "=== LUKS ==="
|
||||
ls -la /dev/mapper/archipelago-data 2>/dev/null && echo " LUKS volume open" || echo " No LUKS volume"
|
||||
cat /etc/crypttab 2>/dev/null
|
||||
echo ""
|
||||
echo "=== Podman ==="
|
||||
podman --version 2>/dev/null || echo " podman not found"
|
||||
podman ps -a --format "{{.Names}} {{.Status}}" 2>/dev/null | head -20
|
||||
echo ""
|
||||
echo "=== Kiosk ==="
|
||||
systemctl status archipelago-kiosk --no-pager 2>&1 | head -10
|
||||
echo ""
|
||||
echo "=== Console Setup ==="
|
||||
systemctl status console-setup --no-pager 2>&1 | head -5
|
||||
cat /etc/default/keyboard 2>/dev/null || echo " No keyboard config"
|
||||
echo ""
|
||||
echo "=== Logind (Lid) ==="
|
||||
cat /etc/systemd/logind.conf.d/lid-ignore.conf 2>/dev/null || echo " No lid config"
|
||||
echo ""
|
||||
echo "=== Disk ==="
|
||||
df -h / /boot/efi /var/lib/archipelago 2>/dev/null
|
||||
echo ""
|
||||
echo "=== Network ==="
|
||||
ip addr show | grep -E "inet |link/" | head -10
|
||||
echo ""
|
||||
echo "=== Journal Errors (last boot) ==="
|
||||
journalctl -b -p err --no-pager 2>/dev/null | tail -30
|
||||
echo ""
|
||||
echo "=== Done ==="
|
||||
DIAGSCRIPT
|
||||
chmod +x /mnt/target/opt/archipelago/scripts/first-boot-diag.sh
|
||||
|
||||
# Systemd oneshot service for first-boot diagnostics
|
||||
cat > /mnt/target/etc/systemd/system/archipelago-diag.service <<'DIAGSVC'
|
||||
[Unit]
|
||||
Description=Archipelago First Boot Diagnostics
|
||||
After=multi-user.target archipelago.service nginx.service
|
||||
ConditionPathExists=!/var/log/archipelago-first-boot-diag.log
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
ExecStartPre=/bin/sleep 30
|
||||
ExecStart=/opt/archipelago/scripts/first-boot-diag.sh
|
||||
RemainAfterExit=yes
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
DIAGSVC
|
||||
chroot /mnt/target systemctl enable archipelago-diag.service 2>/dev/null || true
|
||||
|
||||
# Write build info into the installed system
|
||||
cat > /mnt/target/opt/archipelago/build-info.txt <<BUILDINFO
|
||||
commit=$(cd /tmp 2>/dev/null && git -C "$BOOT_MEDIA/../" rev-parse --short HEAD 2>/dev/null || echo "unknown")
|
||||
date=$(date -u '+%Y-%m-%d %H:%M:%S UTC')
|
||||
type=unbundled
|
||||
BUILDINFO
|
||||
|
||||
# Cleanup
|
||||
sync
|
||||
umount /mnt/target/run 2>/dev/null || true
|
||||
@@ -1919,6 +2009,9 @@ echo ""
|
||||
echo ""
|
||||
echo -e "${YELLOW} >>> REMOVE THE USB DRIVE NOW <<<${NC}"
|
||||
echo ""
|
||||
# Save install log to target disk for post-install debugging
|
||||
cp "$INSTALL_LOG" /mnt/target/var/log/archipelago-install.log 2>/dev/null || true
|
||||
|
||||
read -p "Press Enter to reboot (make sure USB is removed)..."
|
||||
|
||||
# Suppress all error output during cleanup and reboot
|
||||
|
||||
Reference in New Issue
Block a user