ci/jq/coverage.jq (64 lines of code) (raw):
# DESCRIPTION: Generates a Markdown-formatted coverage summary table
# from a JSON-formatted LLVM coverage report.
#
# PARAMETERS:
# - Standard input: JSON-formatted LLVM coverage report.
# - Named:
# - $bad: Integer threshold below which coverage percentage is "bad".
# - $good: Integer threshold above which coverage percentage is
# "good".
# - $manifest: Path to a `Cargo.toml`. Should be absolute and a
# workspace manifest for ideal path relativization.
# - $root: Absolute path of the repository root.
# - $short_name: Base name of the directory containing the crate
# manifest.
# NOTE(rustup): `.data` is an array, but only contains one element LLVM
# 15 (used by Rust 1.65). This assumption should be verified as the
# Rust version is upgraded.
# Ref: https://github.com/llvm/llvm-project/blob/llvmorg-15.0.0/llvm/tools/llvm-cov/CoverageExporterJson.cpp#L298-L308
def symbol:
if . < $bad then "\u274c"
elif . < $good then "\u2796"
else "\u2795"
end;
($manifest | rtrimstr("Cargo.toml")) as $manifest_directory
# NOTE: Extra newline is necessary after `</summary>` since otherwise
# the table does not get formatted.
| [ "<details><summary>\($short_name): \($manifest | ltrimstr($root + "/"))</summary>\n"
, "Crate | Coverage | Status"
, "----- | ----- | -----"
, ( .data[]
| ( ( [ .files
# NOTE: This intentionally allows the crate described by a
# workspace manifest to be identified by a blank string: the
# directory name is already present in `$short_name`.
| map_values(.crate = (.filename | split("src/") | first))
| group_by(.crate)[]
| { crate: (first | .crate | ltrimstr($manifest_directory))
, coverage:
( reduce .[].summary.lines as $item
( { count: 0, covered: 0 }
; with_entries(.value += $item[.key])
)
| .covered / .count * 100
| floor
)
}
]
# NOTE: Sorting is usually unnecessary, but is required when
# the directory prefix is trimmed from a subset of crate paths.
# The most obvious example is when the manifest is for a crate,
# wherein the crate's coverage summary is shifted to the first
# row.
| sort_by(.crate)[]
| "\(.crate) | \(.coverage)% | \(.coverage | symbol)"
)
, ( .totals.lines
| (.percent | floor) as $percent
| "**Summary** | **\($percent)%** (\(.covered) / \(.count)) | \($percent | symbol)"
)
)
)
, "</details>"
]
| join("\n")