Output evaluation errors without crashing if aggregate job is broken.
[?]
Sep 22, 2021, 8:54 PM
GOVMQVEDNIXFRAIBG5T2HGYSSHMFH542W5H67PFVG74L5T2JABIQCDependencies
- [2]
W7OCNTLFFix build with latest Nix - [3]
HWGFAF2Bqueue runner: test notifications - [4]
VA3Z62HQRevert "Fix unhelpful error messages in aggregate jobs." - [5]
D4G756UKhydra-eval-jobs: Identify unexpected errors in handling aggregate jobs - [6]
4DHGJ2FLFix build - [7]
VUYJ47EVhydra-eval-jobs: Parallelize - [8]
NQPGIRXXRevert "hydra-eval-jobs -> nix eval-hydra-jobs" - [9]
6NUK6AZAFix build - [*]
2JJP7673tests: move to t, allow `yath test` from root
Change contents
- edit in src/hydra-eval-jobs/hydra-eval-jobs.cc at line 1
#include <map> - edit in src/hydra-eval-jobs/hydra-eval-jobs.cc at line 3
#include <optional>#include <unordered_map> - edit in src/hydra-eval-jobs/hydra-eval-jobs.cc at line 445
std::unordered_map<std::string, std::string> brokenJobs;auto getNonBrokenJobOrRecordError = [&brokenJobs, &jobName, &state](const std::string & childJobName) -> std::optional<nlohmann::json> {auto childJob = state->jobs.find(childJobName);if (childJob == state->jobs.end()) {printError("aggregate job '%s' references non-existent job '%s'", jobName, childJobName);brokenJobs[childJobName] = "does not exist";return std::nullopt;}if (childJob->find("error") != childJob->end()) {std::string error = (*childJob)["error"];printError("aggregate job '%s' references broken job '%s': %s", jobName, childJobName, error);brokenJobs[childJobName] = error;return std::nullopt;}return *childJob;}; - replacement in src/hydra-eval-jobs/hydra-eval-jobs.cc at line 466
auto job2 = state->jobs.find(jobName2);if (job2 == state->jobs.end())throw Error("aggregate job '%s' references non-existent job '%s'", jobName, jobName2);auto job2 = getNonBrokenJobOrRecordError(jobName2);if (!job2) {continue;} - replacement in src/hydra-eval-jobs/hydra-eval-jobs.cc at line 478
auto job2 = state->jobs.find(jobName2);if (job2 == state->jobs.end())throw Error("aggregate job '%s' references non-existent job '%s'", jobName, jobName2);auto job2 = getNonBrokenJobOrRecordError(jobName2);if (!job2) {continue;} - replacement in src/hydra-eval-jobs/hydra-eval-jobs.cc at line 488
std::string drvName(drvPath.name());assert(hasSuffix(drvName, drvExtension));drvName.resize(drvName.size() - drvExtension.size());auto h = std::get<Hash>(hashDerivationModulo(*store, drv, true));auto outPath = store->makeOutputPath("out", h, drvName);drv.env["out"] = store->printStorePath(outPath);drv.outputs.insert_or_assign("out", DerivationOutput { .output = DerivationOutputInputAddressed { .path = outPath } });auto newDrvPath = store->printStorePath(writeDerivation(*store, drv));if (brokenJobs.empty()) {std::string drvName(drvPath.name());assert(hasSuffix(drvName, drvExtension));drvName.resize(drvName.size() - drvExtension.size());auto h = std::get<Hash>(hashDerivationModulo(*store, drv, true));auto outPath = store->makeOutputPath("out", h, drvName);drv.env["out"] = store->printStorePath(outPath);drv.outputs.insert_or_assign("out", DerivationOutput { .output = DerivationOutputInputAddressed { .path = outPath } });auto newDrvPath = store->printStorePath(writeDerivation(*store, drv)); - replacement in src/hydra-eval-jobs/hydra-eval-jobs.cc at line 498
debug("rewrote aggregate derivation %s -> %s", store->printStorePath(drvPath), newDrvPath);debug("rewrote aggregate derivation %s -> %s", store->printStorePath(drvPath), newDrvPath); - replacement in src/hydra-eval-jobs/hydra-eval-jobs.cc at line 500
job["drvPath"] = newDrvPath;job["outputs"]["out"] = store->printStorePath(outPath);job["drvPath"] = newDrvPath;job["outputs"]["out"] = store->printStorePath(outPath);} - edit in src/hydra-eval-jobs/hydra-eval-jobs.cc at line 506
if (!brokenJobs.empty()) {std::stringstream ss;for (const auto& [jobName, error] : brokenJobs) {ss << jobName << ": " << error << "\n";}job["error"] = ss.str();} - file addition: broken-constituent.nix[11.1263]
with import ./config.nix;{broken = mkDerivation {name = "broken";_hydraAggregate = true;constituents = ["does-not-exist""does-not-evaluate"];builder = ./fail.sh;};# does-not-exist doesn't exist.does-not-evaluate = assert false; {};} - file addition: constituents.t[3.321]
use feature 'unicode_strings';use strict;use warnings;use Setup;my %ctx = test_init();require Hydra::Schema;require Hydra::Model::DB;use Test2::V0;my $db = Hydra::Model::DB->new;hydra_setup($db);my $project = $db->resultset('Projects')->create({name => "tests", displayname => "", owner => "root"});my $jobset = createBaseJobset("broken-constituent", "broken-constituent.nix", $ctx{jobsdir});ok(evalSucceeds($jobset), "Evaluating jobs/broken-constituent.nix should exit with return code 0");is(nrQueuedBuildsForJobset($jobset), 0, "Evaluating jobs/broken-constituent.nix should not queue any builds");like($jobset->errormsg,qr/^does-not-exist: does not exist$/m,"Evaluating jobs/broken-constituent.nix should log an error for does-not-exist");like($jobset->errormsg,qr/^does-not-evaluate: error: assertion 'false' failed$/m,"Evaluating jobs/broken-constituent.nix should log an error for does-not-evaluate");done_testing;