Files
komorebi/tools/fast-check
T

132 lines
6.3 KiB
Bash
Executable File

#!/usr/bin/env bash
# fast-check: run only the minimal checks for the current jj change.
# Run from anywhere inside a jj workspace of the repository. Never commits, never pushes.
# See tools/README.md.
set -uo pipefail
S="${FAST_CHECK_SCRATCH:-${XDG_CACHE_HOME:-$HOME/.cache}/komorebi-fast-check}"
HERE="$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")"
FROM=""
LIST=0
SELF="$(readlink -f "${BASH_SOURCE[0]}")"
usage() {
cat <<'USAGE'
usage: fast-check [--list] [--range | --since REV] [--help]
--list dry run: print the checks that would run
--range diff trunk()..@ instead of just @
--since REV diff REV..@ (REV is a jj revset, e.g. wip-a3b)
Env: FAST_CHECK_SCRATCH base dir for the persistent target dirs (default: ${XDG_CACHE_HOME:-~/.cache}/komorebi-fast-check)
USAGE
}
# Evaluation-only nix check, attribute level: `nix flake show` (about 9 s, 0.4 GB) and the drvPath of one check
# and one package of each platform (the Windows, Linux and macOS groups of the one root flake). `nix flake check
# --no-build` forces every check of every system (up to 28 GB RSS for 5 minutes with --all-systems) and fails
# without .git anyway (decision D9). Not caught here: an error inside a check's derivation body; the
# pre-landing `nix build` of the check still catches that.
nix_eval() {
systemd-run --user --scope -q -p MemoryMax=6G nice -n 19 nix flake show >/dev/null || return 1
for a in checks.x86_64-linux.windows-clippy checks.x86_64-linux.linux-clippy checks.aarch64-darwin.macos-clippy \
packages.x86_64-linux.windows-komorebic packages.x86_64-linux.komorebic packages.aarch64-darwin.komorebic; do
systemd-run --user --scope -q -p MemoryMax=6G nice -n 19 nix eval --raw ".#$a.drvPath" >/dev/null || return 1
done
}
while [ $# -gt 0 ]; do
case "$1" in
--list) LIST=1 ;;
--range) FROM='trunk()' ;;
--nix-eval) nix_eval; exit $? ;;
--since) shift; FROM="${1:?--since needs a revset}" ;;
-h | --help) usage; exit 0 ;;
*) usage >&2; exit 2 ;;
esac
shift
done
ROOT="$(jj root 2>/dev/null)" || { echo "fast-check: not in a jj workspace" >&2; exit 2; }
cd "$ROOT" || exit 2
if [ -n "$FROM" ]; then
FILES="$(jj diff --name-only --from "$FROM" --to @)" || exit 2
else
FILES="$(jj diff --name-only -r @)" || exit 2
fi
want_kde=0 want_mac=0 want_win=0 want_native=0 want_nix=0
unclassified=()
while IFS= read -r f; do
[ -z "$f" ] && continue
case "$f" in
flake.nix | flake.lock | nix/* | *.nix) want_nix=1 ;;
# the files the Rust sources include or read, before the docs are ignored
docs/linux/komorebi.example.json | docs/linux/skhdrc.sample | schemas/linux/*) want_kde=1 ;;
docs/macos/*.json | docs/macos/*.sample | docs/macos/cli/* | schemas/macos/*) want_mac=1 ;;
docs/*.json | docs/*.sample | schemas/windows/*) want_win=1 ;;
Cargo.toml | Cargo.lock | .cargo/* | rust-toolchain.toml | rustfmt.toml | deny.toml) want_win=1; want_kde=1; want_mac=1 ;;
# the platform crates and the crates of one set, before the `crates/*` catch-all
crates/komorebi-layouts/* | crates/komorebi-scrolling/*) want_native=1; want_win=1 ;;
crates/komorebi-linux/* | crates/komorebi-hotkeys/* | scripts/linux/*) want_kde=1 ;;
crates/komorebi-macos/*) want_mac=1 ;;
crates/komorebi-windows/* | crates/komorebi-themes/* | crates/komorebi-e2e-agent/* | crates/komorebi-testwin/*) want_win=1 ;;
komorebic/src/linux* | komorebic/tests/linux_* | crates/komorebi-client/src/linux.rs | crates/komorebi-client/tests/linux_* | komorebi/tests/linux_*) want_kde=1 ;;
komorebic/src/macos* | crates/komorebi-client/src/macos.rs | komorebi-bar/src/macos*) want_mac=1 ;;
crates/komorebi-client/*) want_win=1; want_kde=1; want_mac=1 ;;
crates/*) want_native=1; want_kde=1; want_mac=1; want_win=1 ;;
komorebi-bar/*) want_win=1; want_mac=1 ;;
komorebi/* | komorebic/*) want_win=1; want_kde=1; want_mac=1 ;;
*.md | docs/* | tools/* | LICENSE* | .github/* | *.png | *.jpg | *.gif) ;;
komorebi-gui/* | komorebi-shortcuts/* | komorebic-no-console/* | e2e/*)
want_win=1 ;;
*) unclassified+=("$f") ;;
esac
done <<<"$FILES"
NAMES=() DIRS=() CMDS=()
add() { NAMES+=("$1"); DIRS+=("$2"); CMDS+=("$3"); }
if [ "$want_native" = 1 ]; then
add "native: shared crates tests" "." \
"CARGO_TARGET_DIR=$S/target-fast-native nix shell nixpkgs#gcc -c cargo test --locked -p komorebi-layouts -p komorebi-scrolling"
fi
if [ "$want_win" = 1 ]; then
# a bare cargo command builds default-members (the Windows crates) of the one workspace
add "windows: clippy --all-targets -D warnings (dev shell, cross)" "." \
"CARGO_TARGET_DIR=$S/target-fast-win nix develop --command cargo clippy --locked --all-targets -- -D warnings"
fi
if [ "$want_kde" = 1 ]; then
add "kde: cargo check + lib tests (komorebi-linux)" "." \
"export CARGO_TARGET_DIR=$S/kde-target COMMIT_HASH=\${COMMIT_HASH:-dev}; nix shell nixpkgs#gcc -c bash -c 'cargo check --locked -p komorebi-linux && cargo check --locked -p komorebi && cargo test --locked -p komorebi-linux --lib && cargo test --locked -p komorebi-linux --test schemas -- --test-threads=1'"
fi
if [ "$want_mac" = 1 ]; then
add "macos: type-check only (fake CC, cannot link)" "." \
"export CARGO_TARGET_DIR=$S/target-fast-mac COMMIT_HASH=\${COMMIT_HASH:-dev} CC_aarch64_apple_darwin=$HERE/cc-fake.sh AR_aarch64_apple_darwin=ar; PKG_CONFIG_PATH=\$(nix build --no-link --print-out-paths nixpkgs#openssl.dev)/lib/pkgconfig; export PKG_CONFIG_PATH; nix shell nixpkgs#gcc nixpkgs#pkg-config nixpkgs#openssl.dev -c cargo check --locked --target aarch64-apple-darwin -p komorebi -p komorebi-macos -p komorebic -p komorebi-client -p komorebi-bar --all-targets"
fi
if [ "$want_nix" = 1 ]; then
add "nix: root flake evaluation only (flake show and the drvPath of one check and package per platform)" "." "$SELF --nix-eval"
fi
if [ "${#unclassified[@]}" -gt 0 ]; then
echo "fast-check: unclassified (no check): ${unclassified[*]}"
fi
if [ "${#NAMES[@]}" -eq 0 ]; then
echo "fast-check: nothing to run for this diff"
exit 0
fi
fail=0
for i in "${!NAMES[@]}"; do
if [ "$LIST" = 1 ]; then
echo "[list] ${NAMES[$i]} (cd ${DIRS[$i]}; ${CMDS[$i]})"
continue
fi
echo "==> ${NAMES[$i]}"
start=$SECONDS
(cd "${DIRS[$i]}" && bash -c "${CMDS[$i]}")
rc=$?
el=$((SECONDS - start))
if [ $rc -eq 0 ]; then echo "<== PASS ${NAMES[$i]} (${el}s)"; else echo "<== FAIL ${NAMES[$i]} (${el}s, exit $rc)"; fail=1; fi
done
exit $fail