forked from lix-project/lix
Better document build failure exit codes
- Improved API docs from comment - Exit codes are for `nix-build`, not just `nix-store --release` - Make note in tests so the magic numbers are not surprising Picking up where #8387 left off.
This commit is contained in:
parent
2291232dc1
commit
97df060588
|
@ -70,6 +70,8 @@ except for `--arg` and `--attr` / `-A` which are passed to [`nix-instantiate`](n
|
||||||
Change the name of the symlink to the output path created from
|
Change the name of the symlink to the output path created from
|
||||||
`result` to *outlink*.
|
`result` to *outlink*.
|
||||||
|
|
||||||
|
{{#include ./status-build-failure.md}}
|
||||||
|
|
||||||
{{#include ./opt-common.md}}
|
{{#include ./opt-common.md}}
|
||||||
|
|
||||||
{{#include ./env-common.md}}
|
{{#include ./env-common.md}}
|
||||||
|
|
|
@ -54,36 +54,7 @@ The following flags are available:
|
||||||
previous build, the new output path is left in
|
previous build, the new output path is left in
|
||||||
`/nix/store/name.check.`
|
`/nix/store/name.check.`
|
||||||
|
|
||||||
Special exit codes:
|
{{#include ../status-build-failure.md}}
|
||||||
|
|
||||||
- `100`\
|
|
||||||
Generic build failure, the builder process returned with a non-zero
|
|
||||||
exit code.
|
|
||||||
|
|
||||||
- `101`\
|
|
||||||
Build timeout, the build was aborted because it did not complete
|
|
||||||
within the specified `timeout`.
|
|
||||||
|
|
||||||
- `102`\
|
|
||||||
Hash mismatch, the build output was rejected because it does not
|
|
||||||
match the [`outputHash` attribute of the
|
|
||||||
derivation](@docroot@/language/advanced-attributes.md).
|
|
||||||
|
|
||||||
- `104`\
|
|
||||||
Not deterministic, the build succeeded in check mode but the
|
|
||||||
resulting output is not binary reproducible.
|
|
||||||
|
|
||||||
With the `--keep-going` flag it's possible for multiple failures to
|
|
||||||
occur, in this case the 1xx status codes are or combined using binary
|
|
||||||
or.
|
|
||||||
|
|
||||||
1100100
|
|
||||||
^^^^
|
|
||||||
|||`- timeout
|
|
||||||
||`-- output hash mismatch
|
|
||||||
|`--- build failure
|
|
||||||
`---- not deterministic
|
|
||||||
|
|
||||||
|
|
||||||
{{#include ./opt-common.md}}
|
{{#include ./opt-common.md}}
|
||||||
|
|
||||||
|
|
34
doc/manual/src/command-ref/status-build-failure.md
Normal file
34
doc/manual/src/command-ref/status-build-failure.md
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
# Special exit codes for build failure
|
||||||
|
|
||||||
|
1xx status codes are used when requested builds failed.
|
||||||
|
The following codes are in use:
|
||||||
|
|
||||||
|
- `100` Generic build failure
|
||||||
|
|
||||||
|
The builder process returned with a non-zero exit code.
|
||||||
|
|
||||||
|
- `101` Build timeout
|
||||||
|
|
||||||
|
The build was aborted because it did not complete within the specified `timeout`.
|
||||||
|
|
||||||
|
- `102` Hash mismatch
|
||||||
|
|
||||||
|
The build output was rejected because it does not match the
|
||||||
|
[`outputHash` attribute of the derivation](@docroot@/language/advanced-attributes.md).
|
||||||
|
|
||||||
|
- `104` Not deterministic
|
||||||
|
|
||||||
|
The build succeeded in check mode but the resulting output is not binary reproducible.
|
||||||
|
|
||||||
|
With the `--keep-going` flag it's possible for multiple failures to occur.
|
||||||
|
In this case the 1xx status codes are or combined using
|
||||||
|
[bitwise OR](https://en.wikipedia.org/wiki/Bitwise_operation#OR).
|
||||||
|
|
||||||
|
```
|
||||||
|
0b1100100
|
||||||
|
^^^^
|
||||||
|
|||`- timeout
|
||||||
|
||`-- output hash mismatch
|
||||||
|
|`--- build failure
|
||||||
|
`---- not deterministic
|
||||||
|
```
|
|
@ -31,11 +31,11 @@ void Store::buildPaths(const std::vector<DerivedPath> & reqs, BuildMode buildMod
|
||||||
}
|
}
|
||||||
|
|
||||||
if (failed.size() == 1 && ex) {
|
if (failed.size() == 1 && ex) {
|
||||||
ex->status = worker.exitStatus();
|
ex->status = worker.failingExitStatus();
|
||||||
throw std::move(*ex);
|
throw std::move(*ex);
|
||||||
} else if (!failed.empty()) {
|
} else if (!failed.empty()) {
|
||||||
if (ex) logError(ex->info());
|
if (ex) logError(ex->info());
|
||||||
throw Error(worker.exitStatus(), "build of %s failed", showPaths(failed));
|
throw Error(worker.failingExitStatus(), "build of %s failed", showPaths(failed));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,10 +102,10 @@ void Store::ensurePath(const StorePath & path)
|
||||||
|
|
||||||
if (goal->exitCode != Goal::ecSuccess) {
|
if (goal->exitCode != Goal::ecSuccess) {
|
||||||
if (goal->ex) {
|
if (goal->ex) {
|
||||||
goal->ex->status = worker.exitStatus();
|
goal->ex->status = worker.failingExitStatus();
|
||||||
throw std::move(*goal->ex);
|
throw std::move(*goal->ex);
|
||||||
} else
|
} else
|
||||||
throw Error(worker.exitStatus(), "path '%s' does not exist and cannot be created", printStorePath(path));
|
throw Error(worker.failingExitStatus(), "path '%s' does not exist and cannot be created", printStorePath(path));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -128,7 +128,7 @@ void Store::repairPath(const StorePath & path)
|
||||||
goals.insert(worker.makeDerivationGoal(*info->deriver, OutputsSpec::All { }, bmRepair));
|
goals.insert(worker.makeDerivationGoal(*info->deriver, OutputsSpec::All { }, bmRepair));
|
||||||
worker.run(goals);
|
worker.run(goals);
|
||||||
} else
|
} else
|
||||||
throw Error(worker.exitStatus(), "cannot repair path '%s'", printStorePath(path));
|
throw Error(worker.failingExitStatus(), "cannot repair path '%s'", printStorePath(path));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -468,16 +468,9 @@ void Worker::waitForInput()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
unsigned int Worker::exitStatus()
|
unsigned int Worker::failingExitStatus()
|
||||||
{
|
{
|
||||||
/*
|
// See API docs in header for explanation
|
||||||
* 1100100
|
|
||||||
* ^^^^
|
|
||||||
* |||`- timeout
|
|
||||||
* ||`-- output hash mismatch
|
|
||||||
* |`--- build failure
|
|
||||||
* `---- not deterministic
|
|
||||||
*/
|
|
||||||
unsigned int mask = 0;
|
unsigned int mask = 0;
|
||||||
bool buildFailure = permanentFailure || timedOut || hashMismatch;
|
bool buildFailure = permanentFailure || timedOut || hashMismatch;
|
||||||
if (buildFailure)
|
if (buildFailure)
|
||||||
|
|
|
@ -280,7 +280,28 @@ public:
|
||||||
*/
|
*/
|
||||||
void waitForInput();
|
void waitForInput();
|
||||||
|
|
||||||
unsigned int exitStatus();
|
/***
|
||||||
|
* The exit status in case of failure.
|
||||||
|
*
|
||||||
|
* In the case of a build failure, returned value follows this
|
||||||
|
* bitmask:
|
||||||
|
*
|
||||||
|
* ```
|
||||||
|
* 0b1100100
|
||||||
|
* ^^^^
|
||||||
|
* |||`- timeout
|
||||||
|
* ||`-- output hash mismatch
|
||||||
|
* |`--- build failure
|
||||||
|
* `---- not deterministic
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* In other words, the failure code is at least 100 (0b1100100), but
|
||||||
|
* might also be greater.
|
||||||
|
*
|
||||||
|
* Otherwise (no build failure, but some other sort of failure by
|
||||||
|
* assumption), this returned value is 1.
|
||||||
|
*/
|
||||||
|
unsigned int failingExitStatus();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check whether the given valid path exists and has the right
|
* Check whether the given valid path exists and has the right
|
||||||
|
|
|
@ -18,6 +18,9 @@ clearStore
|
||||||
nix-build dependencies.nix --no-out-link
|
nix-build dependencies.nix --no-out-link
|
||||||
nix-build dependencies.nix --no-out-link --check
|
nix-build dependencies.nix --no-out-link --check
|
||||||
|
|
||||||
|
# Build failure exit codes (100, 104, etc.) are from
|
||||||
|
# doc/manual/src/command-ref/status-build-failure.md
|
||||||
|
|
||||||
# check for dangling temporary build directories
|
# check for dangling temporary build directories
|
||||||
# only retain if build fails and --keep-failed is specified, or...
|
# only retain if build fails and --keep-failed is specified, or...
|
||||||
# ...build is non-deterministic and --check and --keep-failed are both specified
|
# ...build is non-deterministic and --check and --keep-failed are both specified
|
||||||
|
|
|
@ -36,11 +36,13 @@ nix-sandbox-build dependencies.nix --check
|
||||||
# Test that sandboxed builds with --check and -K can move .check directory to store
|
# Test that sandboxed builds with --check and -K can move .check directory to store
|
||||||
nix-sandbox-build check.nix -A nondeterministic
|
nix-sandbox-build check.nix -A nondeterministic
|
||||||
|
|
||||||
|
# `100 + 4` means non-determinstic, see doc/manual/src/command-ref/status-build-failure.md
|
||||||
expectStderr 104 nix-sandbox-build check.nix -A nondeterministic --check -K > $TEST_ROOT/log
|
expectStderr 104 nix-sandbox-build check.nix -A nondeterministic --check -K > $TEST_ROOT/log
|
||||||
grepQuietInverse 'error: renaming' $TEST_ROOT/log
|
grepQuietInverse 'error: renaming' $TEST_ROOT/log
|
||||||
grepQuiet 'may not be deterministic' $TEST_ROOT/log
|
grepQuiet 'may not be deterministic' $TEST_ROOT/log
|
||||||
|
|
||||||
# Test that sandboxed builds cannot write to /etc easily
|
# Test that sandboxed builds cannot write to /etc easily
|
||||||
|
# `100` means build failure without extra info, see doc/manual/src/command-ref/status-build-failure.md
|
||||||
expectStderr 100 nix-sandbox-build -E 'with import ./config.nix; mkDerivation { name = "etc-write"; buildCommand = "echo > /etc/test"; }' |
|
expectStderr 100 nix-sandbox-build -E 'with import ./config.nix; mkDerivation { name = "etc-write"; buildCommand = "echo > /etc/test"; }' |
|
||||||
grepQuiet "/etc/test: Permission denied"
|
grepQuiet "/etc/test: Permission denied"
|
||||||
|
|
||||||
|
@ -50,6 +52,7 @@ testCert () {
|
||||||
expectation=$1 # "missing" | "present"
|
expectation=$1 # "missing" | "present"
|
||||||
mode=$2 # "normal" | "fixed-output"
|
mode=$2 # "normal" | "fixed-output"
|
||||||
certFile=$3 # a string that can be the path to a cert file
|
certFile=$3 # a string that can be the path to a cert file
|
||||||
|
# `100` means build failure without extra info, see doc/manual/src/command-ref/status-build-failure.md
|
||||||
[ "$mode" == fixed-output ] && ret=1 || ret=100
|
[ "$mode" == fixed-output ] && ret=1 || ret=100
|
||||||
expectStderr $ret nix-sandbox-build linux-sandbox-cert-test.nix --argstr mode "$mode" --option ssl-cert-file "$certFile" |
|
expectStderr $ret nix-sandbox-build linux-sandbox-cert-test.nix --argstr mode "$mode" --option ssl-cert-file "$certFile" |
|
||||||
grepQuiet "CERT_${expectation}_IN_SANDBOX"
|
grepQuiet "CERT_${expectation}_IN_SANDBOX"
|
||||||
|
|
Loading…
Reference in a new issue