Merge pull request #212 from PhysShell/claude/lab-boundary-context-re… #341
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
| # The gate AGENTS.md already documents — format, lint, test, doc — enforced. | |
| # Until now nothing ran `cargo clippy -D warnings` or `cargo test --workspace` | |
| # in CI, so lint regressions landed on `main` unnoticed (14 of them in the | |
| # cockpit alone). The wasm render is checked separately by cockpit-web-test. | |
| # | |
| # `fuzz/` is a nightly, non-member crate (ADR-0010), so `--workspace` never | |
| # reaches it; the `fuzz` job below is its gate — the crate sat silently | |
| # broken from S16 Phase 2 until Phase 3's final slice tried to compile it, | |
| # which is the whole argument for a blocking gate in one anecdote. | |
| name: ci | |
| on: | |
| pull_request: | |
| push: | |
| branches: [main] | |
| permissions: | |
| contents: read | |
| env: | |
| CARGO_TERM_COLOR: always | |
| jobs: | |
| check: | |
| runs-on: ubuntu-latest | |
| steps: | |
| # persist-credentials: false — later steps compile and run PR-authored | |
| # code (build scripts, tests), so don't leave the token in .git/config | |
| # for them to read (zizmor: artipacked). | |
| - uses: actions/checkout@v4 | |
| with: | |
| persist-credentials: false | |
| # rust-toolchain.toml pins the channel and pulls in rustfmt + clippy. | |
| - name: Show toolchain | |
| run: rustc --version && cargo clippy --version && cargo fmt --version | |
| - name: Cache cargo | |
| uses: actions/cache@v4 | |
| with: | |
| path: | | |
| ~/.cargo/registry | |
| ~/.cargo/git | |
| target | |
| key: ci-${{ hashFiles('Cargo.lock', '**/Cargo.toml') }} | |
| # eframe needs a windowing/GL stack to *link* the cockpit's native target. | |
| - name: Install native deps | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y libgtk-3-dev libxcb-render0-dev libxcb-shape0-dev \ | |
| libxcb-xfixes0-dev libxkbcommon-dev libssl-dev libasound2-dev | |
| - name: Format | |
| run: cargo fmt --all --check | |
| - name: Lint | |
| run: cargo clippy --workspace --all-targets -- -D warnings | |
| - name: Test | |
| run: cargo test --workspace | |
| # Not yet `-D warnings`: rustdoc flags five pre-existing findings in | |
| # griff-core (an unresolved `AtomRest` link, public docs linking to | |
| # private items). Deny once those are cleared. | |
| - name: Doc | |
| run: cargo doc --no-deps --workspace | |
| # The MSRV is a promise; build on it or it rots. It sat at 1.74 for a year | |
| # while egui/eframe 0.34 already demanded 1.92 — nobody on 1.74 could have | |
| # built the cockpit. | |
| msrv: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| persist-credentials: false | |
| - name: Read the MSRV from the workspace manifest | |
| id: msrv | |
| run: | | |
| v=$(grep -m1 -E '^rust-version' Cargo.toml | grep -oE '[0-9]+\.[0-9]+(\.[0-9]+)?') | |
| echo "version=$v" >> "$GITHUB_OUTPUT" | |
| echo "workspace MSRV: $v" | |
| - name: Install the MSRV toolchain | |
| run: rustup toolchain install ${{ steps.msrv.outputs.version }} --profile minimal | |
| - name: Cache cargo | |
| uses: actions/cache@v4 | |
| with: | |
| path: | | |
| ~/.cargo/registry | |
| ~/.cargo/git | |
| target | |
| key: msrv-${{ steps.msrv.outputs.version }}-${{ hashFiles('Cargo.lock') }} | |
| - name: Install native deps | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y libgtk-3-dev libxcb-render0-dev libxcb-shape0-dev \ | |
| libxcb-xfixes0-dev libxkbcommon-dev libssl-dev libasound2-dev | |
| - name: Build on the MSRV | |
| run: cargo +${{ steps.msrv.outputs.version }} check --workspace --all-targets | |
| # ADR-0010 / docs/fuzzing.md: bounded smoke fuzz plus a replay of the | |
| # committed corpus is a *blocking* PR gate (~60 s per implemented target, | |
| # matrixed so wall-clock stays one target's worth). libFuzzer enforces the | |
| # no-hang / no-unbounded-alloc half of the oracle via -timeout and the | |
| # memory limits; the asserts in each target enforce the rest. | |
| fuzz: | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 25 | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| target: | |
| - midi_import | |
| - midi_roundtrip | |
| - semantic_diff | |
| - score_projection | |
| - guitar_pro_import | |
| - phrase_boundary | |
| - generation_request | |
| - complement_request | |
| - structure_metrics | |
| - gesture_request | |
| - swang_parse | |
| - pattern_expansion | |
| include: | |
| # F-003 (docs/fuzzing.md): guitarpro-0.4.2 indexes measure headers | |
| # by an unvalidated direction index — a panic inside the upstream | |
| # crate that no adapter-side pre-validation can reach. Quarantined | |
| # to signature-check only, *visibly*, with exit criteria in the | |
| # findings registry: an upstream fix or a vendored patch turns the | |
| # smoke back on. | |
| - target: guitar_pro_import | |
| smoke: skip | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| persist-credentials: false | |
| # fuzz/rust-toolchain.toml pins nightly for the crate itself; the | |
| # explicit install keeps the first `cargo +nightly` from surprising us. | |
| - name: Install nightly | |
| run: rustup toolchain install nightly --profile minimal -c rustfmt -c clippy | |
| - name: Cache cargo | |
| uses: actions/cache@v4 | |
| with: | |
| path: | | |
| ~/.cargo/registry | |
| ~/.cargo/git | |
| ~/.cargo/bin | |
| fuzz/target | |
| key: fuzz-${{ matrix.target }}-${{ hashFiles('fuzz/Cargo.toml', 'Cargo.lock') }} | |
| - name: Install cargo-fuzz | |
| run: command -v cargo-fuzz || cargo install cargo-fuzz --locked | |
| # The signatures rot first (see the job comment): a plain check under | |
| # the nightly pin catches API drift even before the smoke runs. | |
| - name: Signatures stay compiled | |
| working-directory: fuzz | |
| run: cargo check --bins | |
| - name: Bounded smoke + corpus replay | |
| if: matrix.smoke != 'skip' | |
| run: | | |
| mkdir -p fuzz/corpus/${{ matrix.target }} | |
| cargo +nightly fuzz run ${{ matrix.target }} -- \ | |
| -max_total_time=60 -timeout=60 -rss_limit_mb=4096 -malloc_limit_mb=2048 | |
| # A finding nobody can download is a finding nobody can minimize: keep | |
| # the crashing inputs when the smoke fails. | |
| - name: Keep any finding | |
| if: failure() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: fuzz-artifacts-${{ matrix.target }} | |
| path: fuzz/artifacts/ | |
| if-no-files-found: ignore |