# Action majors verified 2026-09-07 against # `gh api repos///releases/latest --jq .tag_name`. name: CI on: push: branches: [main] pull_request: env: CARGO_TERM_COLOR: always RUSTFLAGS: -D warnings jobs: test: name: test (${{ matrix.os }}) runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: os: [ubuntu-latest, macos-latest, windows-latest] steps: - uses: actions/checkout@v7 # No toolchain action: `rust-toolchain.toml` names the compiler, and # one that installed `stable` here would be overridden by it anyway. - run: rustup show - uses: Swatinem/rust-cache@v2 - run: cargo test --locked --all-targets lint: name: fmt and clippy runs-on: ubuntu-latest steps: - uses: actions/checkout@v7 - run: rustup show - uses: Swatinem/rust-cache@v2 - run: cargo fmt --all --check - run: cargo clippy --locked --all-targets --all-features deny: name: supply chain runs-on: ubuntu-latest steps: - uses: actions/checkout@v7 - uses: EmbarkStudios/cargo-deny-action@v2 with: command: check # The advisory database moves on its own, so this can fail on an # unchanged tree. That's the point. command-arguments: --deny warnings typos: name: spelling runs-on: ubuntu-latest steps: - uses: actions/checkout@v7 # Reads `typos.toml`, so `locale = "en-us"` applies here too. - uses: crate-ci/typos@v1.51.1 lexicons: name: lexicons runs-on: ubuntu-latest steps: - uses: actions/checkout@v7 - uses: oven-sh/setup-bun@v2 - run: bun install --frozen-lockfile - run: bun run check working-directory: tools/lexicon-check - run: bun run gen --check working-directory: tools/lex-gen prose: name: prose runs-on: ubuntu-latest steps: - uses: actions/checkout@v7 - uses: oven-sh/setup-bun@v2 - run: bun install --frozen-lockfile - run: bun run check working-directory: tools/prose-check scanner: name: scanner on wasm runs-on: ubuntu-latest steps: - uses: actions/checkout@v7 - run: rustup show - uses: Swatinem/rust-cache@v2 - uses: oven-sh/setup-bun@v2 - run: bun install --frozen-lockfile # Reads the committed module beside one built here, so the bytes a # browser is served are what this answers for. Comparing those bytes to # a rebuild is the pre-push hook's job — see `docs/scanner.md`. - run: bun run check working-directory: tools/scanner-check typescript: name: typescript runs-on: ubuntu-latest steps: - uses: actions/checkout@v7 - uses: oven-sh/setup-bun@v2 - run: bun install --frozen-lockfile # One scope for the client and the tools: the tools import the client's # own modules, so a change to those has to typecheck against both. - run: bun run lint - run: bun run types - run: bun test - run: bun run build msrv: name: minimum supported rust version runs-on: ubuntu-latest steps: - uses: actions/checkout@v7 # Read from Cargo.toml so rust-version is the only place the floor lives. - id: msrv run: >- sed -n 's/^rust-version = "\(.*\)"/version=\1/p' Cargo.toml >> "$GITHUB_OUTPUT" - uses: dtolnay/rust-toolchain@stable with: toolchain: ${{ steps.msrv.outputs.version }} - uses: Swatinem/rust-cache@v2 # `+` rather than the default the action set: `rust-toolchain.toml` # beats that, and the floor would go unchecked without a word. - run: cargo +${{ steps.msrv.outputs.version }} check --locked container: name: container runs-on: ubuntu-latest steps: - uses: actions/checkout@v7 - uses: docker/setup-buildx-action@v4 # The slowest job here, and still cheaper than hearing from someone else # that the image never built. It proves the entrypoint, not the service. - uses: docker/build-push-action@v7 with: context: . load: true tags: manaweb:ci cache-from: type=gha cache-to: type=gha,mode=max - run: docker run --rm manaweb:ci version