Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
147 changes: 82 additions & 65 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -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:
Expand All @@ -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"
Loading