name: CI on: push: branches: [main] pull_request: env: CARGO_TERM_COLOR: always RUSTFLAGS: "-D warnings" jobs: fmt: name: Format runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@stable with: components: rustfmt - run: cargo fmt --all --check clippy: name: Lint (${{ matrix.lua }}) runs-on: ubuntu-latest strategy: fail-fast: false matrix: # mlua's Lua-flavor features are mutually exclusive, so we can't # use --all-features. Run clippy under each supported flavor. lua: [luajit, lua54] steps: - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@stable with: components: clippy - uses: Swatinem/rust-cache@v2 - run: cargo clippy --all-targets --no-default-features --features ${{ matrix.lua }} -- -D warnings # pmacs-gpu is Lua-flavor-independent (it depends on pmacs-protocol, # not pmacs), so the root-package clippy above never lints it. Lint # it explicitly or its warnings slip through CI (audit F-001). - run: cargo clippy -p pmacs-gpu --all-targets -- -D warnings gpu-render: name: GPU Render (headless) runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@stable - uses: Swatinem/rust-cache@v2 # The headless render harness (audit F-014) needs a Vulkan adapter; # the runner has no GPU, so install the mesa software rasterizer # (lavapipe). This job also runs pmacs-gpu's other tests, which the # workspace test job (root package only) never executes. - name: Install lavapipe (Vulkan software rasterizer) run: | sudo apt-get update sudo apt-get install -y mesa-vulkan-drivers vulkan-tools - name: Confirm a Vulkan adapter is present run: | ls -la /usr/share/vulkan/icd.d/ || true vulkaninfo --summary || true - name: pmacs-gpu tests (render harness included) env: # Force the Vulkan backend so wgpu uses lavapipe. Do NOT set # VK_ICD_FILENAMES — the loader's default ICD discovery already # finds lavapipe (vulkaninfo above proves it), and pinning a # path that doesn't match the runner hides every ICD. The # PMACS_REQUIRE_GPU guard turns a missing adapter into a hard # failure so a broken setup can't pass as a silent skip. WGPU_BACKEND: vulkan LIBGL_ALWAYS_SOFTWARE: "1" PMACS_REQUIRE_GPU: "1" run: cargo test -p pmacs-gpu -- --test-threads=1 test: name: Test (${{ matrix.os }} / ${{ matrix.lua }}) runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: os: [ubuntu-latest, macos-latest] lua: [luajit, lua54] steps: - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@stable - uses: Swatinem/rust-cache@v2 - run: cargo build --all-targets --no-default-features --features ${{ matrix.lua }} # Several acceptance binaries spawn real daemon / PTY child # processes. Keep the harness serial so macOS runners do not # expose cross-test process lifecycle races that are unrelated # to the behavior under test. - run: cargo test --all-targets --no-default-features --features ${{ matrix.lua }} -- --test-threads=1 - run: cargo test --doc --no-default-features --features ${{ matrix.lua }} # The workspace default member is only the root `pmacs` package, so # the runs above never execute pmacs-protocol's own tests — the # shared wire format (encode/decode, transport framing) the daemon, # TUI, and GPU all depend on. Run them explicitly (Lua-flavor # independent, so once is enough; runs on every matrix leg cheaply # off the shared cache). - run: cargo test -p pmacs-protocol --all-targets acceptance: name: M1 Acceptance Gates runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@stable - uses: Swatinem/rust-cache@v2 - name: perf, memory, and 30s fuzz gates run: cargo test --release --test acceptance -- --ignored --nocapture --test-threads=1 m4-perf-gates: name: M4 Perf Gates runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@stable - uses: Swatinem/rust-cache@v2 - name: tree-sitter parse + highlight latency budgets run: cargo test --release --test m4_acceptance -- --ignored --nocapture --test-threads=1 # m5-perf-gates: luajit-only by design. # The keystroke-to-render gate measures protocol-path latency (Unix # socket frontend ↔ daemon RTT plus the daemon's keymap-dispatch / # buffer-mutate / repaint pipeline). Lua flavor is irrelevant — the # measured path doesn't enter the Lua VM. Matrixing over flavors # doubles CI cost without adding signal. If a future perf gate # measures Lua-touching code paths (command dispatch via Lua, # hook invocation), revisit then. m5-perf-gates: name: M5 Perf Gates runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@stable - uses: Swatinem/rust-cache@v2 - name: keystroke-to-render p99 over loopback LocalSocket run: cargo test --release --test m5_perf_acceptance -- --ignored --nocapture # m6-perf-gates: luajit-only by design. The M6.6/M6.7 gates measure # rope-append throughput, RSS ceiling, cancel-response latency, # scrollback navigation latency, and scrollback search latency — # none of which exercise the Lua VM's hot path differently across # flavors. Same reasoning as m5-perf-gates above. # # --test-threads=1 is required: the M6.6 RSS-ceiling gate samples # process-wide /proc/self/status, and concurrent ingest / scrollback # populate from sibling tests inflate that reading. Serializing # gives each test a clean baseline. The wall-clock cost of serial # execution (~5 minutes) is acceptable for a perf-gates job that # only runs on push/PR. m6-perf-gates: name: M6 Perf Gates runs-on: ubuntu-latest timeout-minutes: 15 steps: - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@stable - uses: Swatinem/rust-cache@v2 - name: ingest rate, RSS ceiling, cancel p99, navigation p99, search p99 env: # Full cancel profile remains the test default. Hosted CI has # an effective five-minute ceiling for this job and variable # PTY throughput, so keep the per-PR profile short and stable. PMACS_M6_INGEST_MIN_BYTES_PER_SEC: "67108864" PMACS_M6_CANCEL_TRIALS: "30" PMACS_M6_CANCEL_MAX_DELAY_MS: "500" run: cargo test --release --test m6_perf_acceptance -- --ignored --nocapture --test-threads=1