#!/usr/bin/env bash # Lumbridge CI. # # scripts/ci.sh headless and UI # scripts/ci.sh --headless everything except the GPUI product # scripts/ci.sh --ui only the GPUI product and its fixture # # The split exists because the UI crates pull GPUI's dependency tree — several # hundred packages and a large target directory — while the headless crates # build in seconds. A contributor changing lumbridge-core should not wait for a # window toolkit, and a CI runner that cannot carry the UI job can still gate # everything else. set -euo pipefail run_headless=1 run_ui=1 case "${1:-}" in --headless) run_ui=0 ;; --ui) run_headless=0 ;; "") ;; *) echo "usage: $0 [--headless|--ui]" >&2; exit 2 ;; esac # The UI crates. Excluded from the headless pass by name so a new crate is # headless by default rather than silently joining the slow job. ui_packages=(lumbridge lumbridge-ui-fixture) # In CI a missing tool is a failure, not a warning. Locally it stays a warning so # a contributor without cargo-deny is not blocked. The difference matters: the # licence closure DISTRIBUTION.md depends on was, until this flag existed, being # skipped on a runner that had never installed cargo-deny -- and reported green. # Set LUMBRIDGE_CI_STRICT=1 (the workflow does) to require every gate to run. strict="${LUMBRIDGE_CI_STRICT:-0}" require_tool() { command -v "$1" >/dev/null 2>&1 && return 0 if [ "$strict" = 1 ]; then echo "$1 is required when LUMBRIDGE_CI_STRICT=1 and is not installed" >&2 exit 1 fi return 1 } # Structural gates that need no compiler: crate membership, and the pinned UI # dependency. First, because they cost milliseconds and catch the failure that # makes every later gate meaningless -- code that is silently not being built. "$(dirname "$0")/workspace-guard.sh" cargo fmt --all --check # The product's licence closure and its source allowlist. Graduating GPUI into # the workspace made both the product's problem rather than a spike's; deny.toml # records which licences were reviewed and which Git sources are permitted. # # `sources` is checked here for the first time. It had been declared in deny.toml # and never run, which is why nobody noticed it was failing. if require_tool cargo-deny; then cargo deny check licenses sources else echo "cargo-deny not installed; skipping the licence and source gates (cargo install cargo-deny)" >&2 fi test_runner() { if require_tool cargo-nextest; then cargo nextest run "$@" --all-features --profile "${NEXTEST_PROFILE:-default}" else echo "cargo-nextest not installed; using cargo test" >&2 cargo test "$@" --all-features fi } if [ "$run_headless" = 1 ]; then exclusions=() for package in "${ui_packages[@]}"; do exclusions+=(--exclude "$package") done cargo clippy --workspace "${exclusions[@]}" --all-targets --all-features -- -D warnings test_runner --workspace "${exclusions[@]}" # nextest deliberately does not run doctests on stable Rust. cargo test --workspace "${exclusions[@]}" --all-features --doc fi if [ "$run_ui" = 1 ]; then # shellcheck source=/dev/null . "$(dirname "$0")/native-libs.sh" selections=() for package in "${ui_packages[@]}"; do selections+=(-p "$package") done cargo clippy "${selections[@]}" --all-targets --all-features -- -D warnings test_runner "${selections[@]}" cargo test "${selections[@]}" --all-features --doc fi