name: CI on: push: branches: [main] pull_request: branches: [main] env: ZIG_VERSION: "0.16.0" NODE_VERSION: "24" jobs: test: runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v4 - name: Set up Zig uses: mlugg/setup-zig@v2 with: version: ${{ env.ZIG_VERSION }} - name: Run test suite (unit + hermetic loopback integration) run: zig build test -Dintegration frontend: runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v4 - name: Set up Node uses: actions/setup-node@v4 with: node-version: ${{ env.NODE_VERSION }} cache: npm cache-dependency-path: web/package-lock.json - name: Install dependencies working-directory: web run: npm ci - name: Check formatting working-directory: web run: npm run format:check - name: Lint working-directory: web run: npm run lint - name: Typecheck working-directory: web run: npm run typecheck - name: Run tests working-directory: web run: npm test - name: Build working-directory: web run: npm run build cross: runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v4 - name: Set up Zig uses: mlugg/setup-zig@v2 with: version: ${{ env.ZIG_VERSION }} - name: Set up Node uses: actions/setup-node@v4 with: node-version: ${{ env.NODE_VERSION }} cache: npm cache-dependency-path: web/package-lock.json - name: Build the web UI working-directory: web run: | npm ci npm run build # ReleaseSafe because the < 15 MB budget (PLAN §18) is for release # binaries; a Debug build strips to ~25 MB and can never meet it. - name: Build static musl executables run: zig build cross -Dweb-dist=web/dist -Doptimize=ReleaseSafe - name: Install file(1) and strip tooling run: | missing="" command -v file >/dev/null 2>&1 || missing="$missing file" command -v objcopy >/dev/null 2>&1 || missing="$missing binutils" command -v aarch64-linux-gnu-objcopy >/dev/null 2>&1 || missing="$missing binutils-aarch64-linux-gnu" if [ -n "$missing" ]; then sudo apt-get update -qq sudo apt-get install -qq -y $missing fi # The size budget applies to stripped binaries (PLAN §18) and # `zig build cross` does not strip, so the assert measures a # stripped copy and leaves the built artifact untouched. - name: Assert executables are statically linked and within the size budget run: | set -euo pipefail size_limit=$((15 * 1024 * 1024)) for triple in x86_64-linux-musl aarch64-linux-musl; do binary="zig-out/cross/$triple/nxdns" if [ ! -f "$binary" ]; then echo "missing executable: $binary" exit 1 fi description=$(file -b "$binary") echo "$triple: $description" case "$description" in *"statically linked"*) ;; *) echo "not statically linked: $binary" exit 1 ;; esac case "$triple" in x86_64-*) strip_tool=objcopy ;; aarch64-*) strip_tool=aarch64-linux-gnu-objcopy ;; esac "$strip_tool" --strip-all "$binary" "$binary.stripped" size=$(stat -c %s "$binary.stripped") echo "$triple: stripped size $size bytes" if [ "$size" -ge "$size_limit" ]; then echo "stripped executable exceeds the 15 MB budget: $binary" exit 1 fi done