1
1
Fork 0
mirror of https://github.com/NixOS/nix.git synced 2025-11-09 03:56:01 +01:00

hydra: Restore coverage job

Sometime ago we lost the coverage job in the midst of
meson migration. Until we have something like codecov
it'd be very useful to restore this job with the html
reports and historical metrics.

As a bonus we get more coverage metrics by switching to
LLVM tooling from LCOV.
This commit is contained in:
Sergei Zimmerman 2025-08-08 12:05:01 +03:00
parent cac8ec3b05
commit 51c0e6bc63
No known key found for this signature in database
2 changed files with 47 additions and 20 deletions

View file

@ -2,6 +2,12 @@
nixFlake ? builtins.getFlake ("git+file://" + toString ../../..), nixFlake ? builtins.getFlake ("git+file://" + toString ../../..),
system ? builtins.currentSystem, system ? builtins.currentSystem,
pkgs ? nixFlake.inputs.nixpkgs.legacyPackages.${system}, pkgs ? nixFlake.inputs.nixpkgs.legacyPackages.${system},
nixComponents ? (
nixFlake.lib.makeComponents {
inherit pkgs;
inherit getStdenv;
}
),
getStdenv ? p: p.stdenv, getStdenv ? p: p.stdenv,
componentTestsPrefix ? "", componentTestsPrefix ? "",
withSanitizers ? false, withSanitizers ? false,
@ -64,18 +70,13 @@ let
in in
rec { rec {
nixComponents = nixComponentsInstrumented = nixComponents.overrideScope (
(nixFlake.lib.makeComponents { final: prev: {
inherit pkgs; nix-store-tests = prev.nix-store-tests.override { withBenchmarks = true; };
inherit getStdenv;
}).overrideScope
(
final: prev: {
nix-store-tests = prev.nix-store-tests.override { withBenchmarks = true; };
mesonComponentOverrides = lib.composeManyExtensions componentOverrides; mesonComponentOverrides = lib.composeManyExtensions componentOverrides;
} }
); );
/** /**
Top-level tests for the flake outputs, as they would be built by hydra. Top-level tests for the flake outputs, as they would be built by hydra.
@ -120,15 +121,15 @@ rec {
lib.concatMapAttrs (testName: test: { lib.concatMapAttrs (testName: test: {
"${componentTestsPrefix}${pkgName}-${testName}" = test; "${componentTestsPrefix}${pkgName}-${testName}" = test;
}) (pkg.tests or { }) }) (pkg.tests or { })
) nixComponents) ) nixComponentsInstrumented)
// lib.optionalAttrs (pkgs.stdenv.hostPlatform == pkgs.stdenv.buildPlatform) { // lib.optionalAttrs (pkgs.stdenv.hostPlatform == pkgs.stdenv.buildPlatform) {
"${componentTestsPrefix}nix-functional-tests" = nixComponents.nix-functional-tests; "${componentTestsPrefix}nix-functional-tests" = nixComponentsInstrumented.nix-functional-tests;
}; };
codeCoverage = codeCoverage =
let let
componentsTestsToProfile = componentsTestsToProfile =
(builtins.mapAttrs (n: v: nixComponents.${n}.tests.run) { (builtins.mapAttrs (n: v: nixComponentsInstrumented.${n}.tests.run) {
"nix-util-tests" = { }; "nix-util-tests" = { };
"nix-store-tests" = { }; "nix-store-tests" = { };
"nix-fetchers-tests" = { }; "nix-fetchers-tests" = { };
@ -136,7 +137,7 @@ rec {
"nix-flake-tests" = { }; "nix-flake-tests" = { };
}) })
// { // {
inherit (nixComponents) nix-functional-tests; inherit (nixComponentsInstrumented) nix-functional-tests;
}; };
coverageProfileDrvs = lib.mapAttrs ( coverageProfileDrvs = lib.mapAttrs (
@ -170,12 +171,13 @@ rec {
coverageReports = coverageReports =
let let
nixComponentDrvs = lib.filter (lib.isDerivation) (lib.attrValues nixComponents); nixComponentDrvs = lib.filter (lib.isDerivation) (lib.attrValues nixComponentsInstrumented);
in in
pkgs.runCommand "code-coverage-report" pkgs.runCommand "code-coverage-report"
{ {
nativeBuildInputs = [ nativeBuildInputs = [
pkgs.llvmPackages.libllvm pkgs.llvmPackages.libllvm
pkgs.jq
]; ];
__structuredAttrs = true; __structuredAttrs = true;
nixComponents = nixComponentDrvs; nixComponents = nixComponentDrvs;
@ -201,6 +203,24 @@ rec {
echo echo
} >> $out/index.txt } >> $out/index.txt
llvm-cov export $arguments -instr-profile ${mergedProfdata} -format=text > $out/coverage.json
mkdir -p $out/nix-support
coverageTotals=$(jq ".data[0].totals" $out/coverage.json)
# Mostly inline from pkgs/build-support/setup-hooks/make-coverage-analysis-report.sh [1],
# which we can't use here, because we rely on LLVM's infra for source code coverage collection.
# [1]: https://github.com/NixOS/nixpkgs/blob/67bb48c4c8e327417d6d5aa7e538244b209e852b/pkgs/build-support/setup-hooks/make-coverage-analysis-report.sh#L16
declare -A metricsArray=(["lineCoverage"]="lines" ["functionCoverage"]="functions" ["branchCoverage"]="branches")
for metricName in "''\${!metricsArray[@]}"; do
key="''\${metricsArray[$metricName]}"
metric=$(echo "$coverageTotals" | jq ".$key.percent * 10 | round / 10")
echo "$metricName $metric %" >> $out/nix-support/hydra-metrics
done
echo "report coverage $out" >> $out/nix-support/hydra-build-products
''; '';
in in
assert withCoverage; assert withCoverage;

View file

@ -223,10 +223,17 @@ in
dockerImage = lib.genAttrs linux64BitSystems (system: self.packages.${system}.dockerImage); dockerImage = lib.genAttrs linux64BitSystems (system: self.packages.${system}.dockerImage);
# # Line coverage analysis. # # Line coverage analysis.
# coverage = nixpkgsFor.x86_64-linux.native.nix.override { coverage =
# pname = "nix-coverage"; (import ./../ci/gha/tests rec {
# withCoverageChecks = true; withCoverage = true;
# }; pkgs = nixpkgsFor.x86_64-linux.nativeForStdenv.clangStdenv;
nixComponents = pkgs.nixComponents2;
nixFlake = null;
getStdenv = p: p.clangStdenv;
}).codeCoverage.coverageReports.overrideAttrs
{
name = "nix-coverage"; # For historical consistency
};
# Nix's manual # Nix's manual
manual = nixpkgsFor.x86_64-linux.native.nixComponents2.nix-manual; manual = nixpkgsFor.x86_64-linux.native.nixComponents2.nix-manual;