#!/usr/bin/env bash # check_coverage.sh — Check Go project coverage against thresholds # # Usage: # bash scripts/test/check_coverage.sh [min-percentage] # # Default threshold: 85% (matches Hermes config agent.min_test_coverage) # # Reads thresholds from: # 1. CLI argument (highest priority) # 2. tests/quality/coverage_thresholds.tsv (per-package thresholds) # 3. Default 85% # # Output: # - Coverage report (stdout) # - Exit code 1 if any package below threshold set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" PROJECT_DIR="$(cd "${SCRIPT_DIR}/../.." && pwd)" DEFAULT_THRESHOLD="${1:-85}" THRESHOLD_FILE="${PROJECT_DIR}/tests/quality/coverage_thresholds.tsv" echo "==> coverage threshold: ${DEFAULT_THRESHOLD}%" # Collect coverage cd "$PROJECT_DIR" COVERAGE_OUT=$(mktemp) go test -count=1 -cover ./internal/... 2>&1 | tee "$COVERAGE_OUT" # Check per-package thresholds from file if exists HAS_FILE_THRESHOLDS=false declare -A PACKAGE_THRESHOLDS if [[ -f "$THRESHOLD_FILE" ]]; then HAS_FILE_THRESHOLDS=true while IFS=$'\t' read -r pkg threshold; do [[ -z "$pkg" || "$pkg" == \#* ]] && continue PACKAGE_THRESHOLDS["$pkg"]="$threshold" done < "$THRESHOLD_FILE" fi # Parse and validate EXIT_CODE=0 declare -a FAILURES=() CURRENT_PKG="" TOTAL_PKG=0 PASS_PKG=0 parse_coverage_line() { local line="$1" # Match: ok github.com/xxx/sub2api-cn-relay-manager/internal/provision 0.012s coverage: 82.8% of statements # Match: ? github.com/xxx/sub2api-cn-relay-manager/internal/provision [no test files] if [[ "$line" =~ ^ok[[:space:]]+.*/[^[:space:]]+[[:space:]]+[0-9.]+s[[:space:]]+coverage:[[:space:]]+([0-9.]+)% ]]; then local pct="${BASH_REMATCH[1]}" local pkg_name pkg_name=$(echo "$line" | awk '{print $2}' | awk -F'/' '{print $NF}') local threshold="$DEFAULT_THRESHOLD" if $HAS_FILE_THRESHOLDS && [[ -n "${PACKAGE_THRESHOLDS[$pkg_name]:-}" ]]; then threshold="${PACKAGE_THRESHOLDS[$pkg_name]}" fi TOTAL_PKG=$((TOTAL_PKG + 1)) if (( $(echo "$pct < $threshold" | bc -l 2>/dev/null || echo 1) )); then FAILURES+=("${pkg_name}: ${pct}% < ${threshold}%") EXIT_CODE=1 else PASS_PKG=$((PASS_PKG + 1)) echo " ✅ ${pkg_name}: ${pct}% (threshold: ${threshold}%)" fi fi } while IFS= read -r line; do parse_coverage_line "$line" done < "$COVERAGE_OUT" echo "" echo "==> summary: ${PASS_PKG}/${TOTAL_PKG} packages pass coverage threshold" if [[ ${#FAILURES[@]} -gt 0 ]]; then echo "FAILURES:" for f in "${FAILURES[@]}"; do echo " ❌ $f" done fi # Optionally generate markdown report REPORT_FILE="${COVERAGE_REPORT:-}" if [[ -n "$REPORT_FILE" ]]; then { echo "# Coverage Report ($(date +%Y-%m-%d))" echo "" echo "| Package | Coverage | Threshold | Status |" echo "|---------|----------|-----------|--------|" while IFS= read -r line; do if [[ "$line" =~ ^ok[[:space:]]+.*/[^[:space:]]+[[:space:]]+[0-9.]+s[[:space:]]+coverage:[[:space:]]+([0-9.]+)% ]]; then pkg=$(echo "$line" | awk '{print $2}' | awk -F'/' '{print $NF}') pct="${BASH_REMATCH[1]}" threshold="$DEFAULT_THRESHOLD" if $HAS_FILE_THRESHOLDS && [[ -n "${PACKAGE_THRESHOLDS[$pkg]:-}" ]]; then threshold="${PACKAGE_THRESHOLDS[$pkg]}" fi status="✅" if (( $(echo "$pct < $threshold" | bc -l 2>/dev/null || echo 1) )); then status="❌" fi echo "| ${pkg} | ${pct}% | ${threshold}% | ${status} |" fi done < "$COVERAGE_OUT" echo "" echo "**Overall: ${PASS_PKG}/${TOTAL_PKG} passing, exit $([ $EXIT_CODE -eq 0 ] && echo 0 || echo 1)**" } > "$REPORT_FILE" echo "Report: $REPORT_FILE" fi rm -f "$COVERAGE_OUT" exit $EXIT_CODE