This repository was archived by the owner on Jun 19, 2026. It is now read-only.
Merge pull request #165 from NERVsystems/claude/review-file-tree-view… #555
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: CI | |
| on: | |
| push: | |
| branches: [ master ] | |
| pull_request: | |
| branches: [ master ] | |
| workflow_dispatch: | |
| permissions: {} | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.ref }} | |
| cancel-in-progress: true | |
| jobs: | |
| # ───────────────────────────────────────────── | |
| # Linux AMD64: Full bootstrap build from source | |
| # ───────────────────────────────────────────── | |
| linux-amd64: | |
| name: Linux AMD64 Build & Test | |
| runs-on: ubuntu-24.04 | |
| timeout-minutes: 30 | |
| permissions: | |
| contents: read | |
| env: | |
| ROOT: ${{ github.workspace }} | |
| steps: | |
| - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 | |
| - name: Stamp build version | |
| run: | | |
| BUILD_DATE=$(date +%Y%m%d) | |
| SHORT_SHA=${GITHUB_SHA::8} | |
| sed -i "s|InferNode 0.1|InferNode 0.1 build ${BUILD_DATE}-${SHORT_SHA}|" include/version.h | |
| echo "Version: $(cat include/version.h)" | |
| - name: Install build dependencies | |
| run: sudo apt-get update && sudo apt-get install -y build-essential | |
| - name: Bootstrap build (mk, libraries, limbo, emulator) | |
| run: | | |
| chmod +x build-linux-amd64.sh | |
| ./build-linux-amd64.sh | |
| - name: Verify emulator binary | |
| run: | | |
| test -x emu/Linux/o.emu || { echo "Emulator not built"; exit 1; } | |
| file emu/Linux/o.emu | |
| test -x Linux/amd64/bin/limbo || { echo "Limbo compiler not built"; exit 1; } | |
| - name: Compile test suite | |
| run: | | |
| LIMBO="$ROOT/Linux/amd64/bin/limbo" | |
| # Build the testing module first | |
| mkdir -p dis/tests dis/lib | |
| # Build testing library | |
| COMPILE_FAILURES=0 | |
| if [ -d tests/testing ]; then | |
| cd tests/testing | |
| for f in *.b; do | |
| if [ -f "$f" ]; then | |
| if ! "$LIMBO" -I "$ROOT/module" -o "$ROOT/dis/lib/${f%.b}.dis" "$f" 2>&1; then | |
| echo "ERROR: Failed to compile testing/$f" | |
| COMPILE_FAILURES=$((COMPILE_FAILURES + 1)) | |
| fi | |
| fi | |
| done | |
| cd "$ROOT" | |
| fi | |
| # Build test runner and test files into tests/ where the runner expects them | |
| cd tests | |
| for f in *.b; do | |
| name="${f%.b}" | |
| echo "Compiling $f..." | |
| if ! "$LIMBO" -I "$ROOT/module" -o "$ROOT/tests/$name.dis" "$f" 2>&1; then | |
| echo "ERROR: Failed to compile $f" | |
| COMPILE_FAILURES=$((COMPILE_FAILURES + 1)) | |
| fi | |
| done | |
| cd "$ROOT" | |
| # Verify runner was compiled | |
| test -f tests/runner.dis || { echo "Test runner not compiled"; exit 1; } | |
| echo "Compiled test .dis files:" | |
| ls tests/*_test.dis 2>/dev/null | wc -l | |
| if [ "$COMPILE_FAILURES" -gt 0 ]; then | |
| echo "ERROR: $COMPILE_FAILURES test file(s) failed to compile" | |
| exit 1 | |
| fi | |
| - name: Run test suite | |
| run: | | |
| # Create /tmp inside Inferno root for tmp_writable test | |
| mkdir -p tmp | |
| echo "Running test suite inside Inferno emulator..." | |
| # The emulator doesn't exit cleanly after the test runner finishes | |
| # (kernel threads keep the process alive), so we capture output and | |
| # parse the result instead of relying on exit code. | |
| timeout 60 ./emu/Linux/o.emu -r . /tests/runner.dis -v > test-output.txt 2>&1 || true | |
| cat test-output.txt | |
| # Check test results from output | |
| if grep -q "^PASS$" test-output.txt; then | |
| echo "Tests passed." | |
| elif grep -q "^FAIL$" test-output.txt; then | |
| echo "Tests failed." | |
| exit 1 | |
| else | |
| echo "No test result found in output — tests may not have run." | |
| exit 1 | |
| fi | |
| - name: Run wallet and secstore integration tests | |
| run: | | |
| echo "Running host-side integration tests..." | |
| # wallet9p basic operations | |
| if [ -f tests/host/wallet9p_test.sh ]; then | |
| echo "--- wallet9p test ---" | |
| chmod +x tests/host/wallet9p_test.sh | |
| ROOT=. bash tests/host/wallet9p_test.sh > wallet9p-test.txt 2>&1 || true | |
| cat wallet9p-test.txt | |
| if grep -q "=== PASS ===" wallet9p-test.txt; then | |
| echo "wallet9p test: PASS" | |
| else | |
| echo "wallet9p test: SKIP (requires full Inferno namespace)" | |
| fi | |
| fi | |
| # wallet persistence (secstore round-trip) | |
| if [ -f tests/host/wallet_persist_test.sh ]; then | |
| echo "--- wallet persistence test ---" | |
| chmod +x tests/host/wallet_persist_test.sh | |
| ROOT=. bash tests/host/wallet_persist_test.sh > wallet-persist-test.txt 2>&1 || true | |
| cat wallet-persist-test.txt | |
| if grep -q "^PASS$" wallet-persist-test.txt; then | |
| echo "wallet persistence test: PASS" | |
| else | |
| echo "wallet persistence test: FAIL (non-fatal in CI)" | |
| fi | |
| fi | |
| - name: Upload Linux build artifacts | |
| uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 | |
| if: success() | |
| with: | |
| name: infernode-linux-amd64 | |
| path: | | |
| emu/Linux/o.emu | |
| Linux/amd64/bin/limbo | |
| Linux/amd64/bin/mk | |
| retention-days: 14 | |
| # ───────────────────────────────────────────── | |
| # macOS ARM64: Build using shipped toolchain | |
| # ───────────────────────────────────────────── | |
| macos-arm64: | |
| name: macOS ARM64 Build & Test | |
| runs-on: macos-15 | |
| timeout-minutes: 30 | |
| permissions: | |
| contents: read | |
| env: | |
| ROOT: ${{ github.workspace }} | |
| steps: | |
| - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 | |
| - name: Stamp build version | |
| run: | | |
| BUILD_DATE=$(date +%Y%m%d) | |
| SHORT_SHA=${GITHUB_SHA::8} | |
| sed -i '' "s|InferNode 0.1|InferNode 0.1 build ${BUILD_DATE}-${SHORT_SHA}|" include/version.h | |
| echo "Version: $(cat include/version.h)" | |
| - name: Build mk | |
| run: | | |
| chmod +x makemk.sh | |
| ./makemk.sh | |
| test -x MacOSX/arm64/bin/mk || { echo "mk build failed"; exit 1; } | |
| - name: Build system libraries | |
| run: | | |
| export PATH="$ROOT/MacOSX/arm64/bin:/usr/bin:/bin" | |
| for dir in lib9 libbio libmp libsec libmath; do | |
| echo "Building $dir..." | |
| (cd $dir && "$ROOT/MacOSX/arm64/bin/mk" install) || exit 1 | |
| done | |
| - name: Build limbo compiler | |
| run: | | |
| export PATH="$ROOT/MacOSX/arm64/bin:/usr/bin:/bin" | |
| (cd limbo && "$ROOT/MacOSX/arm64/bin/mk" install) || exit 1 | |
| test -x MacOSX/arm64/bin/limbo || { echo "limbo not found"; exit 1; } | |
| - name: Build libinterp and remaining libraries | |
| run: | | |
| export PATH="$ROOT/MacOSX/arm64/bin:/usr/bin:/bin" | |
| (cd libinterp && "$ROOT/MacOSX/arm64/bin/mk" install) || exit 1 | |
| for dir in libkeyring libdraw libmemdraw libmemlayer; do | |
| echo "Building $dir..." | |
| if ! (cd $dir && "$ROOT/MacOSX/arm64/bin/mk" install); then | |
| echo "WARNING: $dir build failed (non-fatal for headless build)" | |
| fi | |
| done | |
| - name: Build headless emulator | |
| run: | | |
| export PATH="$ROOT/MacOSX/arm64/bin:/usr/bin:/bin" | |
| cd emu/MacOSX | |
| OBJTYPE=arm64 SYSTARG=MacOSX SHELL=/bin/sh "$ROOT/MacOSX/arm64/bin/mk" -f mkfile-g | |
| test -f o.emu || { echo "Headless emulator build failed"; exit 1; } | |
| - name: Compile essential dis files | |
| run: | | |
| LIMBO="$ROOT/MacOSX/arm64/bin/limbo" | |
| # Verify limbo works | |
| echo "Using limbo: $LIMBO" | |
| "$LIMBO" -w 2>&1 || true | |
| # emuinit + shell (these must succeed) | |
| echo "Compiling emuinit.b..." | |
| "$LIMBO" -I./module -gw appl/cmd/emuinit.b | |
| cp emuinit.dis dis/ | |
| echo "Compiling sh.b..." | |
| (cd appl/cmd/sh && ../../../MacOSX/arm64/bin/limbo -I../../../module -gw sh.b && cp sh.dis ../../../dis/) | |
| # Core commands | |
| for cmd in cat ls pwd echo date; do | |
| echo "Compiling $cmd.b..." | |
| "$LIMBO" -I./module -gw "appl/cmd/$cmd.b" && cp "$cmd.dis" dis/ || echo "WARNING: $cmd.b compilation failed" | |
| done | |
| # Essential libraries | |
| mkdir -p dis/lib | |
| cd appl/lib | |
| for f in bufio.b string.b readdir.b arg.b; do | |
| echo "Compiling lib/$f..." | |
| "../../MacOSX/arm64/bin/limbo" -I../../module -gw "$f" || echo "WARNING: $f compilation failed" | |
| done | |
| cp bufio.dis string.dis readdir.dis arg.dis ../../dis/lib/ 2>/dev/null || true | |
| cd "$ROOT" | |
| # Verify critical .dis files exist (from compilation or git checkout) | |
| echo "Verifying essential .dis files..." | |
| for f in dis/emuinit.dis dis/sh.dis dis/cat.dis dis/ls.dis dis/pwd.dis; do | |
| if [ -f "$f" ]; then | |
| echo " OK: $f ($(wc -c < "$f") bytes)" | |
| else | |
| echo " MISSING: $f" | |
| fi | |
| done | |
| - name: Compile test suite | |
| run: | | |
| LIMBO="$ROOT/MacOSX/arm64/bin/limbo" | |
| mkdir -p dis/lib | |
| # Build testing library | |
| COMPILE_FAILURES=0 | |
| if [ -d tests/testing ]; then | |
| cd tests/testing | |
| for f in *.b; do | |
| if [ -f "$f" ]; then | |
| if ! "$LIMBO" -I "$ROOT/module" -o "$ROOT/dis/lib/${f%.b}.dis" "$f" 2>&1; then | |
| echo "ERROR: Failed to compile testing/$f" | |
| COMPILE_FAILURES=$((COMPILE_FAILURES + 1)) | |
| fi | |
| fi | |
| done | |
| cd "$ROOT" | |
| fi | |
| # Build test runner and test files into tests/ where the runner expects them | |
| cd tests | |
| for f in *.b; do | |
| name="${f%.b}" | |
| echo "Compiling $f..." | |
| if ! "$LIMBO" -I "$ROOT/module" -o "$ROOT/tests/$name.dis" "$f" 2>&1; then | |
| echo "ERROR: Failed to compile $f" | |
| COMPILE_FAILURES=$((COMPILE_FAILURES + 1)) | |
| fi | |
| done | |
| cd "$ROOT" | |
| test -f tests/runner.dis || { echo "Test runner not compiled"; exit 1; } | |
| echo "Compiled test .dis files:" | |
| ls tests/*_test.dis 2>/dev/null | wc -l | |
| if [ "$COMPILE_FAILURES" -gt 0 ]; then | |
| echo "ERROR: $COMPILE_FAILURES test file(s) failed to compile" | |
| exit 1 | |
| fi | |
| - name: Run test suite | |
| run: | | |
| # Create /tmp inside Inferno root for tmp_writable test | |
| mkdir -p tmp | |
| echo "Running test suite inside Inferno emulator..." | |
| # The emulator doesn't exit cleanly after the test runner finishes | |
| # (kernel threads keep the process alive), so we capture output and | |
| # parse the result instead of relying on exit code. | |
| # macOS doesn't have timeout; use background process with kill | |
| ./emu/MacOSX/o.emu -r . /tests/runner.dis -v > test-output.txt 2>&1 & | |
| EMU_PID=$! | |
| ( sleep 60; kill $EMU_PID 2>/dev/null ) & | |
| WATCHDOG=$! | |
| wait $EMU_PID 2>/dev/null || true | |
| kill $WATCHDOG 2>/dev/null || true | |
| cat test-output.txt | |
| # Check test results from output | |
| if grep -q "^PASS$" test-output.txt; then | |
| echo "Tests passed." | |
| elif grep -q "^FAIL$" test-output.txt; then | |
| echo "Tests failed." | |
| exit 1 | |
| else | |
| echo "No test result found in output — tests may not have run." | |
| exit 1 | |
| fi | |
| - name: Run port verification | |
| run: | | |
| chmod +x verify-port.sh | |
| ./verify-port.sh | |
| - name: Run wallet and secstore integration tests | |
| run: | | |
| echo "Running host-side integration tests..." | |
| # wallet9p basic operations | |
| if [ -f tests/host/wallet9p_test.sh ]; then | |
| echo "--- wallet9p test ---" | |
| chmod +x tests/host/wallet9p_test.sh | |
| ROOT=. bash tests/host/wallet9p_test.sh > wallet9p-test.txt 2>&1 || true | |
| cat wallet9p-test.txt | |
| if grep -q "=== PASS ===" wallet9p-test.txt; then | |
| echo "wallet9p test: PASS" | |
| else | |
| echo "wallet9p test: SKIP (requires full Inferno namespace)" | |
| fi | |
| fi | |
| # wallet persistence (secstore round-trip) | |
| if [ -f tests/host/wallet_persist_test.sh ]; then | |
| echo "--- wallet persistence test ---" | |
| chmod +x tests/host/wallet_persist_test.sh | |
| ROOT=. bash tests/host/wallet_persist_test.sh > wallet-persist-test.txt 2>&1 || true | |
| cat wallet-persist-test.txt | |
| if grep -q "^PASS$" wallet-persist-test.txt; then | |
| echo "wallet persistence test: PASS" | |
| else | |
| echo "wallet persistence test: FAIL (non-fatal in CI)" | |
| fi | |
| fi | |
| - name: Upload macOS build artifacts | |
| uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 | |
| if: success() | |
| with: | |
| name: infernode-macos-arm64 | |
| path: | | |
| emu/MacOSX/o.emu | |
| MacOSX/arm64/bin/limbo | |
| MacOSX/arm64/bin/mk | |
| retention-days: 14 |