prometeu-runtime/scripts/coverage-domain-evidence.sh
2026-04-20 18:01:16 +01:00

106 lines
3.3 KiB
Bash
Executable File

#!/usr/bin/env bash
set -euo pipefail
ROOT="$(git rev-parse --show-toplevel)"
CONFIG_PATH="${ROOT}/files/config/runtime-edge-coverage-domains.json"
DEFAULT_REPORT="${ROOT}/target/llvm-cov/report.json"
usage() {
cat <<'EOF'
Usage:
coverage-domain-evidence.sh --list
coverage-domain-evidence.sh <domain> [report.json]
The report path defaults to target/llvm-cov/report.json and is expected to be
generated by `make ci` or `make coverage-report-json`.
EOF
}
if [[ ! -f "${CONFIG_PATH}" ]]; then
echo "missing coverage domain config: ${CONFIG_PATH}" >&2
exit 1
fi
if [[ $# -eq 0 ]]; then
usage
exit 1
fi
if [[ "$1" == "--list" ]]; then
jq -r '.domains | keys[]' "${CONFIG_PATH}"
exit 0
fi
DOMAIN="$1"
REPORT_PATH="${2:-${DEFAULT_REPORT}}"
if ! jq -e --arg domain "${DOMAIN}" '.domains[$domain]' "${CONFIG_PATH}" >/dev/null; then
echo "unknown domain: ${DOMAIN}" >&2
echo "available domains:" >&2
jq -r '.domains | keys[]' "${CONFIG_PATH}" >&2
exit 1
fi
BASELINE="$(jq -r --arg domain "${DOMAIN}" '.domains[$domain].baseline_percent' "${CONFIG_PATH}")"
echo "Runtime edge coverage evidence"
echo "Domain: ${DOMAIN}"
echo "Baseline percent: ${BASELINE}"
echo
echo "Mapped repository paths:"
jq -r --arg domain "${DOMAIN}" '.domains[$domain].paths[]' "${CONFIG_PATH}" | while IFS= read -r prefix; do
echo " - ${prefix}"
done
echo
echo "Tracked files present in repository:"
while IFS= read -r path; do
(
cd "${ROOT}"
rg --files . | sed 's#^\./##'
) | rg "^${path//\//\\/}" || true
done < <(jq -r --arg domain "${DOMAIN}" '.domains[$domain].paths[]' "${CONFIG_PATH}")
echo
if [[ ! -f "${REPORT_PATH}" ]]; then
echo "Coverage report not found: ${REPORT_PATH}"
echo "Generate it with: make coverage-report-json"
exit 0
fi
jq -r --arg domain "${DOMAIN}" --arg root "${ROOT}" '
.domains[$domain].paths as $paths
| def matches_domain:
. as $file
| any($paths[]; . as $p | ($file.filename | startswith($root + "/" + $p) or startswith("./" + $p) or startswith($p)));
def pct($covered; $count):
if $count > 0 then (($covered * 10000 / $count | floor) / 100) else 0 end;
reduce (
input.data[]?.files[]?
| select(matches_domain)
) as $file (
{
files: [],
lines: {count: 0, covered: 0},
functions: {count: 0, covered: 0},
regions: {count: 0, covered: 0}
};
.files += [$file.filename]
| .lines.count += ($file.summary.lines.count // 0)
| .lines.covered += ($file.summary.lines.covered // 0)
| .functions.count += ($file.summary.functions.count // 0)
| .functions.covered += ($file.summary.functions.covered // 0)
| .regions.count += ($file.summary.regions.count // 0)
| .regions.covered += ($file.summary.regions.covered // 0)
)
| "Coverage summary from " + $domain + ":",
" files_in_report: " + (.files | length | tostring),
" lines: " + (pct(.lines.covered; .lines.count) | tostring) + "% (" + (.lines.covered|tostring) + "/" + (.lines.count|tostring) + ")",
" functions: " + (pct(.functions.covered; .functions.count) | tostring) + "% (" + (.functions.covered|tostring) + "/" + (.functions.count|tostring) + ")",
" regions: " + (pct(.regions.covered; .regions.count) | tostring) + "% (" + (.regions.covered|tostring) + "/" + (.regions.count|tostring) + ")",
"",
"Matched report files:",
(.files[]? | " - " + .)
' "${CONFIG_PATH}" "${REPORT_PATH}"