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

Print failing attribute paths in nix flake check

This commit is contained in:
Robert Hensing 2025-10-22 00:56:37 +02:00
parent 7e8db2eb59
commit a38c7eb64e
2 changed files with 54 additions and 4 deletions

View file

@ -423,7 +423,7 @@ struct CmdFlakeCheck : FlakeCommand
return std::nullopt; return std::nullopt;
}; };
std::vector<DerivedPath> drvPaths; std::map<DerivedPath, std::vector<AttrPath>> attrPathsByDrv;
auto checkApp = [&](const std::string & attrPath, Value & v, const PosIdx pos) { auto checkApp = [&](const std::string & attrPath, Value & v, const PosIdx pos) {
try { try {
@ -621,7 +621,13 @@ struct CmdFlakeCheck : FlakeCommand
.drvPath = makeConstantStorePathRef(*drvPath), .drvPath = makeConstantStorePathRef(*drvPath),
.outputs = OutputsSpec::All{}, .outputs = OutputsSpec::All{},
}; };
drvPaths.push_back(std::move(path));
// Build and store the attribute path for error reporting
AttrPath attrPath;
attrPath.push_back(AttrName(state->symbols.create(name)));
attrPath.push_back(AttrName(attr.name));
attrPath.push_back(AttrName(attr2.name));
attrPathsByDrv[path].push_back(std::move(attrPath));
} }
} }
} }
@ -785,7 +791,9 @@ struct CmdFlakeCheck : FlakeCommand
}); });
} }
if (build && !drvPaths.empty()) { if (build && !attrPathsByDrv.empty()) {
auto keys = std::views::keys(attrPathsByDrv);
std::vector<DerivedPath> drvPaths(keys.begin(), keys.end());
// TODO: This filtering of substitutable paths is a temporary workaround until // TODO: This filtering of substitutable paths is a temporary workaround until
// https://github.com/NixOS/nix/issues/5025 (union stores) is implemented. // https://github.com/NixOS/nix/issues/5025 (union stores) is implemented.
// //
@ -811,7 +819,28 @@ struct CmdFlakeCheck : FlakeCommand
} }
Activity act(*logger, lvlInfo, actUnknown, fmt("running %d flake checks", toBuild.size())); Activity act(*logger, lvlInfo, actUnknown, fmt("running %d flake checks", toBuild.size()));
store->buildPaths(toBuild); auto results = store->buildPathsWithResults(toBuild);
// Report build failures with attribute paths
for (auto & result : results) {
if (auto * failure = result.tryGetFailure()) {
auto it = attrPathsByDrv.find(result.path);
if (it != attrPathsByDrv.end() && !it->second.empty()) {
for (auto & attrPath : it->second) {
auto attrPathStr = showAttrPath(state->symbols, attrPath);
reportError(Error(
"failed to build attribute '%s', build of '%s' failed: %s",
attrPathStr,
result.path.to_string(*store),
failure->errorMsg));
}
} else {
// Derivation has no attribute path (e.g., a build dependency)
reportError(
Error("build of '%s' failed: %s", result.path.to_string(*store), failure->errorMsg));
}
}
}
} }
if (hasErrors) if (hasErrors)
throw Error("some errors were encountered during the evaluation"); throw Error("some errors were encountered during the evaluation");

View file

@ -192,3 +192,24 @@ EOF
# shellcheck disable=SC2015 # shellcheck disable=SC2015
checkRes=$(nix flake check "$flakeDir" 2>&1 && fail "nix flake check should have failed" || true) checkRes=$(nix flake check "$flakeDir" 2>&1 && fail "nix flake check should have failed" || true)
echo "$checkRes" | grepQuiet -E "builder( for .*)? failed with exit code 1" echo "$checkRes" | grepQuiet -E "builder( for .*)? failed with exit code 1"
# Test that attribute paths are shown in error messages
cat > "$flakeDir"/flake.nix <<EOF
{
outputs = { self }: with import ./config.nix; {
checks.${system}.failingCheck = mkDerivation {
name = "failing-check";
buildCommand = "echo 'This check fails'; exit 1";
};
checks.${system}.anotherFailingCheck = mkDerivation {
name = "another-failing-check";
buildCommand = "echo 'This also fails'; exit 1";
};
};
}
EOF
# shellcheck disable=SC2015
checkRes=$(nix flake check --keep-going "$flakeDir" 2>&1 && fail "nix flake check should have failed" || true)
echo "$checkRes" | grepQuiet "checks.${system}.failingCheck"
echo "$checkRes" | grepQuiet "checks.${system}.anotherFailingCheck"