| 1 |
#!/usr/bin/env bash |
| 2 |
# Mirror the Ubuntu per-package coverage gates from `.github/workflows/ci.yml`. |
| 3 |
# |
| 4 |
# Usage: |
| 5 |
# ./scripts/coverage-gates.sh |
| 6 |
# ./scripts/coverage-gates.sh --list |
| 7 |
# ./scripts/coverage-gates.sh --only lock --only export |
| 8 |
# |
| 9 |
# Best match with CI: |
| 10 |
# uv sync --all-extras --dev |
| 11 |
|
| 12 |
set -euo pipefail |
| 13 |
|
| 14 |
cd "$(git rev-parse --show-toplevel)" |
| 15 |
export UV_CACHE_DIR="${UV_CACHE_DIR:-.uv-cache}" |
| 16 |
|
| 17 |
show_list=0 |
| 18 |
selected=() |
| 19 |
|
| 20 |
while [[ $# -gt 0 ]]; do |
| 21 |
case "$1" in |
| 22 |
--list) |
| 23 |
show_list=1 |
| 24 |
;; |
| 25 |
--only) |
| 26 |
shift |
| 27 |
if [[ $# -eq 0 ]]; then |
| 28 |
echo "error: --only requires a gate name" >&2 |
| 29 |
exit 2 |
| 30 |
fi |
| 31 |
selected+=("$1") |
| 32 |
;; |
| 33 |
*) |
| 34 |
echo "usage: ./scripts/coverage-gates.sh [--list] [--only <gate>]..." >&2 |
| 35 |
exit 2 |
| 36 |
;; |
| 37 |
esac |
| 38 |
shift |
| 39 |
done |
| 40 |
|
| 41 |
gates=( |
| 42 |
"doc|tests/unit/doc|src/dlm/doc" |
| 43 |
"store|tests/unit/store|src/dlm/store" |
| 44 |
"hardware|tests/unit/hardware|src/dlm/hardware" |
| 45 |
"base_models|tests/unit/base_models|src/dlm/base_models" |
| 46 |
"data|tests/unit/data|src/dlm/data" |
| 47 |
"replay|tests/unit/replay|src/dlm/replay" |
| 48 |
"train|tests/unit/train|src/dlm/train" |
| 49 |
"train_preference|tests/unit/train/preference|src/dlm/train/preference" |
| 50 |
"eval|tests/unit/eval|src/dlm/eval" |
| 51 |
"inference|tests/unit/inference|src/dlm/inference" |
| 52 |
"export|tests/unit/export|src/dlm/export" |
| 53 |
"export_ollama|tests/unit/export/ollama|src/dlm/export/ollama" |
| 54 |
"cli_reporter|tests/unit/cli|dlm.cli.reporter" |
| 55 |
"io_ulid|tests/unit/test_io_ulid.py|dlm.io.ulid" |
| 56 |
"pack|tests/unit/pack tests/integration/pack|src/dlm/pack" |
| 57 |
"lock|tests/unit/lock|src/dlm/lock" |
| 58 |
) |
| 59 |
|
| 60 |
gate_selected() { |
| 61 |
local name="$1" |
| 62 |
if [[ ${#selected[@]} -eq 0 ]]; then |
| 63 |
return 0 |
| 64 |
fi |
| 65 |
local needle |
| 66 |
for needle in "${selected[@]}"; do |
| 67 |
if [[ "$needle" == "$name" ]]; then |
| 68 |
return 0 |
| 69 |
fi |
| 70 |
done |
| 71 |
return 1 |
| 72 |
} |
| 73 |
|
| 74 |
if [[ $show_list -eq 1 ]]; then |
| 75 |
for gate in "${gates[@]}"; do |
| 76 |
IFS="|" read -r name _tests _cov <<< "$gate" |
| 77 |
printf '%s\n' "$name" |
| 78 |
done |
| 79 |
exit 0 |
| 80 |
fi |
| 81 |
|
| 82 |
ran_any=0 |
| 83 |
for gate in "${gates[@]}"; do |
| 84 |
IFS="|" read -r name tests cov <<< "$gate" |
| 85 |
if ! gate_selected "$name"; then |
| 86 |
continue |
| 87 |
fi |
| 88 |
ran_any=1 |
| 89 |
echo "==> Coverage gate: $name ($cov)" |
| 90 |
# shellcheck disable=SC2206 |
| 91 |
tests_arr=($tests) |
| 92 |
uv run pytest \ |
| 93 |
"${tests_arr[@]}" \ |
| 94 |
--cov="$cov" \ |
| 95 |
--cov-report=term-missing \ |
| 96 |
--cov-fail-under=100 \ |
| 97 |
-q |
| 98 |
echo |
| 99 |
done |
| 100 |
|
| 101 |
if [[ $ran_any -eq 0 ]]; then |
| 102 |
echo "error: no matching coverage gate names selected" >&2 |
| 103 |
exit 2 |
| 104 |
fi |
| 105 |
|
| 106 |
echo "==> coverage gates clean" |