add check-cache-status option to query wether a binary cache has the build

This commit is contained in:
Jörg Thalheim 2022-09-09 11:24:53 +00:00
parent 31245712bf
commit f6890b93e8
2 changed files with 54 additions and 11 deletions

View file

@ -44,6 +44,7 @@ struct MyArgs : MixEvalArgs, MixCommonArgs {
bool meta = false; bool meta = false;
bool showTrace = false; bool showTrace = false;
bool impure = false; bool impure = false;
bool checkCacheStatus = false;
size_t nrWorkers = 1; size_t nrWorkers = 1;
size_t maxMemorySize = 4096; size_t maxMemorySize = 4096;
@ -93,6 +94,15 @@ struct MyArgs : MixEvalArgs, MixCommonArgs {
.description = "include derivation meta field in output", .description = "include derivation meta field in output",
.handler = {&meta, true}}); .handler = {&meta, true}});
addFlag(
{.longName = "check-cache-status",
.description =
"Check if the derivations are present locally or in "
"any configured substituters (i.e. binary cache). The "
"information "
"will be exposed in the `isCached` field of the JSON output.",
.handler = {&checkCacheStatus, true}});
addFlag({.longName = "show-trace", addFlag({.longName = "show-trace",
.description = .description =
"print out a stack trace in case of evaluation errors", "print out a stack trace in case of evaluation errors",
@ -171,11 +181,26 @@ Value *topLevelValue(EvalState &state, Bindings &autoArgs) {
: releaseExprTopLevelValue(state, autoArgs); : releaseExprTopLevelValue(state, autoArgs);
} }
bool queryIsCached(Store &store, std::map<std::string, std::string> &outputs) {
uint64_t downloadSize, narSize;
StorePathSet willBuild, willSubstitute, unknown;
std::vector<StorePathWithOutputs> paths;
for (auto const &[key, val] : outputs) {
paths.push_back(followLinksToStorePathWithOutputs(store, val));
}
store.queryMissing(toDerivedPaths(paths), willBuild, willSubstitute,
unknown, downloadSize, narSize);
return willBuild.empty() && unknown.empty();
}
/* The fields of a derivation that are printed in json form */ /* The fields of a derivation that are printed in json form */
struct Drv { struct Drv {
std::string name; std::string name;
std::string system; std::string system;
std::string drvPath; std::string drvPath;
bool isCached;
std::map<std::string, std::string> outputs; std::map<std::string, std::string> outputs;
std::optional<nlohmann::json> meta; std::optional<nlohmann::json> meta;
@ -209,6 +234,9 @@ struct Drv {
} }
meta = meta_; meta = meta_;
} }
if (myArgs.checkCacheStatus) {
isCached = queryIsCached(*localStore, outputs);
}
name = drvInfo.queryName(); name = drvInfo.queryName();
system = drvInfo.querySystem(); system = drvInfo.querySystem();
@ -217,15 +245,18 @@ struct Drv {
}; };
static void to_json(nlohmann::json &json, const Drv &drv) { static void to_json(nlohmann::json &json, const Drv &drv) {
json = nlohmann::json{ json = nlohmann::json{{"name", drv.name},
{"name", drv.name},
{"system", drv.system}, {"system", drv.system},
{"drvPath", drv.drvPath}, {"drvPath", drv.drvPath},
{"outputs", drv.outputs}, {"outputs", drv.outputs}};
};
if (drv.meta.has_value()) if (drv.meta.has_value()) {
json["meta"] = drv.meta.value(); json["meta"] = drv.meta.value();
}
if (myArgs.checkCacheStatus) {
json["isCached"] = drv.isCached;
}
} }
std::string attrPathJoin(json input) { std::string attrPathJoin(json input) {

View file

@ -4,14 +4,14 @@ import subprocess
import json import json
from tempfile import TemporaryDirectory from tempfile import TemporaryDirectory
from pathlib import Path from pathlib import Path
from typing import List from typing import List, Dict, Any
TEST_ROOT = Path(__file__).parent.resolve() TEST_ROOT = Path(__file__).parent.resolve()
PROJECT_ROOT = TEST_ROOT.parent PROJECT_ROOT = TEST_ROOT.parent
BIN = PROJECT_ROOT.joinpath("build", "src", "nix-eval-jobs") BIN = PROJECT_ROOT.joinpath("build", "src", "nix-eval-jobs")
def common_test(extra_args: List[str]) -> None: def common_test(extra_args: List[str]) -> List[Dict[str, Any]]:
with TemporaryDirectory() as tempdir: with TemporaryDirectory() as tempdir:
cmd = [str(BIN), "--gc-roots-dir", tempdir, "--meta"] + extra_args cmd = [str(BIN), "--gc-roots-dir", tempdir, "--meta"] + extra_args
res = subprocess.run( res = subprocess.run(
@ -47,14 +47,26 @@ def common_test(extra_args: List[str]) -> None:
assert substituted_job["attr"] == "substitutedJob" assert substituted_job["attr"] == "substitutedJob"
assert substituted_job["name"].startswith("hello-") assert substituted_job["name"].startswith("hello-")
assert substituted_job["meta"]["broken"] is False assert substituted_job["meta"]["broken"] is False
return results
def test_flake() -> None: def test_flake() -> None:
common_test(["--flake", ".#hydraJobs"]) results = common_test(["--flake", ".#hydraJobs"])
for result in results:
assert "isCached" not in result
def test_query_cache_status() -> None:
results = common_test(["--flake", ".#hydraJobs", "--check-cache-status"])
# FIXME in the nix sandbox we cannot query binary caches, this would need some local one
for result in results:
assert "isCached" in result
def test_expression() -> None: def test_expression() -> None:
common_test(["ci.nix"]) results = common_test(["ci.nix"])
for result in results:
assert "isCached" not in result
with open(TEST_ROOT.joinpath("assets/ci.nix"), "r") as ci_nix: with open(TEST_ROOT.joinpath("assets/ci.nix"), "r") as ci_nix:
common_test(["-E", ci_nix.read()]) common_test(["-E", ci_nix.read()])