Support testing build determinism

Builds can now specify the attribute "isDeterministic = true" to tell
Hydra to build with build-repeat > 0. If there is a mismatch between
rounds, the step / build fails with a suitable status.

Maybe this should be a meta attribute, but that makes it invisible to
hydra-queue-runner, and it seems reasonable to make a claim of
mandatory determinism part of the derivation (since e.g. enabling this
flag should trigger a rebuild).
This commit is contained in:
Eelco Dolstra
2016-12-06 17:46:06 +01:00
parent d0ad3fd806
commit 8bb36e79bd
6 changed files with 21 additions and 1 deletions

View File

@ -169,7 +169,7 @@ void State::buildRemote(ref<Store> destStore,
unsigned int remoteVersion;
try {
to << SERVE_MAGIC_1 << 0x202;
to << SERVE_MAGIC_1 << 0x203;
to.flush();
unsigned int magic = readInt(from);
@ -180,6 +180,8 @@ void State::buildRemote(ref<Store> destStore,
throw Error(format("unsupported nix-store --serve protocol version on %1%") % machine->sshName);
if (GET_PROTOCOL_MINOR(remoteVersion) >= 1)
sendDerivation = false;
if (GET_PROTOCOL_MINOR(remoteVersion) < 3 && step->isDeterministic)
throw Error("machine %1% does not support deterministic builds; please upgrade it to Nix 1.12", machine->sshName);
} catch (EndOfFile & e) {
child.pid.wait(true);
@ -261,6 +263,9 @@ void State::buildRemote(ref<Store> destStore,
to << maxSilentTime << buildTimeout;
if (GET_PROTOCOL_MINOR(remoteVersion) >= 2)
to << 64 * 1024 * 1024; // == maxLogSize
if (GET_PROTOCOL_MINOR(remoteVersion) >= 3)
// FIXME: make the number of repeats configurable.
to << (step->isDeterministic ? 1 : 0);
to.flush();
result.startTime = time(0);
@ -325,6 +330,11 @@ void State::buildRemote(ref<Store> destStore,
case BuildResult::LogLimitExceeded:
result.stepStatus = bsLogLimitExceeded;
break;
case BuildResult::NotDeterministic:
result.stepStatus = bsNotDeterministic;
result.canRetry = false;
result.canCache = true;
break;
default:
result.stepStatus = bsAborted;
break;

View File

@ -418,6 +418,7 @@ Step::ptr State::createStep(ref<Store> destStore,
step->drv = readDerivation(drvPath);
step->preferLocalBuild = step->drv.willBuildLocally();
step->isDeterministic = get(step->drv.env, "isDetermistic", "0") == "1";
step->systemType = step->drv.platform;
{

View File

@ -35,6 +35,7 @@ typedef enum {
bsUnsupported = 9,
bsLogLimitExceeded = 10,
bsNarSizeLimitExceeded = 11,
bsNotDeterministic = 12,
bsBusy = 100, // not stored
} BuildStatus;
@ -139,6 +140,7 @@ struct Step
nix::Derivation drv;
std::set<std::string> requiredSystemFeatures;
bool preferLocalBuild;
bool isDeterministic;
std::string systemType; // concatenation of drv.platform and requiredSystemFeatures
struct State