| name: CI |
| |
| on: |
| pull_request: |
| branches: [main] |
| push: |
| branches: [main] |
| |
| concurrency: |
| group: ci-${{ github.workflow }}-${{ github.ref }} |
| cancel-in-progress: ${{ github.event_name == 'pull_request' }} |
| |
| jobs: |
| typecheck: |
| runs-on: ubuntu-latest |
| steps: |
| - uses: actions/checkout@v4 |
| - uses: actions/setup-node@v4 |
| with: |
| node-version: '24' |
| cache: npm |
| - run: npm ci |
| - run: npm run lint |
| - run: npm run format:check |
| - run: npm run build |
| - run: npm run typecheck |
| # Dead-code / dependency governance. Entry points and reasoned ignores |
| # live in knip.json; both workspaces must stay at zero findings. |
| - name: Knip (apps/desktop) |
| run: npx knip --workspace apps/desktop |
| - name: Knip (packages/ui) |
| run: npx knip --workspace packages/ui |
| |
| test: |
| runs-on: ubuntu-latest |
| steps: |
| - uses: actions/checkout@v4 |
| - uses: actions/setup-node@v4 |
| with: |
| node-version: '24' |
| cache: npm |
| - uses: astral-sh/setup-uv@v6 |
| - name: Install pinned Harbor contract runtime |
| run: | |
| uv tool install "harbor==0.13.2" |
| uv tool dir --bin >> "$GITHUB_PATH" |
| - name: Install Linux runtime dependencies |
| run: sudo apt-get update && sudo apt-get install -y ripgrep bubblewrap |
| # Ubuntu 24.04 hosted runners gate unprivileged user namespaces through |
| # AppArmor, which otherwise makes bwrap fail while configuring loopback. |
| - name: Enable bubblewrap user namespaces |
| run: | |
| if [[ -e /proc/sys/kernel/apparmor_restrict_unprivileged_userns ]]; then |
| sudo sysctl -w kernel.apparmor_restrict_unprivileged_userns=0 |
| fi |
| if [[ -e /proc/sys/kernel/unprivileged_userns_clone ]]; then |
| sudo sysctl -w kernel.unprivileged_userns_clone=1 |
| fi |
| - run: npm ci |
| # build:test skips the renderer bundle (vite); test:dist only consumes |
| # tsc outputs (dist/main + dist/renderer side-files), never the vite |
| # bundle. e2e builds its own renderer in a separate job. |
| - run: npm run build:test |
| - name: Linux sandbox smoke |
| env: |
| MAKA_REQUIRE_LINUX_SANDBOX_SMOKE: '1' |
| run: npm exec -w @maka/runtime -- node --test dist/__tests__/linux-sandbox-smoke.test.js |
| # test:dist runs the suites against the dist just built above. The |
| # workspace `test` scripts each do `clean && build` first, which would |
| # throw away this dist and rebuild every package a second time. |
| - name: Run required test suite |
| env: |
| MAKA_REQUIRE_HARBOR_CONTRACT: '1' |
| run: npm run test:dist |
| |
| e2e: |
| runs-on: ubuntu-latest |
| steps: |
| - uses: actions/checkout@v4 |
| - uses: actions/setup-node@v4 |
| with: |
| node-version: '24' |
| cache: npm |
| - run: npm ci |
| # Electron is a GUI app; on a headless Linux runner it needs a virtual |
| # display. The suite already runs with show:false, but the process still |
| # requires an X server to start. |
| - name: Ensure xvfb |
| run: command -v xvfb-run >/dev/null 2>&1 || { sudo apt-get update && sudo apt-get install -y xvfb; } |
| - name: E2E |
| run: xvfb-run -a npm --workspace @maka/desktop run e2e |
| # Design governance: the CDP alignment auditor walks the e2e-fixture |
| # fixtures and fails on same-type height mismatches, mixed-type |
| # centerline drift, or radius-family splits. Reuses the renderer the |
| # e2e step just built; same xvfb pattern. |
| - name: Alignment audit |
| run: xvfb-run -a node scripts/audit-alignment.mjs |