Skip to content

Commit 13f9fa8

Browse files
getchooedolstra
authored andcommitted
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: DeterminateSystems#134 Based-on: https://gerrit.lix.systems/c/lix/+/3841 Co-authored-by: Eelco Dolstra <[email protected]>
1 parent 1907a33 commit 13f9fa8

File tree

3 files changed

+52
-2
lines changed

3 files changed

+52
-2
lines changed
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
---
2+
synopsis: "`nix flake check` now skips derivations that can be substituted"
3+
prs: [13574]
4+
---
5+
6+
Previously, `nix flake check` would evaluate and build/substitute all
7+
derivations. Now, it will skip downloading derivations that can be substituted.
8+
This can drastically decrease the time invocations take in environments where
9+
checks may already be cached (like in CI).

src/nix/flake.cc

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -786,8 +786,29 @@ struct CmdFlakeCheck : FlakeCommand
786786
}
787787

788788
if (build && !drvPaths.empty()) {
789-
Activity act(*logger, lvlInfo, actUnknown, fmt("running %d flake checks", drvPaths.size()));
790-
store->buildPaths(drvPaths);
789+
// TODO the pruning is temp hacky fix until https://github.com/NixOS/nix/issues/5025 is implemented.
790+
// At that point this should be replaced by code thats sets up a union store.
791+
// Note that to exactly preserve behavior, we would want to look not a single destination store,
792+
// but an "any of" union of stores as the destination store,
793+
// to support different check results being cached with different substituters.
794+
795+
// This command doesn't need to actually substitute derivation outputs
796+
// if they're missing but substitutable.
797+
auto missing = store->queryMissing(drvPaths);
798+
// Only occurs if `drvPaths` contains a `DerivedPath::Opaque`, which should never happen
799+
assert(missing.unknown.empty());
800+
801+
std::vector<DerivedPath> toBuild;
802+
for (auto & path : missing.willBuild) {
803+
toBuild.emplace_back(
804+
DerivedPath::Built{
805+
.drvPath = makeConstantStorePathRef(path),
806+
.outputs = OutputsSpec::All{},
807+
});
808+
}
809+
810+
Activity act(*logger, lvlInfo, actUnknown, fmt("running %d flake checks", toBuild.size()));
811+
store->buildPaths(toBuild);
791812
}
792813
if (hasErrors)
793814
throw Error("some errors were encountered during the evaluation");

tests/functional/flakes/check.sh

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,3 +167,23 @@ EOF
167167
if !isTestOnNixOS && $NIX_REMOTE != daemon; then
168168
expectStderr 100 nix flake check "$flakeDir" | grepQuiet 'builder failed with exit code 1'
169169
fi
170+
171+
# Ensure non-substitutable (read: usually failed) checks are actually run
172+
# https://github.com/NixOS/nix/pull/13574
173+
cp "$config_nix" $flakeDir/
174+
cat > $flakeDir/flake.nix <<EOF
175+
{
176+
outputs = { self }: with import ./config.nix; {
177+
checks.${system}.expectedToFail = derivation {
178+
name = "expected-to-fail";
179+
inherit system;
180+
builder = "not-a-real-file";
181+
};
182+
};
183+
}
184+
EOF
185+
186+
# NOTE: Regex pattern is used for compatibility with older daemon versions
187+
# We also can't expect a specific status code. Earlier daemons return 1, but as of 2.31, we return 100
188+
checkRes=$(nix flake check $flakeDir 2>&1 && fail "nix flake check should have failed" || true)
189+
echo "$checkRes" | grepQuiet -E "builder( for .*)? failed with exit code 1"

0 commit comments

Comments
 (0)