# Gate every pull request into `main` on the checks this repository already had # and nobody ran automatically. # # Phases 1 and 3 both wrote `cargo fmt`, `cargo clippy -D warnings` and a test # suite, and both ran them BY HAND from a workstation. That is the whole gap # this file closes: a guard nothing invokes is a guard whose state nobody knows, # and the repository that gets released had nothing gating it at all. # # Adapted from RunicGateway/installer's pr-checks.yml, which is the other Rust # crate in this project and already solved the toolchain-on-a-shared-runner # problem. Two differences, both because of where the crate sits: # # • The crate is in `sidecar/`, not at the repo root, so every cargo step runs # with that working directory and the cache key reads that lockfile. # • There is no "does a crate exist yet" detection. The installer needed it # because its CI landed before its code; here the code came first. # # Enforcement (one-time, in the Gitea UI): # Repository Settings → Branches → Branch Protection (rule for `main`) # • Enable Status Check # • Status check patterns: PR Checks / * # Gitea only lists a context in its dropdown after it has reported once, so let # this run on one PR first; the glob matches without the dropdown and keeps # matching as jobs are added. # # Scope note: `edge` is gated as well as `main` though this repo has no `edge` # branch. Multi-phase work lands there first everywhere else in this project, and # gating only the `main` hop would run these checks for the first time at the # cutover — the one moment a red build is most expensive to find. name: PR Checks on: pull_request: branches: [main, edge] concurrency: group: pr-checks-${{ github.ref }} cancel-in-progress: true jobs: rust-gates: runs-on: ubuntu-latest timeout-minutes: 30 defaults: run: working-directory: sidecar steps: - uses: actions/checkout@v4 # One job runs all three gates on purpose: installing the toolchain costs # far more than the checks do, so splitting fmt/clippy/test into parallel # jobs would pay that cost three times for no wall-clock win. - name: Install Rust toolchain (rustfmt + clippy) run: | set -euo pipefail SUDO=""; [ "$(id -u)" -ne 0 ] && SUDO="sudo" $SUDO apt-get update $SUDO apt-get install -y --no-install-recommends \ build-essential curl ca-certificates git if ! command -v cargo >/dev/null 2>&1; then curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs \ | sh -s -- -y --profile minimal --default-toolchain stable fi echo "${HOME}/.cargo/bin" >> "$GITHUB_PATH" export PATH="${HOME}/.cargo/bin:${PATH}" rustup component add rustfmt clippy cargo --version && cargo fmt --version && cargo clippy --version # Keyed on Cargo.lock: dependency builds are reused until a dep actually # changes. A cache miss only makes the run slower, never wrong. - name: Cache cargo registry and build dir uses: actions/cache@v4 with: path: | ~/.cargo/registry ~/.cargo/git sidecar/target key: ${{ runner.os }}-cargo-${{ hashFiles('sidecar/Cargo.lock') }} restore-keys: | ${{ runner.os }}-cargo- # Cheapest gate first — parses only, no compile, so a formatting slip fails # in seconds instead of after a full build. - name: cargo fmt --check run: cargo fmt --check # --all-targets covers the tests too, which is where most of this crate's # interesting code is. -D warnings makes a lint a failure, so the crate # starts clean at this bar and anything new is a regression from the PR. - name: cargo clippy run: cargo clippy --locked --all-targets -- -D warnings # --locked also proves Cargo.lock is in sync with Cargo.toml rather than # letting the build silently update it. - name: cargo test run: cargo test --locked