feat(sdk): add sparse sandbox configuration patches #2414
Workflow file for this run
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: Check | |
| on: | |
| push: | |
| branches: [main] | |
| pull_request: | |
| branches: [main] | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.ref }} | |
| cancel-in-progress: ${{ github.ref != 'refs/heads/main' }} | |
| permissions: | |
| contents: read | |
| env: | |
| CARGO_TERM_COLOR: always | |
| CARGO_NET_RETRY: "10" | |
| CARGO_HTTP_TIMEOUT: "120" | |
| CARGO_HTTP_MULTIPLEXING: "false" | |
| LIBKRUNFW_VERSION: "5.6.1" | |
| LIBKRUNFW_ABI: "5" | |
| jobs: | |
| # --------------------------------------------------------------------------- | |
| # Detect whether the diff touches anything outside docs/. When it doesn't, | |
| # every downstream job is gated off and posts as "skipped", which satisfies | |
| # the required status checks on main without burning CI minutes. | |
| # --------------------------------------------------------------------------- | |
| changes: | |
| name: Detect code changes | |
| runs-on: ubuntu-latest | |
| outputs: | |
| code: ${{ steps.filter.outputs.code }} | |
| steps: | |
| - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| - uses: dorny/paths-filter@7b450fff21473bca461d4b92ce414b9d0420d706 # v4.0.2 | |
| id: filter | |
| with: | |
| filters: | | |
| code: | |
| - '!docs/**' | |
| # --------------------------------------------------------------------------- | |
| # Build kernel.c on Linux for macOS libkrunfw linking | |
| # --------------------------------------------------------------------------- | |
| build-kernel: | |
| name: Build kernel.c (aarch64) | |
| needs: changes | |
| if: needs.changes.outputs.code == 'true' | |
| runs-on: ubuntu-24.04-arm | |
| steps: | |
| - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| submodules: true | |
| - name: Cache kernel.c | |
| id: cache-kernel | |
| uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 | |
| with: | |
| path: vendor/libkrunfw/kernel.c | |
| key: kernel-c-aarch64-${{ hashFiles('vendor/libkrunfw/**') }} | |
| - name: Install kernel build deps | |
| if: steps.cache-kernel.outputs.cache-hit != 'true' | |
| run: sudo apt-get update && sudo apt-get install -y libcap-ng-dev gcc make flex bison libelf-dev bc python3-pyelftools | |
| - name: Build kernel.c | |
| if: steps.cache-kernel.outputs.cache-hit != 'true' | |
| run: | | |
| cd vendor/libkrunfw | |
| make -j$(nproc) | |
| - name: Upload kernel.c | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 | |
| with: | |
| name: kernel-c-aarch64 | |
| path: vendor/libkrunfw/kernel.c | |
| build-kernel-x86_64: | |
| name: Build kernel.c (x86_64) | |
| needs: changes | |
| if: needs.changes.outputs.code == 'true' | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| submodules: true | |
| - name: Cache kernel.c | |
| id: cache-kernel | |
| uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 | |
| with: | |
| path: vendor/libkrunfw/kernel.c | |
| key: kernel-c-x86_64-${{ hashFiles('vendor/libkrunfw/**') }} | |
| - name: Install kernel build deps | |
| if: steps.cache-kernel.outputs.cache-hit != 'true' | |
| run: sudo apt-get update && sudo apt-get install -y libcap-ng-dev gcc make flex bison libelf-dev bc python3-pyelftools | |
| - name: Build kernel.c | |
| if: steps.cache-kernel.outputs.cache-hit != 'true' | |
| run: | | |
| cd vendor/libkrunfw | |
| make -j$(nproc) | |
| - name: Upload kernel.c | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 | |
| with: | |
| name: kernel-c-x86_64 | |
| path: vendor/libkrunfw/kernel.c | |
| # --------------------------------------------------------------------------- | |
| # Build agentd on Linux for macOS packaging | |
| # --------------------------------------------------------------------------- | |
| build-agentd-aarch64: | |
| name: Build agentd (aarch64-linux-musl) | |
| needs: changes | |
| if: needs.changes.outputs.code == 'true' | |
| runs-on: ubuntu-24.04-arm | |
| steps: | |
| - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| submodules: true | |
| - uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable | |
| - uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2 | |
| with: | |
| cache-bin: false | |
| - name: Install agentd build deps | |
| run: sudo apt-get update && sudo apt-get install -y musl-tools | |
| - name: Build agentd | |
| run: | | |
| rustup target add --toolchain stable aarch64-unknown-linux-musl | |
| cargo +stable build --release --manifest-path crates/agentd/Cargo.toml --target aarch64-unknown-linux-musl | |
| mkdir -p build | |
| cp target/aarch64-unknown-linux-musl/release/agentd build/agentd | |
| - name: Upload agentd | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 | |
| with: | |
| name: agentd-aarch64-linux-musl | |
| path: build/agentd | |
| build-agentd-x86_64: | |
| name: Build agentd (x86_64-linux-musl) | |
| needs: changes | |
| if: needs.changes.outputs.code == 'true' | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| submodules: true | |
| - uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable | |
| - uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2 | |
| with: | |
| cache-bin: false | |
| - name: Install agentd build deps | |
| run: sudo apt-get update && sudo apt-get install -y musl-tools | |
| - name: Build agentd | |
| run: | | |
| rustup target add --toolchain stable x86_64-unknown-linux-musl | |
| cargo +stable build --release --manifest-path crates/agentd/Cargo.toml --target x86_64-unknown-linux-musl | |
| mkdir -p build | |
| cp target/x86_64-unknown-linux-musl/release/agentd build/agentd | |
| - name: Upload agentd | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 | |
| with: | |
| name: agentd-x86_64-linux-musl | |
| path: build/agentd | |
| # --------------------------------------------------------------------------- | |
| # Check | |
| # --------------------------------------------------------------------------- | |
| check: | |
| name: Check (${{ matrix.target }}) | |
| needs: [build-kernel, build-agentd-aarch64, changes] | |
| if: always() && needs.changes.outputs.code == 'true' | |
| runs-on: ${{ matrix.runner }} | |
| # A green darwin-aarch64 run takes ~35m, and GitHub-hosted macos-14 | |
| # runner speed varies enough that slow runners blew a 45m budget | |
| # mid-build (main and a PR, both on 2026-07-10). 60m restores | |
| # headroom while still bounding a genuinely wedged run. | |
| timeout-minutes: 60 | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - target: linux-x86_64 | |
| runner: ubuntu-latest | |
| arch: x86_64 | |
| os: linux | |
| agentd_target: x86_64-unknown-linux-musl | |
| libkrunfw_file: libkrunfw.so.5.6.1 | |
| - target: linux-aarch64 | |
| runner: ubuntu-24.04-arm | |
| arch: aarch64 | |
| os: linux | |
| agentd_target: aarch64-unknown-linux-musl | |
| libkrunfw_file: libkrunfw.so.5.6.1 | |
| - target: darwin-aarch64 | |
| runner: macos-14 | |
| arch: aarch64 | |
| os: darwin | |
| libkrunfw_file: libkrunfw.5.dylib | |
| steps: | |
| - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| submodules: true | |
| - uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable | |
| with: | |
| components: clippy, rustfmt | |
| - uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2 | |
| with: | |
| cache-bin: false | |
| # -- Linux build deps -- | |
| - name: Install build deps (Linux) | |
| if: matrix.os == 'linux' | |
| run: sudo apt-get update && sudo apt-get install -y musl-tools libcap-ng-dev gcc make flex bison libelf-dev bc python3-pyelftools | |
| # -- agentd (Linux: native musl) -- | |
| - name: Build agentd (musl) | |
| if: matrix.os == 'linux' | |
| run: | | |
| rustup target add --toolchain stable ${{ matrix.agentd_target }} | |
| cargo +stable build --release --manifest-path crates/agentd/Cargo.toml --target ${{ matrix.agentd_target }} | |
| mkdir -p build | |
| cp target/${{ matrix.agentd_target }}/release/agentd build/agentd | |
| # -- agentd (macOS: download prebuilt Linux artifact) -- | |
| - name: Download agentd (macOS) | |
| if: matrix.os == 'darwin' | |
| uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 | |
| with: | |
| name: agentd-aarch64-linux-musl | |
| path: build/ | |
| # -- libkrunfw (cached) -- | |
| - name: Cache libkrunfw | |
| id: cache-libkrunfw | |
| uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 | |
| with: | |
| path: build/libkrunfw* | |
| key: libkrunfw-${{ matrix.target }}-${{ hashFiles('vendor/libkrunfw/**') }} | |
| - name: Build libkrunfw (Linux) | |
| if: steps.cache-libkrunfw.outputs.cache-hit != 'true' && matrix.os == 'linux' | |
| run: | | |
| cd vendor/libkrunfw | |
| make -j$(nproc) | |
| cd ../.. | |
| mkdir -p build | |
| cp vendor/libkrunfw/libkrunfw.so.${{ env.LIBKRUNFW_VERSION }} build/ | |
| cd build | |
| ln -sf libkrunfw.so.${{ env.LIBKRUNFW_VERSION }} libkrunfw.so.${{ env.LIBKRUNFW_ABI }} | |
| ln -sf libkrunfw.so.${{ env.LIBKRUNFW_ABI }} libkrunfw.so | |
| - name: Download kernel.c (macOS) | |
| if: steps.cache-libkrunfw.outputs.cache-hit != 'true' && matrix.os == 'darwin' | |
| uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 | |
| with: | |
| name: kernel-c-aarch64 | |
| path: vendor/libkrunfw/ | |
| - name: Build libkrunfw (macOS) | |
| if: steps.cache-libkrunfw.outputs.cache-hit != 'true' && matrix.os == 'darwin' | |
| run: | | |
| cd vendor/libkrunfw | |
| cc -fPIC -DABI_VERSION=${{ env.LIBKRUNFW_ABI }} -shared -o libkrunfw.${{ env.LIBKRUNFW_ABI }}.dylib kernel.c | |
| cd ../.. | |
| mkdir -p build | |
| cp vendor/libkrunfw/libkrunfw.${{ env.LIBKRUNFW_ABI }}.dylib build/ | |
| cd build | |
| ln -sf libkrunfw.${{ env.LIBKRUNFW_ABI }}.dylib libkrunfw.dylib | |
| - name: Build msb | |
| run: | | |
| cargo build --release --no-default-features --features net,ssh -p microsandbox-cli | |
| mkdir -p build | |
| cp target/release/msb build/msb | |
| - name: Codesign msb (macOS) | |
| if: matrix.os == 'darwin' | |
| run: codesign --entitlements msb-entitlements.plist --force -s - build/msb | |
| # -- Checks (workspace) -- | |
| - name: Format | |
| run: cargo +stable fmt --all -- --check | |
| - name: Clippy | |
| run: cargo +stable clippy --workspace --exclude microsandbox-agentd -- -D warnings | |
| - name: Docs | |
| env: | |
| RUSTDOCFLAGS: "-D warnings" | |
| run: cargo +stable doc --workspace --exclude microsandbox-agentd --no-deps | |
| - name: Check generated microsandbox types | |
| run: cargo +stable run -p microsandbox-types --features ts --bin microsandbox-types-generate -- --check | |
| # -- Checks (agentd — Linux-only) -- | |
| - name: Format agentd | |
| if: matrix.os == 'linux' | |
| run: cargo +stable fmt --manifest-path crates/agentd/Cargo.toml -- --check | |
| - name: Clippy agentd | |
| if: matrix.os == 'linux' | |
| run: cargo +stable clippy --manifest-path crates/agentd/Cargo.toml --target ${{ matrix.agentd_target }} -- -D warnings | |
| # -- Checks (Node SDK) -- | |
| - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 | |
| with: | |
| node-version: 22 | |
| - name: Build agent client package | |
| working-directory: packages/agent-client/typescript | |
| run: npm ci && npm run build && npm run typecheck && npm test | |
| - name: Build microsandbox types package | |
| working-directory: packages/microsandbox-types/typescript | |
| run: npm ci && npm run build && npm run typecheck | |
| - name: Build Node SDK | |
| working-directory: sdk/node-ts | |
| run: | | |
| node scripts/prune-platform-optional-deps.mjs | |
| npm install --package-lock=false | |
| npm run build | |
| # -- Checks (Python SDK) -- | |
| - uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0 | |
| with: | |
| enable-cache: true | |
| cache-dependency-glob: "sdk/python/uv.lock" | |
| - name: Sync Python dev environment | |
| working-directory: sdk/python | |
| run: uv sync --group dev | |
| - name: Stage runtime bundle (Python SDK) | |
| run: | | |
| mkdir -p sdk/python/microsandbox/_bundled/bin | |
| mkdir -p sdk/python/microsandbox/_bundled/lib | |
| cp build/msb sdk/python/microsandbox/_bundled/bin/ | |
| cp build/${{ matrix.libkrunfw_file }} sdk/python/microsandbox/_bundled/lib/ | |
| cd sdk/python/microsandbox/_bundled/lib | |
| if [ "${{ matrix.os }}" = "darwin" ]; then | |
| ln -sf ${{ matrix.libkrunfw_file }} libkrunfw.dylib | |
| else | |
| ln -sf ${{ matrix.libkrunfw_file }} libkrunfw.so.${{ env.LIBKRUNFW_ABI }} | |
| ln -sf libkrunfw.so.${{ env.LIBKRUNFW_ABI }} libkrunfw.so | |
| fi | |
| - name: Build Python SDK (editable) | |
| working-directory: sdk/python | |
| run: uv run maturin develop --release | |
| - name: Test Python SDK | |
| working-directory: sdk/python | |
| run: uv run pytest | |
| - name: Lint Python SDK (ruff) | |
| working-directory: sdk/python | |
| run: uv run ruff check . | |
| - name: Sanity wheel build (Python SDK) | |
| working-directory: sdk/python | |
| run: uv build --wheel | |
| # -- Checks (Go SDK) -- | |
| - uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0 | |
| with: | |
| go-version: stable | |
| # No cache-dependency-path: sdk/go has zero external deps, | |
| # nothing to cache. | |
| cache: false | |
| - name: Build Go SDK | |
| working-directory: sdk/go | |
| run: go build ./... | |
| - name: Vet Go SDK | |
| working-directory: sdk/go | |
| run: go vet ./... | |
| - name: Unit-test Go SDK | |
| working-directory: sdk/go | |
| # Unit tests don't dlopen the FFI lib, so no MICROSANDBOX_FFI_PATH | |
| # needed. Integration tests live under ./integration with the | |
| # `integration` build tag and run in the go-sdk-test job below. | |
| run: go test -count=1 . | |
| # -- Build Go FFI cdylib (linux-x86_64 only, for the integration job) -- | |
| - name: Build microsandbox-go cdylib | |
| if: matrix.target == 'linux-x86_64' | |
| run: | | |
| cargo build -p microsandbox-go | |
| mkdir -p build | |
| cp target/debug/libmicrosandbox_go_ffi.so build/ | |
| # -- Smoke-test the FFI boundary (no KVM needed) -- | |
| # Released SDK builds embed the FFI library; here we use the | |
| # microsandbox_ffi_path build tag to swap the embed for the | |
| # freshly-built local .so. | |
| - name: Smoke-test Go SDK FFI | |
| if: matrix.target == 'linux-x86_64' | |
| working-directory: sdk/go | |
| env: | |
| MICROSANDBOX_FFI_PATH: ${{ github.workspace }}/build/libmicrosandbox_go_ffi.so | |
| run: go test -tags "smoke microsandbox_ffi_path" -count=1 -timeout 2m . | |
| # -- Upload artifacts (linux-x86_64 only, for SDK smoke tests) -- | |
| - name: Upload build artifacts | |
| if: matrix.target == 'linux-x86_64' | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 | |
| with: | |
| name: msb-linux-x86_64 | |
| path: build/ | |
| - name: Upload Node SDK artifacts | |
| if: matrix.target == 'linux-x86_64' | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 | |
| with: | |
| name: node-sdk-linux-x86_64 | |
| path: | | |
| sdk/node-ts/native/index.cjs | |
| sdk/node-ts/native/index.d.ts | |
| sdk/node-ts/native/microsandbox.*.node | |
| sdk/node-ts/dist/ | |
| sdk/node-ts/package.json | |
| sdk/node-ts/package-lock.json | |
| sdk/node-ts/scripts/prune-platform-optional-deps.mjs | |
| sdk/node-ts/tests/ | |
| sdk/node-ts/tsconfig.json | |
| sdk/node-ts/vitest.config.ts | |
| # -- Checks (MCP server) -- | |
| - name: Build MCP server | |
| working-directory: mcp | |
| run: | | |
| node -e " | |
| const fs = require('fs'); | |
| const pkg = JSON.parse(fs.readFileSync('package.json', 'utf8')); | |
| pkg.dependencies.microsandbox = 'file:../sdk/node-ts'; | |
| fs.writeFileSync('package.json', JSON.stringify(pkg, null, 2)); | |
| " | |
| npm install --no-package-lock --ignore-scripts | |
| npm run build | |
| # --------------------------------------------------------------------------- | |
| # Windows build/check only. | |
| # | |
| # These jobs verify the WHP host targets compile on both Windows architectures. | |
| # VM smoke and integration coverage intentionally stays Linux/KVM-only below. | |
| # --------------------------------------------------------------------------- | |
| windows-check: | |
| name: Check Windows (${{ matrix.target }}) | |
| needs: [build-kernel, build-kernel-x86_64, build-agentd-aarch64, build-agentd-x86_64, changes] | |
| if: always() && needs.changes.outputs.code == 'true' | |
| runs-on: ${{ matrix.runner }} | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - target: windows-aarch64 | |
| runner: windows-11-arm | |
| rust_target: aarch64-pc-windows-msvc | |
| go_arch: arm64 | |
| go_cc: clang | |
| kernel_artifact: kernel-c-aarch64 | |
| agentd_artifact: agentd-aarch64-linux-musl | |
| vs_arch: arm64 | |
| vs_host_arch: arm64 | |
| - target: windows-x86_64 | |
| runner: windows-latest | |
| rust_target: x86_64-pc-windows-msvc | |
| go_arch: amd64 | |
| go_cc: clang -fuse-ld=lld | |
| kernel_artifact: kernel-c-x86_64 | |
| agentd_artifact: agentd-x86_64-linux-musl | |
| vs_arch: amd64 | |
| vs_host_arch: amd64 | |
| steps: | |
| - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| submodules: true | |
| - uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable | |
| with: | |
| components: clippy, rustfmt | |
| targets: ${{ matrix.rust_target }} | |
| - uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2 | |
| with: | |
| cache-bin: false | |
| - name: Download kernel.c | |
| uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 | |
| with: | |
| name: ${{ matrix.kernel_artifact }} | |
| path: vendor/libkrunfw/ | |
| - name: Download agentd | |
| uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 | |
| with: | |
| name: ${{ matrix.agentd_artifact }} | |
| path: build/ | |
| - name: Build libkrunfw.dll | |
| shell: pwsh | |
| run: | | |
| $ErrorActionPreference = "Stop" | |
| & .\vendor\libkrunfw\scripts\build-windows.ps1 ` | |
| -SkipKernelBundle ` | |
| -AbiVersion ${{ env.LIBKRUNFW_ABI }} ` | |
| -Architecture ${{ matrix.vs_arch }} ` | |
| -HostArchitecture ${{ matrix.vs_host_arch }} ` | |
| -Output libkrunfw.dll ` | |
| -ImportLibrary libkrunfw.lib | |
| New-Item -ItemType Directory -Force -Path build | Out-Null | |
| Copy-Item vendor\libkrunfw\libkrunfw.dll build\libkrunfw.dll -Force | |
| - name: Format | |
| shell: pwsh | |
| run: cargo +stable fmt --all -- --check | |
| - name: Check msb | |
| shell: pwsh | |
| run: | | |
| $ErrorActionPreference = "Stop" | |
| . "$env:GITHUB_WORKSPACE\vendor\libkrunfw\scripts\msvc-env.ps1" | |
| Set-MsvcEnvironment -Architecture ${{ matrix.vs_arch }} -HostArchitecture ${{ matrix.vs_host_arch }} | |
| cargo +stable check --no-default-features --features net,ssh -p microsandbox-cli --target ${{ matrix.rust_target }} | |
| - name: Clippy msb | |
| shell: pwsh | |
| run: | | |
| $ErrorActionPreference = "Stop" | |
| . "$env:GITHUB_WORKSPACE\vendor\libkrunfw\scripts\msvc-env.ps1" | |
| Set-MsvcEnvironment -Architecture ${{ matrix.vs_arch }} -HostArchitecture ${{ matrix.vs_host_arch }} | |
| cargo +stable clippy --no-default-features --features net,ssh -p microsandbox-cli --target ${{ matrix.rust_target }} -- -D warnings | |
| - name: Test bind rootfs backend | |
| shell: pwsh | |
| run: | | |
| $ErrorActionPreference = "Stop" | |
| . "$env:GITHUB_WORKSPACE\vendor\libkrunfw\scripts\msvc-env.ps1" | |
| Set-MsvcEnvironment -Architecture ${{ matrix.vs_arch }} -HostArchitecture ${{ matrix.vs_host_arch }} | |
| cargo +stable test --no-default-features --features net -p microsandbox-runtime --lib --target ${{ matrix.rust_target }} test_bind_rootfs_backend_exposes_host_file_and_init | |
| - name: Build msb | |
| shell: pwsh | |
| env: | |
| RUSTFLAGS: -C target-feature=+crt-static | |
| run: | | |
| $ErrorActionPreference = "Stop" | |
| . "$env:GITHUB_WORKSPACE\vendor\libkrunfw\scripts\msvc-env.ps1" | |
| Set-MsvcEnvironment -Architecture ${{ matrix.vs_arch }} -HostArchitecture ${{ matrix.vs_host_arch }} | |
| cargo +stable build --release --no-default-features --features net,ssh -p microsandbox-cli --target ${{ matrix.rust_target }} | |
| - name: Build Go FFI cdylib | |
| shell: pwsh | |
| env: | |
| RUSTFLAGS: -C target-feature=+crt-static | |
| run: | | |
| $ErrorActionPreference = "Stop" | |
| . "$env:GITHUB_WORKSPACE\vendor\libkrunfw\scripts\msvc-env.ps1" | |
| Set-MsvcEnvironment -Architecture ${{ matrix.vs_arch }} -HostArchitecture ${{ matrix.vs_host_arch }} | |
| cargo +stable build --release -p microsandbox-go --target ${{ matrix.rust_target }} | |
| - uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0 | |
| with: | |
| go-version: stable | |
| cache: false | |
| - name: Build and test Go SDK | |
| shell: pwsh | |
| working-directory: sdk/go | |
| env: | |
| CC: ${{ matrix.go_cc }} | |
| CGO_ENABLED: "1" | |
| GOARCH: ${{ matrix.go_arch }} | |
| GOOS: windows | |
| run: | | |
| $ErrorActionPreference = "Stop" | |
| . "$env:GITHUB_WORKSPACE\vendor\libkrunfw\scripts\msvc-env.ps1" | |
| Set-MsvcEnvironment -Architecture ${{ matrix.vs_arch }} -HostArchitecture ${{ matrix.vs_host_arch }} | |
| go build ./... | |
| go test -count=1 . | |
| # --------------------------------------------------------------------------- | |
| # CLI smoke tests (requires KVM) | |
| # | |
| # Runs black-box CLI user flows against the freshly-built msb artifact. | |
| # Keep these below the SDK layer so runtime/libkrun regressions fail with a | |
| # direct signal before SDK packaging enters the picture. | |
| # --------------------------------------------------------------------------- | |
| cli-smoke-test: | |
| name: CLI Smoke Tests | |
| needs: [check, changes] | |
| if: needs.changes.outputs.code == 'true' | |
| runs-on: self-hosted-ubuntu-2404-x64 | |
| # Bound a wedged run so it can't squat a shared runner for the 6h default. | |
| timeout-minutes: 45 | |
| # The self-hosted box has 32 cores shared by several runners. Uncapped cargo | |
| # (-j defaults to ncpu) lets concurrent jobs oversubscribe the CPU ~4x and | |
| # starve microVM boots past the 180s agent-relay deadline (flaky | |
| # "timed out waiting for agent relay"). Cap per-job build parallelism so | |
| # several jobs can build at once without crushing VM boot latency. | |
| env: | |
| CARGO_BUILD_JOBS: "12" | |
| steps: | |
| - name: Clean workspace | |
| run: | | |
| rm -rf "${{ github.workspace }}"/build | |
| rm -rf ~/.microsandbox | |
| - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| - name: Clean runner disk | |
| run: scripts/ci/clean-runner-disk.sh | |
| - name: Download build artifacts | |
| uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 | |
| with: | |
| name: msb-linux-x86_64 | |
| path: build/ | |
| - name: Run CLI smoke tests | |
| run: | | |
| chmod +x build/msb | |
| scripts/smoke/cli/image-archive.sh | |
| scripts/smoke/cli/split-irqchip-bind-net.sh | |
| - name: Disk usage | |
| if: always() | |
| run: scripts/ci/clean-runner-disk.sh | |
| # --------------------------------------------------------------------------- | |
| # Integration tests (requires KVM) | |
| # --------------------------------------------------------------------------- | |
| integration-test: | |
| name: Integration Tests | |
| needs: [check, changes, cli-smoke-test] | |
| if: needs.changes.outputs.code == 'true' | |
| runs-on: self-hosted-ubuntu-2404-x64 | |
| # Bound a wedged run so it can't squat a shared runner for the 6h default. | |
| timeout-minutes: 45 | |
| # The self-hosted box has 32 cores shared by several runners. Uncapped cargo | |
| # (-j defaults to ncpu) lets concurrent jobs oversubscribe the CPU ~4x and | |
| # starve microVM boots past the 180s agent-relay deadline (flaky | |
| # "timed out waiting for agent relay"). Cap per-job build parallelism so | |
| # several jobs can build at once without crushing VM boot latency. | |
| env: | |
| CARGO_BUILD_JOBS: "12" | |
| # Full debuginfo for the dozen-plus integration-test binaries is | |
| # ~14 GiB of target/ and has filled the shared runner disk mid-link, | |
| # killing rust-lld with SIGBUS (#1162). line-tables-only keeps | |
| # file:line in backtraces — all CI needs — at a fraction of the size. | |
| CARGO_PROFILE_DEV_DEBUG: "line-tables-only" | |
| CARGO_PROFILE_TEST_DEBUG: "line-tables-only" | |
| steps: | |
| - name: Clean workspace | |
| run: | | |
| rm -rf "${{ github.workspace }}"/{build} | |
| rm -rf ~/.microsandbox | |
| - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| submodules: true | |
| - name: Clean runner disk | |
| run: scripts/ci/clean-runner-disk.sh | |
| - uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable | |
| - uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2 | |
| with: | |
| cache-bin: false | |
| - uses: taiki-e/install-action@67729d5c413db75907f0ad1e39bb04b9c868ff60 # v2 | |
| with: | |
| tool: cargo-nextest | |
| # -- Download pre-built artifacts -- | |
| - name: Download build artifacts | |
| uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 | |
| with: | |
| name: msb-linux-x86_64 | |
| path: build/ | |
| # -- Install msb + libkrunfw -- | |
| - name: Install msb | |
| run: | | |
| chmod +x build/msb | |
| mkdir -p ~/.microsandbox/bin ~/.microsandbox/lib | |
| install -m755 build/msb ~/.microsandbox/bin/msb | |
| install -m644 build/libkrunfw.so.${{ env.LIBKRUNFW_VERSION }} ~/.microsandbox/lib/ | |
| ln -sf libkrunfw.so.${{ env.LIBKRUNFW_VERSION }} ~/.microsandbox/lib/libkrunfw.so.${{ env.LIBKRUNFW_ABI }} | |
| ln -sf libkrunfw.so.${{ env.LIBKRUNFW_ABI }} ~/.microsandbox/lib/libkrunfw.so | |
| # -- Build deps (mirrors the Linux install in the check job) -- | |
| - name: Install build deps | |
| run: sudo apt-get update && sudo apt-get install -y musl-tools libcap-ng-dev gcc make flex bison libelf-dev bc python3-pyelftools | |
| - name: Build agentd | |
| run: | | |
| rustup target add x86_64-unknown-linux-musl | |
| cargo build --release --manifest-path crates/agentd/Cargo.toml --target x86_64-unknown-linux-musl | |
| cp target/x86_64-unknown-linux-musl/release/agentd build/agentd | |
| # -- Run integration tests -- | |
| # MSB_TEST_ISOLATE_HOME=1 turns on per-test ~/.microsandbox isolation | |
| # (see crates/test-utils), so tests avoid sqlite/image-cache contention. | |
| # Run the VM integration suite serially on the shared self-hosted KVM | |
| # runner; overlapping microVM boots and stdin-heavy exec tests can | |
| # intermittently lose relay/session readiness under CI load. | |
| - name: Run integration tests | |
| env: | |
| MSB_TEST_ISOLATE_HOME: "1" | |
| run: | | |
| export PATH="$HOME/.microsandbox/bin:$PATH" | |
| export LD_LIBRARY_PATH="${{ github.workspace }}/build:$HOME/.microsandbox/lib" | |
| # Functional VM tests deliberately create multiple writable-root sandboxes. Give this | |
| # dedicated runner a stable admission pool so unrelated tests do not depend on its | |
| # momentary MemAvailable-derived pool; Auto still exercises the shipping 1536 MiB | |
| # per-disk controller and the normal host-global admission path. | |
| integration_config="$RUNNER_TEMP/msb-integration-config.json" | |
| printf '%s\n' '{"runtime":{"block_writeback":{"mode":"auto","pool_mib":4096}}}' > "$integration_config" | |
| export MSB_CONFIG_PATH="$integration_config" | |
| cargo nextest run -p microsandbox --tests --run-ignored=only --test-threads 1 | |
| - name: Disk usage | |
| if: always() | |
| run: scripts/ci/clean-runner-disk.sh | |
| # --------------------------------------------------------------------------- | |
| # Node.js SDK smoke tests (requires KVM) | |
| # | |
| # Runs the smoke suite under both Node and Bun. The two are sequential | |
| # in one job so they don't fight over the workspace on the self-hosted | |
| # runner. | |
| # | |
| # No `~/.microsandbox` install: the SDK uses its bundled platform-pkg | |
| # binaries. We patch in the freshly-built msb + libkrunfw so the test | |
| # exercises current code, not the lagged published binary. With no home | |
| # fallback, the bridge is the only path msb can reach native — under Bun | |
| # pre-fix, sandbox creation fails clean instead of being silently masked. | |
| # --------------------------------------------------------------------------- | |
| node-sdk-test: | |
| name: Node.js SDK Tests | |
| needs: [check, changes, integration-test] | |
| if: needs.changes.outputs.code == 'true' | |
| runs-on: self-hosted-ubuntu-2404-x64 | |
| # Bound a wedged run so it can't squat a shared runner for the 6h default. | |
| timeout-minutes: 45 | |
| # The self-hosted box has 32 cores shared by several runners. Uncapped cargo | |
| # (-j defaults to ncpu) lets concurrent jobs oversubscribe the CPU ~4x and | |
| # starve microVM boots past the 180s agent-relay deadline (flaky | |
| # "timed out waiting for agent relay"). Cap per-job build parallelism so | |
| # several jobs can build at once without crushing VM boot latency. | |
| env: | |
| CARGO_BUILD_JOBS: "12" | |
| steps: | |
| - name: Clean workspace | |
| run: | | |
| rm -rf "${{ github.workspace }}"/{sdk,build} | |
| rm -rf ~/.microsandbox | |
| - name: Clean runner disk | |
| run: | | |
| set -euo pipefail | |
| df -hT / /tmp "${GITHUB_WORKSPACE}" "${RUNNER_WORKSPACE}" || true | |
| rm -rf "${GITHUB_WORKSPACE}"/{sdk,build,target} | |
| rm -rf ~/.microsandbox | |
| find /tmp -mindepth 1 -maxdepth 1 -type d \ | |
| \( -name 'msb-*' -o -name 'TestSandbox*' -o -name 'go-build*' \) \ | |
| -mmin +120 -exec rm -rf {} + 2>/dev/null || true | |
| find /tmp -mindepth 1 -maxdepth 1 -type d \ | |
| \( -name 'codex-*' -o -name 'microsandbox-*' -o -name 'libkrun-*' \) \ | |
| -mmin +360 -exec rm -rf {} + 2>/dev/null || true | |
| find "${RUNNER_WORKSPACE}" -mindepth 1 -maxdepth 1 -type d \ | |
| -name 'microsandbox*' -mmin +360 -exec rm -rf {} + 2>/dev/null || true | |
| df -hT / /tmp "${GITHUB_WORKSPACE}" "${RUNNER_WORKSPACE}" || true | |
| - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 | |
| with: | |
| node-version: 22 | |
| - name: Download build artifacts | |
| uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 | |
| with: | |
| name: msb-linux-x86_64 | |
| path: build/ | |
| - name: Download Node SDK artifacts | |
| uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 | |
| with: | |
| name: node-sdk-linux-x86_64 | |
| path: sdk/node-ts/ | |
| - name: Install Node.js dependencies | |
| working-directory: sdk/node-ts | |
| run: | | |
| node scripts/prune-platform-optional-deps.mjs | |
| npm install --package-lock=false --ignore-scripts | |
| # The published platform-pkg msb may lag the SDK; replace it with the | |
| # freshly-built binaries so the smoke test runs against current code. | |
| # Release-bump PRs can reference platform package versions that are not | |
| # published yet, so synthesize the package layout before patching it. | |
| - name: Use fresh runtime binaries in platform package | |
| working-directory: sdk/node-ts | |
| run: | | |
| PKG=node_modules/@superradcompany/microsandbox-linux-x64-gnu | |
| mkdir -p "$PKG/bin" "$PKG/lib" | |
| node - <<'NODE' | |
| const fs = require("node:fs"); | |
| const pkgName = "@superradcompany/microsandbox-linux-x64-gnu"; | |
| const root = JSON.parse(fs.readFileSync("package.json", "utf8")); | |
| const version = root.optionalDependencies?.[pkgName] ?? root.version; | |
| fs.writeFileSync( | |
| "node_modules/@superradcompany/microsandbox-linux-x64-gnu/package.json", | |
| `${JSON.stringify({ | |
| name: pkgName, | |
| version, | |
| main: "microsandbox.linux-x64-gnu.node", | |
| os: ["linux"], | |
| cpu: ["x64"], | |
| libc: ["glibc"], | |
| license: "Apache-2.0", | |
| engines: { node: ">= 22" }, | |
| }, null, 2)}\n`, | |
| ); | |
| NODE | |
| cp native/microsandbox.linux-x64-gnu.node "$PKG/" | |
| chmod +x ${{ github.workspace }}/build/msb | |
| install -m755 ${{ github.workspace }}/build/msb "$PKG/bin/msb" | |
| rm -f "$PKG"/lib/libkrunfw* | |
| cp -P ${{ github.workspace }}/build/libkrunfw.so* "$PKG/lib/" | |
| - name: Run SDK tests (Node) | |
| working-directory: sdk/node-ts | |
| # Linux unix-socket paths are 108 bytes — anchor MSB_HOME under | |
| # /tmp with a cleanup-friendly prefix so sandboxes/<long-name>/runtime/agent.sock fits. | |
| run: | | |
| MSB_HOME=$(mktemp -d -p /tmp msb-node-XXXXXX) | |
| trap "rm -rf '$MSB_HOME'" EXIT | |
| export MSB_HOME | |
| npm test | |
| # setup-bun downloads a zipped release; unzip isn't preinstalled on | |
| # the self-hosted runner. | |
| - name: Install unzip | |
| run: | | |
| if command -v unzip >/dev/null 2>&1; then | |
| exit 0 | |
| fi | |
| for attempt in {1..10}; do | |
| if sudo apt-get update && sudo apt-get install -y unzip; then | |
| exit 0 | |
| fi | |
| echo "apt-get install unzip failed on attempt ${attempt}; retrying..." | |
| sleep 10 | |
| done | |
| exit 1 | |
| - uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2 | |
| - name: Run SDK tests (Bun) | |
| working-directory: sdk/node-ts | |
| # Linux unix-socket paths are 108 bytes — anchor MSB_HOME under | |
| # /tmp with a cleanup-friendly prefix so sandboxes/<long-name>/runtime/agent.sock fits. | |
| run: | | |
| MSB_HOME=$(mktemp -d -p /tmp msb-node-XXXXXX) | |
| trap "rm -rf '$MSB_HOME'" EXIT | |
| export MSB_HOME | |
| bunx --bun vitest run | |
| - name: Disk usage | |
| if: always() | |
| run: | | |
| df -hT / /tmp "${GITHUB_WORKSPACE}" "${RUNNER_WORKSPACE}" || true | |
| du -xhd1 /tmp 2>/dev/null | sort -h | tail -30 || true | |
| # --------------------------------------------------------------------------- | |
| # Python SDK integration tests (requires KVM) | |
| # | |
| # Downloads the pre-built msb + libkrunfw from the `check` job, then builds | |
| # the Python extension locally and runs the integration suite against those | |
| # fresh runtime binaries. | |
| # --------------------------------------------------------------------------- | |
| python-sdk-test: | |
| name: Python SDK Tests | |
| needs: [check, changes, node-sdk-test] | |
| if: needs.changes.outputs.code == 'true' | |
| runs-on: self-hosted-ubuntu-2404-x64 | |
| # Bound a wedged run so it can't squat a shared runner for the 6h default. | |
| timeout-minutes: 45 | |
| # The self-hosted box has 32 cores shared by several runners. Uncapped cargo | |
| # (-j defaults to ncpu) lets concurrent jobs oversubscribe the CPU ~4x and | |
| # starve microVM boots past the 180s agent-relay deadline (flaky | |
| # "timed out waiting for agent relay"). Cap per-job build parallelism so | |
| # several jobs can build at once without crushing VM boot latency. | |
| env: | |
| CARGO_BUILD_JOBS: "12" | |
| steps: | |
| - name: Clean workspace | |
| run: | | |
| rm -rf "${{ github.workspace }}"/{build} | |
| rm -rf ~/.microsandbox | |
| - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| - name: Clean runner disk | |
| run: scripts/ci/clean-runner-disk.sh | |
| - uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable | |
| - uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2 | |
| with: | |
| cache-bin: false | |
| - uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0 | |
| with: | |
| enable-cache: true | |
| cache-dependency-glob: "sdk/python/uv.lock" | |
| - name: Download build artifacts | |
| uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 | |
| with: | |
| name: msb-linux-x86_64 | |
| path: build/ | |
| - name: Stage runtime bundle | |
| run: | | |
| chmod +x build/msb | |
| mkdir -p sdk/python/microsandbox/_bundled/bin | |
| mkdir -p sdk/python/microsandbox/_bundled/lib | |
| cp build/msb sdk/python/microsandbox/_bundled/bin/ | |
| cp build/libkrunfw.so.${{ env.LIBKRUNFW_VERSION }} sdk/python/microsandbox/_bundled/lib/ | |
| cd sdk/python/microsandbox/_bundled/lib | |
| ln -sf libkrunfw.so.${{ env.LIBKRUNFW_VERSION }} libkrunfw.so.${{ env.LIBKRUNFW_ABI }} | |
| ln -sf libkrunfw.so.${{ env.LIBKRUNFW_ABI }} libkrunfw.so | |
| - name: Sync Python dev environment | |
| working-directory: sdk/python | |
| run: uv sync --group dev | |
| - name: Build Python SDK (editable) | |
| working-directory: sdk/python | |
| run: uv run maturin develop --release | |
| - name: Run Python integration tests | |
| working-directory: sdk/python | |
| env: | |
| MSB_PATH: ${{ github.workspace }}/build/msb | |
| LD_LIBRARY_PATH: ${{ github.workspace }}/build:${{ github.workspace }}/sdk/python/microsandbox/_bundled/lib | |
| run: | | |
| MSB_HOME=$(mktemp -d -p /tmp msb-python-XXXXXX) | |
| trap "rm -rf '$MSB_HOME'" EXIT | |
| export MSB_HOME | |
| uv run pytest integration | |
| - name: Disk usage | |
| if: always() | |
| run: scripts/ci/clean-runner-disk.sh | |
| # --------------------------------------------------------------------------- | |
| # Python SDK lower-bound check (Python 3.10) | |
| # | |
| # Every other Python job runs uv unpinned, so it always resolves a modern | |
| # interpreter and never exercises the declared floor in pyproject.toml | |
| # (requires-python = ">=3.10"). That let 3.11-only code ship unimportable | |
| # on 3.10 (#1153). This job pins uv to 3.10 and runs the unit tests, so | |
| # the support claim stays tested until the floor is raised. | |
| # --------------------------------------------------------------------------- | |
| python-sdk-lower-bound: | |
| name: Python SDK (3.10 lower bound) | |
| needs: [check, changes] | |
| if: needs.changes.outputs.code == 'true' | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 45 | |
| steps: | |
| - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| - uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable | |
| - uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2 | |
| with: | |
| cache-bin: false | |
| - uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0 | |
| with: | |
| enable-cache: true | |
| cache-dependency-glob: "sdk/python/uv.lock" | |
| python-version: "3.10" | |
| # The sdk/rust build script provisions msb + libkrunfw during the | |
| # maturin build. Between a libkrunfw version bump and the next | |
| # release its fallback (downloading the released PREBUILT_VERSION | |
| # bundle) ships the older libkrunfw and fails on Linux, so feed | |
| # its CI escape hatch the locally built bundle from `check`, like | |
| # the other SDK jobs do. | |
| - name: Download build artifacts | |
| uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 | |
| with: | |
| name: msb-linux-x86_64 | |
| path: build/ | |
| # microsandbox-runtime links against libcap-ng; GitHub-hosted | |
| # runners don't ship the dev package. | |
| - name: Install system dependencies | |
| run: sudo apt-get update && sudo apt-get install -y libcap-ng-dev | |
| - name: Sync Python dev environment | |
| working-directory: sdk/python | |
| run: uv sync --group dev | |
| # Guard against the pin silently not applying — an unpinned resolve | |
| # is exactly the failure mode this job exists to prevent. | |
| - name: Verify interpreter is 3.10 | |
| working-directory: sdk/python | |
| run: uv run python -c "import sys; assert sys.version_info[:2] == (3, 10), sys.version" | |
| - name: Build Python SDK (editable) | |
| working-directory: sdk/python | |
| run: uv run maturin develop --release | |
| # No runtime bundle is staged here; test_runtime_binary skips without | |
| # it. Bundle-dependent behavior is covered by `check` on a modern | |
| # interpreter — this job only guards the interpreter floor. | |
| - name: Test Python SDK | |
| working-directory: sdk/python | |
| run: uv run pytest | |
| # --------------------------------------------------------------------------- | |
| # Go SDK integration tests (requires KVM) | |
| # | |
| # Downloads the pre-built msb + libkrunfw + libmicrosandbox_go_ffi.so from | |
| # the `check` job, then runs `go test -tags integration ./integration/...`. | |
| # Mirrors the node-sdk-test pattern. | |
| # --------------------------------------------------------------------------- | |
| go-sdk-test: | |
| name: Go SDK Tests | |
| needs: [check, changes, python-sdk-test] | |
| if: needs.changes.outputs.code == 'true' | |
| runs-on: self-hosted-ubuntu-2404-x64 | |
| # Bound a wedged run so it can't squat a shared runner for the 6h default. | |
| timeout-minutes: 45 | |
| # The self-hosted box has 32 cores shared by several runners. Uncapped cargo | |
| # (-j defaults to ncpu) lets concurrent jobs oversubscribe the CPU ~4x and | |
| # starve microVM boots past the 180s agent-relay deadline (flaky | |
| # "timed out waiting for agent relay"). Cap per-job build parallelism so | |
| # several jobs can build at once without crushing VM boot latency. | |
| env: | |
| CARGO_BUILD_JOBS: "12" | |
| steps: | |
| - name: Clean workspace | |
| run: | | |
| rm -rf "${{ github.workspace }}"/build | |
| rm -rf ~/.microsandbox | |
| - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| - name: Clean runner disk | |
| run: scripts/ci/clean-runner-disk.sh | |
| - uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0 | |
| with: | |
| go-version: stable | |
| # No cache-dependency-path: sdk/go has zero external deps, | |
| # nothing to cache. | |
| cache: false | |
| # -- Download pre-built artifacts (msb + libkrunfw + cdylib all in build/) -- | |
| - name: Download build artifacts | |
| uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 | |
| with: | |
| name: msb-linux-x86_64 | |
| path: build/ | |
| # -- Install msb + libkrunfw -- | |
| - name: Install msb | |
| run: | | |
| chmod +x build/msb | |
| mkdir -p ~/.microsandbox/bin ~/.microsandbox/lib | |
| install -m755 build/msb ~/.microsandbox/bin/msb | |
| install -m644 build/libkrunfw.so.${{ env.LIBKRUNFW_VERSION }} ~/.microsandbox/lib/ | |
| ln -sf libkrunfw.so.${{ env.LIBKRUNFW_VERSION }} ~/.microsandbox/lib/libkrunfw.so.${{ env.LIBKRUNFW_ABI }} | |
| ln -sf libkrunfw.so.${{ env.LIBKRUNFW_ABI }} ~/.microsandbox/lib/libkrunfw.so | |
| # -- Run integration tests -- | |
| - name: Run Go integration tests | |
| working-directory: sdk/go | |
| env: | |
| # SDK builds embed the FFI; the microsandbox_ffi_path build tag | |
| # swaps the embed for a reader of this env var so we test | |
| # against the freshly-built local .so. | |
| MICROSANDBOX_FFI_PATH: ${{ github.workspace }}/build/libmicrosandbox_go_ffi.so | |
| # Force the SDK to spawn the freshly-built msb (mirrors node-sdk-test | |
| # reasoning: avoid running against a stale bundled binary). | |
| MSB_PATH: ${{ github.workspace }}/build/msb | |
| # Linux unix-socket paths are 108 bytes — anchor MSB_HOME under | |
| # /tmp with a cleanup-friendly prefix so sandboxes/<long-name>/runtime/agent.sock fits. | |
| run: | | |
| MSB_HOME=$(mktemp -d -p /tmp msb-go-XXXXXX) | |
| trap "rm -rf '$MSB_HOME'" EXIT | |
| export MSB_HOME | |
| export PATH="$HOME/.microsandbox/bin:$PATH" | |
| export LD_LIBRARY_PATH="${{ github.workspace }}/build:$HOME/.microsandbox/lib" | |
| status=0 | |
| go test -tags "integration microsandbox_ffi_path" -count=1 -timeout 45m ./integration/... || status=$? | |
| if [ "$status" -ne 0 ]; then | |
| echo "::group::Go sandbox runtime logs without core.ready" | |
| find "$MSB_HOME/sandboxes" -path '*/logs/runtime.log' -type f -print0 2>/dev/null \ | |
| | while IFS= read -r -d '' log; do | |
| if ! grep -q 'agent relay: received core.ready' "$log"; then | |
| echo "--- $log" | |
| tail -120 "$log" || true | |
| fi | |
| done | |
| echo "::endgroup::" | |
| fi | |
| exit "$status" | |
| - name: Disk usage | |
| if: always() | |
| run: scripts/ci/clean-runner-disk.sh | |
| # --------------------------------------------------------------------------- | |
| # Aggregator: a single status check that always reports, regardless of | |
| # whether the matrix jobs ran. Branch protection requires only this job, | |
| # so docs-only PRs (where the matrix is skipped) still satisfy the gate. | |
| # --------------------------------------------------------------------------- | |
| summary: | |
| name: Check Summary | |
| if: always() | |
| needs: | |
| - changes | |
| - build-kernel | |
| - build-kernel-x86_64 | |
| - build-agentd-aarch64 | |
| - build-agentd-x86_64 | |
| - check | |
| - windows-check | |
| - cli-smoke-test | |
| - integration-test | |
| - node-sdk-test | |
| - python-sdk-test | |
| - python-sdk-lower-bound | |
| - go-sdk-test | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Aggregate results | |
| run: | | |
| results='${{ toJson(needs.*.result) }}' | |
| echo "needs results: $results" | |
| if echo "$results" | grep -qE '"failure"|"cancelled"'; then | |
| echo "::error::A required job failed or was cancelled" | |
| exit 1 | |
| fi | |
| echo "All required jobs passed or were skipped" |