diff --git a/ci/gha/tests/default.nix b/ci/gha/tests/default.nix index d2bee699b..5dbb3f407 100644 --- a/ci/gha/tests/default.nix +++ b/ci/gha/tests/default.nix @@ -2,6 +2,12 @@ nixFlake ? builtins.getFlake ("git+file://" + toString ../../..), system ? builtins.currentSystem, pkgs ? nixFlake.inputs.nixpkgs.legacyPackages.${system}, + nixComponents ? ( + nixFlake.lib.makeComponents { + inherit pkgs; + inherit getStdenv; + } + ), getStdenv ? p: p.stdenv, componentTestsPrefix ? "", withSanitizers ? false, @@ -64,18 +70,13 @@ let in rec { - nixComponents = - (nixFlake.lib.makeComponents { - inherit pkgs; - inherit getStdenv; - }).overrideScope - ( - final: prev: { - nix-store-tests = prev.nix-store-tests.override { withBenchmarks = true; }; + nixComponentsInstrumented = nixComponents.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. @@ -120,15 +121,15 @@ rec { lib.concatMapAttrs (testName: test: { "${componentTestsPrefix}${pkgName}-${testName}" = test; }) (pkg.tests or { }) - ) nixComponents) + ) nixComponentsInstrumented) // 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 = let componentsTestsToProfile = - (builtins.mapAttrs (n: v: nixComponents.${n}.tests.run) { + (builtins.mapAttrs (n: v: nixComponentsInstrumented.${n}.tests.run) { "nix-util-tests" = { }; "nix-store-tests" = { }; "nix-fetchers-tests" = { }; @@ -136,7 +137,7 @@ rec { "nix-flake-tests" = { }; }) // { - inherit (nixComponents) nix-functional-tests; + inherit (nixComponentsInstrumented) nix-functional-tests; }; coverageProfileDrvs = lib.mapAttrs ( @@ -170,12 +171,13 @@ rec { coverageReports = let - nixComponentDrvs = lib.filter (lib.isDerivation) (lib.attrValues nixComponents); + nixComponentDrvs = lib.filter (lib.isDerivation) (lib.attrValues nixComponentsInstrumented); in pkgs.runCommand "code-coverage-report" { nativeBuildInputs = [ pkgs.llvmPackages.libllvm + pkgs.jq ]; __structuredAttrs = true; nixComponents = nixComponentDrvs; @@ -201,6 +203,24 @@ rec { echo } >> $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 assert withCoverage; diff --git a/packaging/hydra.nix b/packaging/hydra.nix index 7a7569fa3..9f9749bde 100644 --- a/packaging/hydra.nix +++ b/packaging/hydra.nix @@ -223,10 +223,17 @@ in dockerImage = lib.genAttrs linux64BitSystems (system: self.packages.${system}.dockerImage); # # Line coverage analysis. - # coverage = nixpkgsFor.x86_64-linux.native.nix.override { - # pname = "nix-coverage"; - # withCoverageChecks = true; - # }; + coverage = + (import ./../ci/gha/tests rec { + 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 manual = nixpkgsFor.x86_64-linux.native.nixComponents2.nix-manual;