#!/usr/bin/env bash set -euo pipefail # ⚠️ DEPRECATED: This script is deprecated and will be removed in v2.0.0 # Please use: .github/skills/scripts/skill-runner.sh test-backend-coverage # For more info: docs/AGENT_SKILLS_MIGRATION.md echo "⚠️ WARNING: This script is deprecated and will be removed in v2.0.0" >&2 echo " Please use: .github/skills/scripts/skill-runner.sh test-backend-coverage" >&2 echo " For more info: docs/AGENT_SKILLS_MIGRATION.md" >&2 echo "" >&2 sleep 1 ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" BACKEND_DIR="$ROOT_DIR/backend" COVERAGE_FILE="$BACKEND_DIR/coverage.txt" MIN_COVERAGE="${CHARON_MIN_COVERAGE:-${CPM_MIN_COVERAGE:-85}}" # Perf asserts are sensitive to -race overhead; loosen defaults for hook runs export PERF_MAX_MS_GETSTATUS_P95="${PERF_MAX_MS_GETSTATUS_P95:-25ms}" export PERF_MAX_MS_GETSTATUS_P95_PARALLEL="${PERF_MAX_MS_GETSTATUS_P95_PARALLEL:-50ms}" export PERF_MAX_MS_LISTDECISIONS_P95="${PERF_MAX_MS_LISTDECISIONS_P95:-75ms}" # trap 'rm -f "$COVERAGE_FILE"' EXIT cd "$BACKEND_DIR" # Packages to exclude from coverage (main packages and infrastructure code) # These are entrypoints and initialization code that don't benefit from unit tests EXCLUDE_PACKAGES=( "github.com/Wikid82/charon/backend/cmd/api" "github.com/Wikid82/charon/backend/cmd/seed" "github.com/Wikid82/charon/backend/internal/logger" "github.com/Wikid82/charon/backend/internal/metrics" "github.com/Wikid82/charon/backend/internal/trace" "github.com/Wikid82/charon/backend/integration" "github.com/Wikid82/charon/backend/pkg/dnsprovider/builtin" ) # Try to run tests to produce coverage file; some toolchains may return a non-zero # exit if certain coverage tooling is unavailable (e.g. covdata) while still # producing a usable coverage file. Capture the status so we can report real # test failures after the coverage check. # Note: Using -v for verbose output and -race for race detection GO_TEST_STATUS=0 if command -v gotestsum &> /dev/null; then if ! gotestsum --format pkgname -- -race -mod=readonly -coverprofile="$COVERAGE_FILE" ./...; then GO_TEST_STATUS=$? fi else if ! go test -race -v -mod=readonly -coverprofile="$COVERAGE_FILE" ./...; then GO_TEST_STATUS=$? fi fi if [ "$GO_TEST_STATUS" -ne 0 ]; then echo "Warning: go test returned non-zero (status ${GO_TEST_STATUS}); checking coverage file presence" fi # Filter out excluded packages from coverage file if [ -f "$COVERAGE_FILE" ]; then echo "Filtering excluded packages from coverage report..." FILTERED_COVERAGE="${COVERAGE_FILE}.filtered" # Build sed command with all patterns at once (more efficient than loop) SED_PATTERN="" for pkg in "${EXCLUDE_PACKAGES[@]}"; do if [ -z "$SED_PATTERN" ]; then SED_PATTERN="\|^${pkg}|d" else SED_PATTERN="${SED_PATTERN};\|^${pkg}|d" fi done # Use non-blocking sed with explicit input/output (avoids -i hang issues) timeout 30 sed "$SED_PATTERN" "$COVERAGE_FILE" > "$FILTERED_COVERAGE" || { echo "Error: Coverage filtering failed or timed out" echo "Using unfiltered coverage file" cp "$COVERAGE_FILE" "$FILTERED_COVERAGE" } mv "$FILTERED_COVERAGE" "$COVERAGE_FILE" echo "Coverage filtering complete" fi if [ ! -f "$COVERAGE_FILE" ]; then echo "Error: coverage file not generated by go test" exit 1 fi # Generate coverage report once with timeout protection # NOTE: Large repos can produce big coverage profiles; allow more time for parsing. COVERAGE_OUTPUT=$(timeout 180 go tool cover -func="$COVERAGE_FILE" 2>&1) || { echo "Error: go tool cover failed or timed out after 180 seconds" echo "This may indicate corrupted coverage data or memory issues" exit 1 } # Extract and display the summary line (total coverage) TOTAL_LINE=$(echo "$COVERAGE_OUTPUT" | awk '/^total:/ {line=$0} END {print line}') echo "$TOTAL_LINE" # Extract total coverage percentage TOTAL_PERCENT=$(echo "$TOTAL_LINE" | awk '{print substr($3, 1, length($3)-1)}') echo "Computed coverage: ${TOTAL_PERCENT}% (minimum required ${MIN_COVERAGE}%)" export TOTAL_PERCENT export MIN_COVERAGE python3 - <<'PY' import os, sys from decimal import Decimal total = Decimal(os.environ['TOTAL_PERCENT']) minimum = Decimal(os.environ['MIN_COVERAGE']) if total < minimum: print(f"Coverage {total}% is below required {minimum}% (set CHARON_MIN_COVERAGE or CPM_MIN_COVERAGE to override)", file=sys.stderr) sys.exit(1) PY echo "Coverage requirement met" # Bubble up real test failures (after printing coverage info) so pre-commit # reflects the actual test status. if [ "$GO_TEST_STATUS" -ne 0 ]; then exit "$GO_TEST_STATUS" fi