Skip to content

Commit 7a60f14

Browse files
authored
Merge pull request #14321 from roberth/nix-flake-check-track-attribute
Track attributes in `nix flake check`
2 parents 65fbb4d + d4fd5c2 commit 7a60f14

File tree

2 files changed

+55
-5
lines changed

2 files changed

+55
-5
lines changed

src/nix/flake.cc

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -362,7 +362,7 @@ struct CmdFlakeCheck : FlakeCommand
362362
throw;
363363
} catch (Error & e) {
364364
if (settings.keepGoing) {
365-
ignoreExceptionExceptInterrupt();
365+
logError(e.info());
366366
hasErrors = true;
367367
} else
368368
throw;
@@ -418,7 +418,7 @@ struct CmdFlakeCheck : FlakeCommand
418418
return std::nullopt;
419419
};
420420

421-
std::vector<DerivedPath> drvPaths;
421+
std::map<DerivedPath, std::vector<AttrPath>> attrPathsByDrv;
422422

423423
auto checkApp = [&](const std::string & attrPath, Value & v, const PosIdx pos) {
424424
try {
@@ -616,7 +616,13 @@ struct CmdFlakeCheck : FlakeCommand
616616
.drvPath = makeConstantStorePathRef(*drvPath),
617617
.outputs = OutputsSpec::All{},
618618
};
619-
drvPaths.push_back(std::move(path));
619+
620+
// Build and store the attribute path for error reporting
621+
AttrPath attrPath;
622+
attrPath.push_back(AttrName(state->symbols.create(name)));
623+
attrPath.push_back(AttrName(attr.name));
624+
attrPath.push_back(AttrName(attr2.name));
625+
attrPathsByDrv[path].push_back(std::move(attrPath));
620626
}
621627
}
622628
}
@@ -780,7 +786,9 @@ struct CmdFlakeCheck : FlakeCommand
780786
});
781787
}
782788

783-
if (build && !drvPaths.empty()) {
789+
if (build && !attrPathsByDrv.empty()) {
790+
auto keys = std::views::keys(attrPathsByDrv);
791+
std::vector<DerivedPath> drvPaths(keys.begin(), keys.end());
784792
// TODO: This filtering of substitutable paths is a temporary workaround until
785793
// https://github.com/NixOS/nix/issues/5025 (union stores) is implemented.
786794
//
@@ -804,7 +812,28 @@ struct CmdFlakeCheck : FlakeCommand
804812
}
805813

806814
Activity act(*logger, lvlInfo, actUnknown, fmt("running %d flake checks", toBuild.size()));
807-
store->buildPaths(toBuild);
815+
auto results = store->buildPathsWithResults(toBuild);
816+
817+
// Report build failures with attribute paths
818+
for (auto & result : results) {
819+
if (auto * failure = result.tryGetFailure()) {
820+
auto it = attrPathsByDrv.find(result.path);
821+
if (it != attrPathsByDrv.end() && !it->second.empty()) {
822+
for (auto & attrPath : it->second) {
823+
auto attrPathStr = showAttrPath(state->symbols, attrPath);
824+
reportError(Error(
825+
"failed to build attribute '%s', build of '%s' failed: %s",
826+
attrPathStr,
827+
result.path.to_string(*store),
828+
failure->errorMsg));
829+
}
830+
} else {
831+
// Derivation has no attribute path (e.g., a build dependency)
832+
reportError(
833+
Error("build of '%s' failed: %s", result.path.to_string(*store), failure->errorMsg));
834+
}
835+
}
836+
}
808837
}
809838
if (hasErrors)
810839
throw Error("some errors were encountered during the evaluation");

tests/functional/flakes/check.sh

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,3 +192,24 @@ EOF
192192
# shellcheck disable=SC2015
193193
checkRes=$(nix flake check "$flakeDir" 2>&1 && fail "nix flake check should have failed" || true)
194194
echo "$checkRes" | grepQuiet -E "builder( for .*)? failed with exit code 1"
195+
196+
# Test that attribute paths are shown in error messages
197+
cat > "$flakeDir"/flake.nix <<EOF
198+
{
199+
outputs = { self }: with import ./config.nix; {
200+
checks.${system}.failingCheck = mkDerivation {
201+
name = "failing-check";
202+
buildCommand = "echo 'This check fails'; exit 1";
203+
};
204+
checks.${system}.anotherFailingCheck = mkDerivation {
205+
name = "another-failing-check";
206+
buildCommand = "echo 'This also fails'; exit 1";
207+
};
208+
};
209+
}
210+
EOF
211+
212+
# shellcheck disable=SC2015
213+
checkRes=$(nix flake check --keep-going "$flakeDir" 2>&1 && fail "nix flake check should have failed" || true)
214+
echo "$checkRes" | grepQuiet "checks.${system}.failingCheck"
215+
echo "$checkRes" | grepQuiet "checks.${system}.anotherFailingCheck"

0 commit comments

Comments
 (0)