feat: add build report and first-boot diagnostics
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:
parent
e4b4519061
commit
102434c041
@ -47,11 +47,65 @@ jobs:
|
|||||||
ISO=$(ls image-recipe/results/archipelago-installer-unbundled-*.iso 2>/dev/null | head -1)
|
ISO=$(ls image-recipe/results/archipelago-installer-unbundled-*.iso 2>/dev/null | head -1)
|
||||||
if [ -n "$ISO" ]; then
|
if [ -n "$ISO" ]; then
|
||||||
DATE=$(date +%Y%m%d-%H%M)
|
DATE=$(date +%Y%m%d-%H%M)
|
||||||
sudo cp "$ISO" "/var/lib/archipelago/filebrowser/Builds/archipelago-unbundled-${DATE}.iso"
|
DEST="/var/lib/archipelago/filebrowser/Builds/archipelago-unbundled-${DATE}.iso"
|
||||||
sudo chown 1000:1000 "/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 "ISO: archipelago-unbundled-${DATE}.iso"
|
||||||
|
echo "Size: $(du -h "$DEST" | cut -f1)"
|
||||||
|
echo "SHA256: $(sha256sum "$DEST" | cut -d' ' -f1)"
|
||||||
fi
|
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
|
- name: Fix workspace permissions
|
||||||
if: always()
|
if: always()
|
||||||
run: sudo chown -R $(id -u):$(id -g) . 2>/dev/null || true
|
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
|
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
|
# Detect architecture at install time
|
||||||
case "$(uname -m)" in
|
case "$(uname -m)" in
|
||||||
x86_64|amd64)
|
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-first-boot-containers.service 2>/dev/null || true
|
||||||
chroot /mnt/target systemctl enable archipelago-kiosk.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
|
# Cleanup
|
||||||
sync
|
sync
|
||||||
umount /mnt/target/run 2>/dev/null || true
|
umount /mnt/target/run 2>/dev/null || true
|
||||||
@ -1919,6 +2009,9 @@ echo ""
|
|||||||
echo ""
|
echo ""
|
||||||
echo -e "${YELLOW} >>> REMOVE THE USB DRIVE NOW <<<${NC}"
|
echo -e "${YELLOW} >>> REMOVE THE USB DRIVE NOW <<<${NC}"
|
||||||
echo ""
|
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)..."
|
read -p "Press Enter to reboot (make sure USB is removed)..."
|
||||||
|
|
||||||
# Suppress all error output during cleanup and reboot
|
# Suppress all error output during cleanup and reboot
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user