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

nix flake check: Skip substitutable derivations

Since `nix flake check` doesn't produce a `result` symlink, it doesn't
actually need to build/substitute derivations that are already known
to have succeeded, i.e. that are substitutable.

This can speed up CI jobs in cases where the derivations have already
been built by other jobs. For instance, a command like

  nix flake check github:NixOS/hydra/aa62c7f7db31753f0cde690f8654dd1907fc0ce2

should no longer build anything because the outputs are already in
cache.nixos.org.

Based-on: https://github.com/DeterminateSystems/nix-src/pull/134
Based-on: https://gerrit.lix.systems/c/lix/+/3841
Co-authored-by: Eelco Dolstra <edolstra@gmail.com>
This commit is contained in:
Seth Flynn 2025-08-05 13:56:09 -04:00 committed by Jörg Thalheim
parent 1907a3300f
commit ecdda5798c
3 changed files with 55 additions and 2 deletions

View file

@ -786,8 +786,32 @@ struct CmdFlakeCheck : FlakeCommand
}
if (build && !drvPaths.empty()) {
Activity act(*logger, lvlInfo, actUnknown, fmt("running %d flake checks", drvPaths.size()));
store->buildPaths(drvPaths);
// TODO: This filtering of substitutable paths is a temporary workaround until
// https://github.com/NixOS/nix/issues/5025 (union stores) is implemented.
//
// Once union stores are available, this code should be replaced with a proper
// union store configuration. Ideally, we'd use a union of multiple destination
// stores to preserve the current behavior where different substituters can
// cache different check results.
//
// For now, we skip building derivations whose outputs are already available
// via substitution, as `nix flake check` only needs to verify buildability,
// not actually produce the outputs.
auto missing = store->queryMissing(drvPaths);
// Only occurs if `drvPaths` contains a `DerivedPath::Opaque`, which should never happen
assert(missing.unknown.empty());
std::vector<DerivedPath> toBuild;
for (auto & path : missing.willBuild) {
toBuild.emplace_back(
DerivedPath::Built{
.drvPath = makeConstantStorePathRef(path),
.outputs = OutputsSpec::All{},
});
}
Activity act(*logger, lvlInfo, actUnknown, fmt("running %d flake checks", toBuild.size()));
store->buildPaths(toBuild);
}
if (hasErrors)
throw Error("some errors were encountered during the evaluation");