#!/bin/bash # ============================================================================ # Run only the tests related to files changed vs HEAD (staged, unstaged and # untracked). Quiet: failures plus a one-line summary. Falls back to the full # suite when a change cannot be mapped to tests. Generated by repo_contract. # ============================================================================ set -euo pipefail cd "$(git rev-parse --show-toplevel)" CHANGED=() while IFS= read -r f; do [[ -n "$f" && -e "$f" ]] && CHANGED+=("$f") done < <({ git diff --name-only HEAD 2>/dev/null || true; git ls-files --others --exclude-standard; } | sort -u) # --no-cov: a subset cannot meet the 100% bar, and the term-missing table is noise. pytest_run() { local py=python3 [[ -x .venv/bin/python ]] && py=.venv/bin/python "$py" -m pytest --no-cov -p no:sugar "$@" } # Dart changes map to app/test/_test.dart; any other app/ change runs the app suite. flutter_run() { (cd app && flutter test --reporter=compact "$@") } if grep -qs testmon pyproject.toml requirements*.txt; then pytest_run --testmon -q --tb=short; exit $? fi full=0 tests=() dart_tests=() dart_full=0 for f in "${CHANGED[@]}"; do case "$f" in */conftest.py | conftest.py | pyproject.toml | requirements*.txt | pytest.ini | setup.cfg) full=1 ;; app/test/*_test.dart) dart_tests+=("${f#app/}") ;; app/lib/*.dart) base="$(basename "$f" .dart)" while IFS= read -r t; do dart_tests+=("${t#app/}"); done \ < <(git ls-files "app/test/*${base}_test.dart") [[ ${#dart_tests[@]} -eq 0 ]] && dart_full=1 ;; app/pubspec.yaml | app/pubspec.lock) dart_full=1 ;; *.py) base="$(basename "$f" .py)" if [[ "$base" == test_* || "$base" == *_test ]]; then tests+=("$f") else while IFS= read -r t; do tests+=("$t"); done \ < <(git ls-files "*test_${base}.py" "*${base}_test.py") fi ;; esac done if [[ ${#CHANGED[@]} -eq 0 ]]; then echo "no changes vs HEAD: nothing to test"; exit 0; fi rc=0 if [[ $dart_full -eq 1 ]]; then flutter_run || rc=1 elif [[ ${#dart_tests[@]} -gt 0 ]]; then flutter_run "${dart_tests[@]}" || rc=1; fi if [[ $full -eq 1 ]]; then echo "config changed: running full python suite"; pytest_run -q -n auto || rc=1 elif [[ ${#tests[@]} -gt 0 ]]; then pytest_run -q --tb=short "${tests[@]}" || rc=1 elif printf '%s\n' "${CHANGED[@]}" | grep -q '\.py$'; then echo "no mapped python tests: running full python suite"; pytest_run -q -n auto --tb=short || rc=1 elif [[ $dart_full -eq 0 && ${#dart_tests[@]} -eq 0 ]]; then echo "no python/dart changes: nothing to test" fi exit "$rc"