forked from lix-project/hydra
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:
parent
d0ad3fd806
commit
8bb36e79bd
|
@ -169,7 +169,7 @@ void State::buildRemote(ref<Store> destStore,
|
||||||
unsigned int remoteVersion;
|
unsigned int remoteVersion;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
to << SERVE_MAGIC_1 << 0x202;
|
to << SERVE_MAGIC_1 << 0x203;
|
||||||
to.flush();
|
to.flush();
|
||||||
|
|
||||||
unsigned int magic = readInt(from);
|
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);
|
throw Error(format("unsupported ‘nix-store --serve’ protocol version on ‘%1%’") % machine->sshName);
|
||||||
if (GET_PROTOCOL_MINOR(remoteVersion) >= 1)
|
if (GET_PROTOCOL_MINOR(remoteVersion) >= 1)
|
||||||
sendDerivation = false;
|
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) {
|
} catch (EndOfFile & e) {
|
||||||
child.pid.wait(true);
|
child.pid.wait(true);
|
||||||
|
@ -261,6 +263,9 @@ void State::buildRemote(ref<Store> destStore,
|
||||||
to << maxSilentTime << buildTimeout;
|
to << maxSilentTime << buildTimeout;
|
||||||
if (GET_PROTOCOL_MINOR(remoteVersion) >= 2)
|
if (GET_PROTOCOL_MINOR(remoteVersion) >= 2)
|
||||||
to << 64 * 1024 * 1024; // == maxLogSize
|
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();
|
to.flush();
|
||||||
|
|
||||||
result.startTime = time(0);
|
result.startTime = time(0);
|
||||||
|
@ -325,6 +330,11 @@ void State::buildRemote(ref<Store> destStore,
|
||||||
case BuildResult::LogLimitExceeded:
|
case BuildResult::LogLimitExceeded:
|
||||||
result.stepStatus = bsLogLimitExceeded;
|
result.stepStatus = bsLogLimitExceeded;
|
||||||
break;
|
break;
|
||||||
|
case BuildResult::NotDeterministic:
|
||||||
|
result.stepStatus = bsNotDeterministic;
|
||||||
|
result.canRetry = false;
|
||||||
|
result.canCache = true;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
result.stepStatus = bsAborted;
|
result.stepStatus = bsAborted;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -418,6 +418,7 @@ Step::ptr State::createStep(ref<Store> destStore,
|
||||||
step->drv = readDerivation(drvPath);
|
step->drv = readDerivation(drvPath);
|
||||||
|
|
||||||
step->preferLocalBuild = step->drv.willBuildLocally();
|
step->preferLocalBuild = step->drv.willBuildLocally();
|
||||||
|
step->isDeterministic = get(step->drv.env, "isDetermistic", "0") == "1";
|
||||||
|
|
||||||
step->systemType = step->drv.platform;
|
step->systemType = step->drv.platform;
|
||||||
{
|
{
|
||||||
|
|
|
@ -35,6 +35,7 @@ typedef enum {
|
||||||
bsUnsupported = 9,
|
bsUnsupported = 9,
|
||||||
bsLogLimitExceeded = 10,
|
bsLogLimitExceeded = 10,
|
||||||
bsNarSizeLimitExceeded = 11,
|
bsNarSizeLimitExceeded = 11,
|
||||||
|
bsNotDeterministic = 12,
|
||||||
bsBusy = 100, // not stored
|
bsBusy = 100, // not stored
|
||||||
} BuildStatus;
|
} BuildStatus;
|
||||||
|
|
||||||
|
@ -139,6 +140,7 @@ struct Step
|
||||||
nix::Derivation drv;
|
nix::Derivation drv;
|
||||||
std::set<std::string> requiredSystemFeatures;
|
std::set<std::string> requiredSystemFeatures;
|
||||||
bool preferLocalBuild;
|
bool preferLocalBuild;
|
||||||
|
bool isDeterministic;
|
||||||
std::string systemType; // concatenation of drv.platform and requiredSystemFeatures
|
std::string systemType; // concatenation of drv.platform and requiredSystemFeatures
|
||||||
|
|
||||||
struct State
|
struct State
|
||||||
|
|
|
@ -69,6 +69,8 @@ FOR step IN steps; IF step.busy; busy = 1; END; END;
|
||||||
<span class="error">Log limit exceeded</span>
|
<span class="error">Log limit exceeded</span>
|
||||||
[% ELSIF step.status == 11 %]
|
[% ELSIF step.status == 11 %]
|
||||||
<span class="error">Output limit exceeded</span>
|
<span class="error">Output limit exceeded</span>
|
||||||
|
[% ELSIF step.status == 12 %]
|
||||||
|
<span class="error">Non-deterministic build</span>
|
||||||
[% ELSIF step.errormsg %]
|
[% ELSIF step.errormsg %]
|
||||||
<span class="error">Failed: [% HTML.escape(step.errormsg) %]</span>
|
<span class="error">Failed: [% HTML.escape(step.errormsg) %]</span>
|
||||||
[% ELSE %]
|
[% ELSE %]
|
||||||
|
|
|
@ -209,6 +209,8 @@ BLOCK renderBuildStatusIcon;
|
||||||
<img src="[% c.uri_for("/static/images/emojione-red-x-274c.svg") %]" height="[% size %]" width="[% size %]" title="Log limit exceeded" alt="Log limit exceeded" class="build-status" />
|
<img src="[% c.uri_for("/static/images/emojione-red-x-274c.svg") %]" height="[% size %]" width="[% size %]" title="Log limit exceeded" alt="Log limit exceeded" class="build-status" />
|
||||||
[% ELSIF buildstatus == 11 %]
|
[% ELSIF buildstatus == 11 %]
|
||||||
<img src="[% c.uri_for("/static/images/emojione-red-x-274c.svg") %]" height="[% size %]" width="[% size %]" title="Output size limit exceeded" alt="Output size limit exceeded" class="build-status" />
|
<img src="[% c.uri_for("/static/images/emojione-red-x-274c.svg") %]" height="[% size %]" width="[% size %]" title="Output size limit exceeded" alt="Output size limit exceeded" class="build-status" />
|
||||||
|
[% ELSIF buildstatus == 12 %]
|
||||||
|
<img src="[% c.uri_for("/static/images/emojione-red-x-274c.svg") %]" height="[% size %]" width="[% size %]" title="Non-deterministic build" alt="Non-deterministic build" class="build-status" />
|
||||||
[% ELSE %]
|
[% ELSE %]
|
||||||
<img src="[% c.uri_for("/static/images/emojione-red-x-274c.svg") %]" height="[% size %]" width="[% size %]" title="Failed" alt="Failed" class="build-status" />
|
<img src="[% c.uri_for("/static/images/emojione-red-x-274c.svg") %]" height="[% size %]" width="[% size %]" title="Failed" alt="Failed" class="build-status" />
|
||||||
[% END;
|
[% END;
|
||||||
|
@ -240,6 +242,8 @@ BLOCK renderStatus;
|
||||||
<span class="error">Log limit exceeded</span>
|
<span class="error">Log limit exceeded</span>
|
||||||
[% ELSIF buildstatus == 11 %]
|
[% ELSIF buildstatus == 11 %]
|
||||||
<span class="error">Output limit exceeded</span>
|
<span class="error">Output limit exceeded</span>
|
||||||
|
[% ELSIF buildstatus == 12 %]
|
||||||
|
<span class="error">Non-deterministic build</span>
|
||||||
[% ELSE %]
|
[% ELSE %]
|
||||||
<span class="error">Aborted</span>
|
<span class="error">Aborted</span>
|
||||||
(Hydra failure; see <a href="#nix-error">below</a>)
|
(Hydra failure; see <a href="#nix-error">below</a>)
|
||||||
|
|
|
@ -211,6 +211,7 @@ create table Builds (
|
||||||
-- 9 = unsupported system type
|
-- 9 = unsupported system type
|
||||||
-- 10 = log limit exceeded
|
-- 10 = log limit exceeded
|
||||||
-- 11 = NAR size limit exceeded
|
-- 11 = NAR size limit exceeded
|
||||||
|
-- 12 = build or step was not deterministic
|
||||||
buildStatus integer,
|
buildStatus integer,
|
||||||
|
|
||||||
size bigint,
|
size bigint,
|
||||||
|
|
Loading…
Reference in a new issue