Files
2026-08-27 21:09:14 +00:00

192 lines
6.6 KiB
YAML

name: Rust lints
permissions:
contents: read
on:
workflow_dispatch:
pull_request:
paths:
- "src/**/*.rs"
- "src/**/Cargo.toml"
- "src/**/*.classes.ts"
- "src/codegen/**"
- "scripts/build/**"
- "scripts/build.ts"
- "scripts/rust-miri.ts"
- "package.json"
- "Cargo.toml"
- "Cargo.lock"
- "clippy.toml"
- "dylint.toml"
- "mordant-baseline.toml"
- "rust-toolchain.toml"
- ".github/workflows/rust-lints.yml"
- ".github/actions/rust-lint-setup/**"
- ".github/actions/setup-bun/**"
- ".github/rust-matcher.json"
merge_group:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
env:
BUN_VERSION: "1.3.14"
LLVM_VERSION_MAJOR: "21"
# Pin the toolchain explicitly so rustup ignores rust-toolchain.toml's
# `targets` list (11 cross triples ≈ 450 MB of prebuilt std we don't need
# to lint the host). Keep in sync with `channel` in rust-toolchain.toml.
RUSTUP_TOOLCHAIN: nightly-2026-07-20
jobs:
clippy:
name: cargo clippy
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Setup
uses: ./.github/actions/rust-lint-setup
with:
bun-version: ${{ env.BUN_VERSION }}
llvm-version: ${{ env.LLVM_VERSION_MAJOR }}
toolchain: ${{ env.RUSTUP_TOOLCHAIN }}
components: clippy
ninja-targets: codegen clone-lolhtml
- name: cargo clippy
env:
BUN_CODEGEN_DIR: ${{ github.workspace }}/build/debug/codegen
run: bun run rust:clippy
miri:
name: cargo miri test
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Setup
uses: ./.github/actions/rust-lint-setup
with:
bun-version: ${{ env.BUN_VERSION }}
llvm-version: ${{ env.LLVM_VERSION_MAJOR }}
toolchain: ${{ env.RUSTUP_TOOLCHAIN }}
components: miri rust-src
- name: cargo miri test
env:
BUN_CODEGEN_DIR: ${{ github.workspace }}/build/debug/codegen
run: bun run rust:miri
lolhtml:
# The vendored lol-html is a fork (oven-sh/lol-html, `bun` branch) carrying
# content-handler suspension, and its own test suite is the only thing that
# guards the fork's invariants: nothing in the Bun test suite reaches, for
# example, the parser's suspension bookkeeping or `Arena::compact()`.
name: lol-html cargo test
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Setup
uses: ./.github/actions/rust-lint-setup
with:
bun-version: ${{ env.BUN_VERSION }}
llvm-version: ${{ env.LLVM_VERSION_MAJOR }}
toolchain: ${{ env.RUSTUP_TOOLCHAIN }}
- name: cargo test
# `lol_html` is a path dependency, not a workspace member (it carries
# dev-dependencies the Bun workspace does not), so run it in place.
working-directory: vendor/lolhtml
run: cargo test
mordant:
name: mordant
runs-on: ubuntu-latest
if: github.event_name != 'merge_group'
# Advisory while the pack is new: shows up on the PR, does not block it.
continue-on-error: true
env:
DYLINT_VERSION: "6.0.3"
# Mordant (pinned in Cargo.toml's [workspace.metadata.dylint]) is built
# with, and lints us using, the nightly named in its own rust-toolchain
# file, which dylint selects itself; rustup fetches it on demand, so the
# pin is the only thing to bump. The outer cargo just needs to exist:
# point it at the runner's stable so rust-toolchain.toml's cross-target
# list is not installed.
RUSTUP_TOOLCHAIN: stable
RUSTUP_AUTO_INSTALL: "1"
steps:
- name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Setup
uses: ./.github/actions/rust-lint-setup
with:
bun-version: ${{ env.BUN_VERSION }}
llvm-version: ${{ env.LLVM_VERSION_MAJOR }}
ninja-targets: codegen clone-lolhtml
- name: Cache the dylint binaries
# Compiling cargo-dylint and dylint-link is ~100s; they only change on
# a DYLINT_VERSION bump.
id: dylint-bin
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: |
~/.cargo/bin/cargo-dylint
~/.cargo/bin/dylint-link
key: dylint-bin-${{ runner.os }}-${{ env.DYLINT_VERSION }}
- name: Build the dylint binaries
if: steps.dylint-bin.outputs.cache-hit != 'true'
run: cargo install --locked cargo-dylint@"$DYLINT_VERSION" dylint-link@"$DYLINT_VERSION"
- name: Read the mordant pin
# The driver and library dylint builds are tied to the pinned mordant
# revision, so it is their cache key.
id: pin
run: |
rev=$(sed -n 's/.*scarletindustries\/mordant", rev = "\([0-9a-f]*\)".*/\1/p' Cargo.toml)
test -n "$rev"
echo "rev=$rev" >> "$GITHUB_OUTPUT"
- name: Cache the dylint driver and the built mordant library
# Both are a pure function of the dylint version and the pinned
# revision (which names the nightly they are built for): ~50s and
# ~60s of the job. What remains uncached is checking bun itself.
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: |
~/.dylint_drivers
target/dylint/libraries
key: dylint-lib-${{ runner.os }}-${{ env.DYLINT_VERSION }}-${{ steps.pin.outputs.rev }}
- name: mordant
env:
# Mordant's nightly is older than rust-toolchain.toml's, so `#[allow]`s
# of lints added since then are unknown to it.
DYLINT_RUSTFLAGS: "-A unknown_lints"
run: |
rm -f target/mordant/over-baseline.txt
cargo dylint --all --workspace -- --keep-going
- name: Fail on findings over the baseline
# In baseline mode mordant reports findings over mordant-baseline.toml
# as warnings and lists them in this file; absent or empty means clean.
run: test ! -s target/mordant/over-baseline.txt