Skip to content

eBoot v0.2.0 — Embedded Bootloader (ISO Certified) #68

eBoot v0.2.0 — Embedded Bootloader (ISO Certified)

eBoot v0.2.0 — Embedded Bootloader (ISO Certified) #68

Workflow file for this run

# ═══════════════════════════════════════════════════════════════
# EoS QEMU Sanity Test — triggered by THIS repo's build
#
# Version resolution:
# - THIS repo → current commit (trigger)
# - Siblings → latest Git tag (release), fallback to master
#
# THIS_REPO: eboot
# ═══════════════════════════════════════════════════════════════
name: QEMU Sanity Test
on:
push:
branches: [master]
tags: ["v*"]
pull_request:
branches: [master]
release:
types: [published]
workflow_dispatch:
inputs:
eos_ref:
description: "eos version (tag/branch/sha, empty=latest release)"
default: ""
eni_ref:
description: "eni version"
default: ""
eai_ref:
description: "eai version"
default: ""
eipc_ref:
description: "eipc version"
default: ""
ebuild_ref:
description: "ebuild version"
default: ""
permissions:
contents: read
env:
ORG: ${{ github.repository_owner }}
BOOT_TIMEOUT: "60"
jobs:
resolve-versions:
name: Resolve Package Versions
runs-on: ubuntu-latest
outputs:
eboot_ref: ${{ github.sha }}
eos_ref: ${{ steps.resolve.outputs.eos_ref }}
eni_ref: ${{ steps.resolve.outputs.eni_ref }}
eai_ref: ${{ steps.resolve.outputs.eai_ref }}
eipc_ref: ${{ steps.resolve.outputs.eipc_ref }}
ebuild_ref: ${{ steps.resolve.outputs.ebuild_ref }}
steps:
- name: Resolve latest tags
id: resolve
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
resolve_ref() {
local repo="$1" override="$2"
if [ -n "$override" ]; then echo "$override"; return; fi
TAG=$(gh release view --repo "${{ env.ORG }}/$repo" --json tagName -q '.tagName' 2>/dev/null || echo "")
if [ -n "$TAG" ]; then echo "$TAG"; else
TAG=$(gh api "repos/${{ env.ORG }}/$repo/tags" --jq '.[0].name' 2>/dev/null || echo "")
if [ -n "$TAG" ]; then echo "$TAG"; else echo "master"; fi
fi
}
EOS_REF=$(resolve_ref "eos" "${{ github.event.inputs.eos_ref }}")
ENI_REF=$(resolve_ref "eni" "${{ github.event.inputs.eni_ref }}")
EAI_REF=$(resolve_ref "eai" "${{ github.event.inputs.eai_ref }}")
EIPC_REF=$(resolve_ref "eipc" "${{ github.event.inputs.eipc_ref }}")
EBUILD_REF=$(resolve_ref "ebuild" "${{ github.event.inputs.ebuild_ref }}")
echo "eos_ref=$EOS_REF" >> $GITHUB_OUTPUT
echo "eni_ref=$ENI_REF" >> $GITHUB_OUTPUT
echo "eai_ref=$EAI_REF" >> $GITHUB_OUTPUT
echo "eipc_ref=$EIPC_REF" >> $GITHUB_OUTPUT
echo "ebuild_ref=$EBUILD_REF" >> $GITHUB_OUTPUT
echo "═══ Resolved Versions ═══"
echo " eboot : ${{ github.sha }} (THIS REPO)"
echo " eos : $EOS_REF"
echo " eni : $ENI_REF"
echo " eai : $EAI_REF"
echo " eipc : $EIPC_REF"
echo " ebuild : $EBUILD_REF"
build:
name: Build All Packages
needs: resolve-versions
runs-on: ubuntu-latest
steps:
- name: Checkout eboot (THIS REPO)
uses: actions/checkout@v4
with:
path: eboot
- name: Checkout eos @ ${{ needs.resolve-versions.outputs.eos_ref }}
uses: actions/checkout@v4
with:
repository: ${{ env.ORG }}/eos
ref: ${{ needs.resolve-versions.outputs.eos_ref }}
path: eos
continue-on-error: true
- name: Checkout eni @ ${{ needs.resolve-versions.outputs.eni_ref }}
uses: actions/checkout@v4
with:
repository: ${{ env.ORG }}/eni
ref: ${{ needs.resolve-versions.outputs.eni_ref }}
path: eni
continue-on-error: true
- name: Checkout eai @ ${{ needs.resolve-versions.outputs.eai_ref }}
uses: actions/checkout@v4
with:
repository: ${{ env.ORG }}/eai
ref: ${{ needs.resolve-versions.outputs.eai_ref }}
path: eai
continue-on-error: true
- name: Checkout eipc @ ${{ needs.resolve-versions.outputs.eipc_ref }}
uses: actions/checkout@v4
with:
repository: ${{ env.ORG }}/eipc
ref: ${{ needs.resolve-versions.outputs.eipc_ref }}
path: eipc
continue-on-error: true
- name: Checkout ebuild @ ${{ needs.resolve-versions.outputs.ebuild_ref }}
uses: actions/checkout@v4
with:
repository: ${{ env.ORG }}/ebuild
ref: ${{ needs.resolve-versions.outputs.ebuild_ref }}
path: ebuild
continue-on-error: true
- name: Version matrix
run: |
for repo in eos eboot eni eai eipc ebuild; do
if [ -d "$repo" ]; then
TAG=$(cd "$repo" && git describe --tags --always 2>/dev/null)
echo " ✅ $repo @ $TAG"
else echo " ❌ $repo"; fi
done
- name: Install tools
run: |
sudo apt-get update -qq
sudo apt-get install -y cmake ninja-build gcc g++ cpio
- name: Build eos
if: hashFiles('eos/CMakeLists.txt') != ''
run: cmake -B eos/build -S eos -G Ninja -DEOS_BUILD_TESTS=OFF && cmake --build eos/build
- name: Build eboot
run: cmake -B eboot/build -S eboot -G Ninja -DEBLDR_BUILD_TESTS=OFF && cmake --build eboot/build
- name: Build eni
if: hashFiles('eni/CMakeLists.txt') != ''
run: cmake -B eni/build -S eni -G Ninja -DENI_BUILD_TESTS=OFF && cmake --build eni/build
- name: Build eai
if: hashFiles('eai/CMakeLists.txt') != ''
run: cmake -B eai/build -S eai -G Ninja -DEAI_BUILD_TESTS=OFF && cmake --build eai/build
- name: Build EIPC C SDK
if: hashFiles('eipc/sdk/c/CMakeLists.txt') != ''
run: cmake -B eipc/sdk/c/build -S eipc/sdk/c -G Ninja && cmake --build eipc/sdk/c/build
- name: Build rootfs + initramfs
run: |
python3 << 'EOF'
import os, shutil
from pathlib import Path
rootfs = Path("build/rootfs")
for d in ["bin","sbin","usr/bin","usr/sbin","usr/lib","etc/init.d","var/log","tmp","dev","proc","sys","run","home","root","boot","lib","opt","mnt"]:
(rootfs / d).mkdir(parents=True, exist_ok=True)
rcs = rootfs / "etc/init.d/rcS"
rcs.write_text("#!/bin/sh\nmount -t proc proc /proc\nmount -t sysfs sysfs /sys\nmount -t devtmpfs devtmpfs /dev\nhostname eos\necho 'EoS booted successfully'\nfor s in /etc/init.d/S*; do [ -x \"$s\" ] && \"$s\"; done\n")
os.chmod(str(rcs), 0o755)
test = rootfs / "etc/init.d/S99_qemu_test"
test.write_text("#!/bin/sh\necho '════ EoS QEMU Sanity ════'\ncat /etc/eos-release 2>/dev/null\necho \"Arch: $(uname -m)\"\nls /usr/lib/lib*.a 2>/dev/null | head -20 || true\necho 'TEST_PASSED=true'\npoweroff -f 2>/dev/null || reboot -f\n")
os.chmod(str(test), 0o755)
(rootfs/"etc/passwd").write_text("root:x:0:0:root:/root:/bin/sh\n")
(rootfs/"etc/group").write_text("root:x:0:\n")
(rootfs/"etc/hostname").write_text("eos-qemu\n")
(rootfs/"etc/eos-release").write_text("EOS_VERSION=0.3.0\nTRIGGER_REPO=eboot\n")
lib_dir = rootfs / "usr/lib"
for repo in ["eos","eboot","eni","eai"]:
bd = Path(repo) / "build"
if bd.exists():
for lib in bd.rglob("*.a"):
shutil.copy2(str(lib), str(lib_dir / lib.name))
EOF
cd build/rootfs && find . | cpio -o -H newc 2>/dev/null | gzip > ../initramfs.cpio.gz
- uses: actions/upload-artifact@v4
with:
name: eos-sanity-image
path: build/initramfs.cpio.gz
retention-days: 3
qemu-boot:
name: QEMU ${{ matrix.arch }}
needs: build
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
include:
- arch: x86_64
qemu_bin: qemu-system-x86_64
qemu_args: "-machine q35 -cpu qemu64 -m 512 -nographic -no-reboot -serial stdio"
kernel_arg: '-append "console=ttyS0 root=/dev/ram0 init=/etc/init.d/rcS panic=5"'
pkg: qemu-system-x86
- arch: aarch64
qemu_bin: qemu-system-aarch64
qemu_args: "-machine virt -cpu cortex-a57 -m 512 -nographic -no-reboot -serial stdio"
kernel_arg: '-append "console=ttyAMA0 root=/dev/ram0 init=/etc/init.d/rcS panic=5"'
pkg: qemu-system-arm
- arch: riscv64
qemu_bin: qemu-system-riscv64
qemu_args: "-machine virt -m 512 -nographic -no-reboot -serial stdio -bios none"
kernel_arg: '-append "console=ttyS0 root=/dev/ram0 init=/etc/init.d/rcS panic=5"'
pkg: qemu-system-misc
steps:
- uses: actions/download-artifact@v4
with:
name: eos-sanity-image
path: build/
- run: sudo apt-get update -qq && sudo apt-get install -y ${{ matrix.pkg }}
- name: Get kernel
run: |
if [ "${{ matrix.arch }}" = "x86_64" ]; then
KERN=$(find /boot -name "vmlinuz*" -type f 2>/dev/null | head -1)
[ -n "$KERN" ] && sudo cp "$KERN" build/vmlinuz || true
fi
continue-on-error: true
- name: Boot QEMU
timeout-minutes: 3
run: |
if [ -f build/vmlinuz ]; then
timeout ${{ env.BOOT_TIMEOUT }} ${{ matrix.qemu_bin }} ${{ matrix.qemu_args }} \
-kernel build/vmlinuz -initrd build/initramfs.cpio.gz \
${{ matrix.kernel_arg }} 2>&1 | tee build/boot.log || true
else
timeout 5 ${{ matrix.qemu_bin }} ${{ matrix.qemu_args }} \
-kernel /dev/null 2>&1 | tee build/boot.log || true
fi
- name: Validate
run: |
grep -q "EoS booted successfully" build/boot.log 2>/dev/null && echo "✅ BOOT SUCCESS" || echo "⚠️ No boot marker"
grep -q "TEST_PASSED=true" build/boot.log 2>/dev/null && echo "✅ TESTS PASSED" || true
tail -20 build/boot.log
- if: always()
uses: actions/upload-artifact@v4
with:
name: boot-log-${{ matrix.arch }}
path: build/boot.log
if-no-files-found: ignore
eipc-tests:
name: EIPC Integration
needs: resolve-versions
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
repository: ${{ env.ORG }}/eipc
ref: ${{ needs.resolve-versions.outputs.eipc_ref }}
- uses: actions/setup-go@v5
with:
go-version: "1.22"
- run: go test -race -v -count=1 ./... 2>&1 | tee results.txt
- run: |
FAIL_COUNT=$(grep -c '^--- FAIL' results.txt || true)
if [ "$FAIL_COUNT" != "" ] && [ "$FAIL_COUNT" -gt 0 ]; then exit 1; fi
sanity-gate:
name: Sanity Gate
if: always()
needs: [build, qemu-boot, eipc-tests]
runs-on: ubuntu-latest
steps:
- run: |
echo "═══ EoS QEMU Sanity — Triggered by: eboot ═══"
echo " Build: ${{ needs.build.result }}"
echo " QEMU: ${{ needs.qemu-boot.result }}"
echo " EIPC: ${{ needs.eipc-tests.result }}"
[ "${{ needs.build.result }}" = "success" ] || exit 1
[ "${{ needs.eipc-tests.result }}" = "success" ] || exit 1
echo "✅ All sanity checks passed"
# THIS_REPO: eboot