Monorepo for Aesthetic.Computer aesthetic.computer
4
fork

Configure Feed

Select the types of activity you want to include in your feed.

build: generate UEFI ISO alongside vmlinuz for browser-based flashing

- docker-build.sh: Step 5 creates EFI-bootable ISO with config marker
that os.mjs can patch client-side with user creds
- upload-release.sh: uploads ISO to CDN alongside vmlinuz
- native-builder.mjs: extracts + uploads ISO from Docker container
- Dockerfile: add xorriso for ISO generation

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

+118 -13
+1 -1
fedac/native/Dockerfile.builder
··· 13 13 RUN dnf install -y --setopt=install_weak_deps=False \ 14 14 gcc make cpio lz4 bc perl flex bison diffutils \ 15 15 elfutils-libelf-devel openssl-devel \ 16 - curl jq git tar xz findutils pkgconf-pkg-config zstd \ 16 + curl jq git tar xz findutils pkgconf-pkg-config zstd xorriso \ 17 17 ca-certificates \ 18 18 alsa-lib-devel libdrm-devel flite-devel \ 19 19 ffmpeg-free-devel \
+65
fedac/native/docker-build.sh
··· 348 348 VMLINUZ_SIZE=$(stat -c%s "$BUILD/vmlinuz") 349 349 SHA=$(sha256sum "$BUILD/vmlinuz" | awk '{print $1}') 350 350 351 + # ══════════════════════════════════════════════ 352 + # Step 5: Generate UEFI-bootable ISO 353 + # ══════════════════════════════════════════════ 354 + log "Step 5: Building ISO..." 355 + ISO_DIR="$BUILD/iso-root" 356 + EFI_IMG="$BUILD/efi.img" 357 + ISO_OUT="$BUILD/ac-os.iso" 358 + 359 + rm -rf "$ISO_DIR" "$EFI_IMG" 360 + mkdir -p "$ISO_DIR/EFI/BOOT" 361 + 362 + # Copy kernel as UEFI boot binary 363 + cp "$BUILD/vmlinuz" "$ISO_DIR/EFI/BOOT/BOOTX64.EFI" 364 + 365 + # Create config.json with patchable marker (browser replaces this) 366 + CONFIG_MARKER='{"handle":"","piece":"notepat","sub":"","email":""}' 367 + CONFIG_PAD=4096 368 + printf "%-${CONFIG_PAD}s" "$CONFIG_MARKER" > "$ISO_DIR/config.json" 369 + 370 + # Create FAT32 EFI boot image 371 + EFI_SIZE_MB=$(( (VMLINUZ_SIZE + CONFIG_PAD + 1048576) / 1048576 + 4 )) 372 + dd if=/dev/zero of="$EFI_IMG" bs=1M count=$EFI_SIZE_MB 2>/dev/null 373 + mkfs.fat -F 32 "$EFI_IMG" >/dev/null 2>&1 374 + mmd -i "$EFI_IMG" ::EFI ::EFI/BOOT 2>/dev/null 375 + mcopy -i "$EFI_IMG" "$BUILD/vmlinuz" ::EFI/BOOT/BOOTX64.EFI 376 + mcopy -i "$EFI_IMG" "$ISO_DIR/config.json" ::config.json 377 + 378 + # Build ISO with EFI boot support 379 + if command -v xorriso &>/dev/null; then 380 + xorriso -as mkisofs \ 381 + -o "$ISO_OUT" \ 382 + -e efi.img -no-emul-boot \ 383 + -isohybrid-gpt-basdat \ 384 + "$ISO_DIR" 2>/dev/null 385 + # Embed EFI image into ISO for hybrid boot 386 + cp "$EFI_IMG" "$ISO_DIR/efi.img" 387 + xorriso -as mkisofs \ 388 + -o "$ISO_OUT" \ 389 + -e efi.img -no-emul-boot \ 390 + "$ISO_DIR" 2>/dev/null 391 + elif command -v genisoimage &>/dev/null; then 392 + genisoimage -o "$ISO_OUT" \ 393 + -efi-boot efi.img \ 394 + -no-emul-boot \ 395 + "$ISO_DIR" 2>/dev/null 396 + else 397 + # Fallback: raw disk image (dd-able) 398 + log " No ISO tools — creating raw disk image" 399 + cp "$EFI_IMG" "$ISO_OUT" 400 + fi 401 + 402 + if [ -f "$ISO_OUT" ]; then 403 + ISO_SIZE=$(stat -c%s "$ISO_OUT") 404 + ISO_SHA=$(sha256sum "$ISO_OUT" | awk '{print $1}') 405 + cp "$ISO_OUT" "$OUT/ac-os.iso" 2>/dev/null || true 406 + log " ISO: $((ISO_SIZE / 1048576))MB (sha256: ${ISO_SHA:0:16}...)" 407 + else 408 + log " ISO generation failed — vmlinuz still available" 409 + fi 410 + 351 411 log "" 352 412 log "═══════════════════════════════════════════" 353 413 log " Build complete: $BUILD_NAME" 354 414 log " Kernel: $((VMLINUZ_SIZE / 1048576))MB" 355 415 log " SHA256: $SHA" 416 + if [ -f "$ISO_OUT" ]; then 417 + log " ISO: $((ISO_SIZE / 1048576))MB" 418 + fi 356 419 log "═══════════════════════════════════════════" 357 420 358 421 # Write metadata ··· 363 426 "build_ts": "$BUILD_TS", 364 427 "size": $VMLINUZ_SIZE, 365 428 "sha256": "$SHA", 429 + "iso_size": ${ISO_SIZE:-0}, 430 + "iso_sha256": "${ISO_SHA:-}", 366 431 "handle": "$HANDLE" 367 432 } 368 433 EOF
+34 -6
fedac/native/scripts/upload-release.sh
··· 3 3 # Publishes: native-notepat-latest.vmlinuz, .sha256, .version, and updates releases.json 4 4 # 5 5 # Usage: ./upload-release.sh [vmlinuz_path] 6 + # ./upload-release.sh --iso [iso_path] # Upload ISO only 6 7 # Credentials auto-loaded from aesthetic-computer-vault/fedac/native/upload.env 7 8 8 9 set -e 9 10 10 11 SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" 11 - VMLINUZ="${1:-${SCRIPT_DIR}/../build/vmlinuz}" 12 - if [ ! -f "$VMLINUZ" ]; then 13 - echo "Error: vmlinuz not found at $VMLINUZ" >&2 14 - exit 1 12 + ISO_ONLY=0 13 + if [ "${1:-}" = "--iso" ]; then 14 + ISO_ONLY=1 15 + ISO_PATH="${2:-${SCRIPT_DIR}/../build/ac-os.iso}" 16 + if [ ! -f "$ISO_PATH" ]; then 17 + echo "Error: ISO not found at $ISO_PATH" >&2 18 + exit 1 19 + fi 20 + VMLINUZ="/dev/null" # not used but needed for cred loading below 21 + else 22 + VMLINUZ="${1:-${SCRIPT_DIR}/../build/vmlinuz}" 23 + if [ ! -f "$VMLINUZ" ]; then 24 + echo "Error: vmlinuz not found at $VMLINUZ" >&2 25 + exit 1 26 + fi 15 27 fi 16 28 17 29 # Credentials — check env (set by ac-os), session cache, plaintext vault, or GPG decrypt ··· 164 176 | node "$SCRIPT_DIR/track-build.mjs" record 2>&1 || true 165 177 fi 166 178 179 + # Upload ISO if available (from --iso flag or alongside vmlinuz) 180 + if [ "$ISO_ONLY" = "1" ]; then 181 + echo "Uploading ISO: $(du -sh "$ISO_PATH" | cut -f1)" 182 + do_upload "$ISO_PATH" "os/${CHANNEL_PREFIX}native-notepat-latest.iso" "application/octet-stream" 183 + echo "ISO published: ${BASE_URL}/os/${CHANNEL_PREFIX}native-notepat-latest.iso" 184 + exit 0 185 + fi 186 + 187 + # Also upload ISO if it exists next to vmlinuz 188 + ISO_SIBLING="$(dirname "$VMLINUZ")/ac-os.iso" 189 + if [ -f "$ISO_SIBLING" ]; then 190 + echo " Uploading ISO ($(du -sh "$ISO_SIBLING" | cut -f1))..." 191 + do_upload "$ISO_SIBLING" "os/${CHANNEL_PREFIX}native-notepat-latest.iso" "application/octet-stream" 192 + fi 193 + 167 194 echo "" 168 195 echo "Release published: $BUILD_NAME ($FULL_VERSION)" 169 - echo " ${BASE_URL}/os/native-notepat-latest.vmlinuz" 170 - echo " ${BASE_URL}/os/releases.json" 196 + echo " ${BASE_URL}/os/${CHANNEL_PREFIX}native-notepat-latest.vmlinuz" 197 + echo " ${BASE_URL}/os/${CHANNEL_PREFIX}releases.json" 198 + [ -f "$ISO_SIBLING" ] && echo " ${BASE_URL}/os/${CHANNEL_PREFIX}native-notepat-latest.iso"
+18 -6
oven/native-builder.mjs
··· 204 204 205 205 job.percent = 75; 206 206 207 - // Phase 3: Extract vmlinuz from container 208 - addLogLine(job, "stdout", "Phase 3: Extracting kernel..."); 207 + // Phase 3: Extract vmlinuz + ISO from container 208 + addLogLine(job, "stdout", "Phase 3: Extracting kernel + ISO..."); 209 209 const cid = (await fs.readFile(cidFile, "utf8")).trim(); 210 + const isoOut = `/tmp/oven-iso-${job.id}`; 210 211 await runPhase(job, "extract", "bash", ["-c", 211 - `docker cp ${cid}:/tmp/ac-build/vmlinuz ${vmlinuzOut} && docker rm ${cid} >/dev/null` 212 + `docker cp ${cid}:/tmp/ac-build/vmlinuz ${vmlinuzOut} && docker cp ${cid}:/tmp/ac-build/ac-os.iso ${isoOut} 2>/dev/null; docker rm ${cid} >/dev/null` 212 213 ], repoDir); 213 214 214 215 job.percent = 80; 215 216 216 - // Phase 4: Upload vmlinuz to DO Spaces CDN 217 + // Phase 4: Upload vmlinuz + ISO to DO Spaces CDN 217 218 addLogLine(job, "stdout", "Phase 4: Uploading to CDN..."); 218 219 const uploadScript = path.join(NATIVE_DIR, "scripts/upload-release.sh"); 219 - await runPhase(job, "upload", "bash", [uploadScript, vmlinuzOut], NATIVE_DIR, { 220 + const uploadEnv = { 220 221 DO_SPACES_KEY: process.env.DO_SPACES_KEY || process.env.ART_SPACES_KEY || "", 221 222 DO_SPACES_SECRET: 222 223 process.env.DO_SPACES_SECRET || process.env.ART_SPACES_SECRET || "", 223 - }); 224 + }; 225 + await runPhase(job, "upload", "bash", [uploadScript, vmlinuzOut], NATIVE_DIR, uploadEnv); 226 + 227 + // Upload ISO if it was generated 228 + try { 229 + await fs.access(isoOut); 230 + addLogLine(job, "stdout", " Uploading ISO..."); 231 + await runPhase(job, "upload-iso", "bash", ["-c", 232 + `${uploadScript} --iso ${isoOut}` 233 + ], NATIVE_DIR, uploadEnv); 234 + } catch { addLogLine(job, "stdout", " No ISO generated — skipping"); } 224 235 225 236 // Cleanup C build 226 237 try { await fs.unlink(vmlinuzOut); } catch {} 238 + try { await fs.unlink(isoOut); } catch {} 227 239 try { await fs.unlink(cidFile); } catch {} 228 240 229 241 job.percent = 85;