diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index eb95eec..98097fe 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,10 +1,3 @@ -# The quality gate from AGENTS.md (`cargo xtask ci`: fmt, clippy -D warnings, tests, layers, -# assets, docs, text, demo-check) on every pull request and every push to main, so nothing red -# lands on main and waits for the next session to find it. -# -# One Ubuntu job. The code is portable (one `cfg(windows)` in the tree), the UI tests carry no -# committed golden pictures (docs/testing.md), and the gate is the same command a person runs -# locally, so a second runner would cost minutes without proving anything new. name: CI on: @@ -16,113 +9,137 @@ on: permissions: contents: read -# A newer push to a pull request cancels its older run. Runs on main cancel too: the gate is one -# job, so a cancelled main run is re-run by the next push within minutes. concurrency: group: ci-${{ github.ref }} cancel-in-progress: true +env: + CARGO_TERM_COLOR: always + CARGO_INCREMENTAL: "0" + CARGO_BUILD_JOBS: "2" + CARGO_PROFILE_DEV_DEBUG: "1" + CARGO_PROFILE_TEST_DEBUG: "1" + RUST_BACKTRACE: "1" + jobs: - gate: - name: cargo xtask ci + fmt: + name: fmt runs-on: ubuntu-24.04 - timeout-minutes: 60 - env: - CARGO_TERM_COLOR: always - CARGO_INCREMENTAL: "0" - RUST_BACKTRACE: "1" + timeout-minutes: 20 steps: - # Third-party actions are pinned by commit, as the sibling Craft apps pin them. - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + - name: Install Rust + run: rustup install + - run: cargo fmt --all -- --check - # winit, eframe and rfd need the X11, Wayland and GTK headers. The UI and icon tests render - # through wgpu off screen, so the runner needs a Vulkan driver: mesa-vulkan-drivers brings - # lavapipe, the software one. Without it `Harness::render` fails and the suite fails loudly. + clippy: + name: clippy + runs-on: ubuntu-24.04 + timeout-minutes: 60 + steps: + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: Install Linux build dependencies run: | sudo apt-get update - sudo apt-get install -y --no-install-recommends \ - pkg-config libxkbcommon-dev libwayland-dev libx11-dev libxcursor-dev libxrandr-dev \ - libxi-dev libgtk-3-dev libfontconfig1-dev libfreetype-dev \ - libvulkan1 mesa-vulkan-drivers + sudo apt-get install -y --no-install-recommends pkg-config libxkbcommon-dev libwayland-dev libx11-dev libxcursor-dev libxrandr-dev libxi-dev libgtk-3-dev libfontconfig1-dev libfreetype-dev libvulkan1 mesa-vulkan-drivers + - name: Install Rust + run: rustup install + - uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2 + with: + save-if: ${{ github.ref == 'refs/heads/main' }} + - run: cargo clippy --workspace --all-targets -- -D warnings - # No version named here on purpose: rust-toolchain.toml pins it, with the components it - # needs, and `rustup install` with no arguments installs exactly that. So the runner and a - # person's machine compile with the same Rust, and raising it is a one-line change there. - - name: Install Rust (the version in rust-toolchain.toml) + test: + name: test + runs-on: ubuntu-24.04 + timeout-minutes: 60 + steps: + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + - name: Install Linux build dependencies run: | - rustup install - rustc --version - cargo clippy --version - - # Only main writes the cache. Pull requests read main's, so one pull request cannot push - # another one's entries out of the repository's cache budget. + sudo apt-get update + sudo apt-get install -y --no-install-recommends pkg-config libxkbcommon-dev libwayland-dev libx11-dev libxcursor-dev libxrandr-dev libxi-dev libgtk-3-dev libfontconfig1-dev libfreetype-dev libvulkan1 mesa-vulkan-drivers + - name: Install Rust + run: rustup install - uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2 with: save-if: ${{ github.ref == 'refs/heads/main' }} cache-on-failure: true + - name: Show disk space + run: df -h + - name: Run workspace tests with infrastructure-only retry + shell: bash + run: | + set -o pipefail + set +e + cargo test --workspace 2>&1 | tee cargo-test.log + status=${PIPESTATUS[0]} + set -e + if [[ "$status" -eq 0 ]]; then exit 0; fi + if grep -Eq 'No space left on device|IO failure on output stream|Bus error|signal 7' cargo-test.log; then + echo "Retrying after an infrastructure/resource failure" + cargo test --workspace + exit $? + fi + exit "$status" - # Quality level L3. The branch name is a warning; being up to date with main is the - # repository's "require branches to be up to date" setting. + static: + name: static checks + runs-on: ubuntu-24.04 + timeout-minutes: 30 + steps: + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + - name: Install Rust + run: rustup install - name: Branch check run: cargo xtask check-branch - - - name: PII Scanner + - name: PII scanner run: bash SKILLS/nc-devx/scripts/check-pii.sh + - name: Layers + run: cargo xtask layers + - name: Assets + run: cargo xtask assets + - name: Docs + run: cargo xtask docs + - name: Text + run: cargo xtask text + - name: Demo check + run: cargo xtask demo-check - - name: Quality gate - run: cargo xtask ci - - # Coverage against docs/coverage.json. A drop is a warning on the pull request and a table on - # the run's summary page, never a red mark: the job may fail without failing the workflow, and - # `cargo xtask coverage` itself exits 0 when coverage falls. See docs/testing.md#coverage. coverage: name: coverage (warns, never blocks) runs-on: ubuntu-24.04 timeout-minutes: 60 continue-on-error: true - env: - CARGO_TERM_COLOR: always - CARGO_INCREMENTAL: "0" steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - - name: Install Linux build dependencies run: | sudo apt-get update - sudo apt-get install -y --no-install-recommends \ - pkg-config libxkbcommon-dev libwayland-dev libx11-dev libxcursor-dev libxrandr-dev \ - libxi-dev libgtk-3-dev libfontconfig1-dev libfreetype-dev \ - libvulkan1 mesa-vulkan-drivers - + sudo apt-get install -y --no-install-recommends pkg-config libxkbcommon-dev libwayland-dev libx11-dev libxcursor-dev libxrandr-dev libxi-dev libgtk-3-dev libfontconfig1-dev libfreetype-dev libvulkan1 mesa-vulkan-drivers - name: Install Rust and cargo-llvm-cov run: | rustup install rustup component add llvm-tools cargo install cargo-llvm-cov --locked --version 0.9.1 - - uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2 with: key: coverage save-if: ${{ github.ref == 'refs/heads/main' }} + - name: Show disk space + run: df -h + - run: cargo xtask coverage - - name: Coverage compared with docs/coverage.json - run: cargo xtask coverage - - # Report overall CI status to branch protection. The gate and coverage jobs both complete, - # but GitHub's branch protection rule requires a top-level "CI" status check. This job - # depends on both and reports overall success, so the branch protection check passes once - # all CI work is done (whether coverage passed its own checks or not, per its continue-on-error). ci-status: name: CI runs-on: ubuntu-latest - needs: [gate, coverage] + needs: [fmt, clippy, test, static, coverage] if: always() steps: - name: Check CI result run: | - if [[ "${{ needs.gate.result }}" == "failure" ]]; then - echo "❌ Quality gate failed" + if [[ "${{ needs.fmt.result }}" == "failure" || "${{ needs.clippy.result }}" == "failure" || "${{ needs.test.result }}" == "failure" || "${{ needs.static.result }}" == "failure" ]]; then + echo "Quality checks failed" exit 1 fi - echo "✅ CI checks passed" + echo "CI checks passed"