#!/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) tests=() for f in "${CHANGED[@]}"; do case "$f" in tests/*.bats | test/*.bats) tests+=("$f") ;; tests/test_*.sh | test/test_*.sh) tests+=("$f") ;; *.sh) base="$(basename "$f" .sh)" for cand in "tests/${base}.bats" "test/${base}.bats" "tests/test_${base}.sh"; do [[ -f "$cand" ]] && tests+=("$cand") done ;; esac done run_tests() { local rc=0 out for t in "$@"; do if [[ "$t" == *.bats ]]; then out="$(bats -F tap "$t" 2>&1)" || rc=1 else out="$(bash "$t" 2>&1)" || rc=1; fi grep -v '^ok ' <<<"$out" | grep -v '^1\.\.' || true done echo "ran ${#} test file(s): $([[ $rc -eq 0 ]] && echo pass || echo FAIL)" return "$rc" } if [[ ${#CHANGED[@]} -eq 0 ]]; then echo "no changes vs HEAD: nothing to test"; exit 0; fi if [[ ${#tests[@]} -gt 0 ]]; then run_tests "${tests[@]}"; exit $?; fi mapfile -t all < <(git ls-files 'tests/*.bats' 'test/*.bats' 'tests/test_*.sh' 'test/test_*.sh') if [[ ${#all[@]} -eq 0 ]]; then echo "no shell tests found"; exit 1; fi echo "no mapped tests: running full suite" run_tests "${all[@]}"