Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion doc/stdenv/meta.chapter.md
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ The list of Nix platform types for which the [Hydra](https://github.com/nixos/hy

### `broken` {#var-meta-broken}

If set to `true`, the package is marked as "broken", meaning that it won’t show up in [search.nixos.org](https://search.nixos.org/packages), and cannot be built or installed unless the environment variable [`NIXPKGS_ALLOW_BROKEN`](#opt-allowBroken) is set.
If set to `true`, the package is marked as "broken", meaning that it won’t show up in [search.nixos.org](https://search.nixos.org/packages), and cannot be built or installed unless [explicitly allowing it](#sec-allow-broken).
Such unconditionally-broken packages should be removed from Nixpkgs eventually unless they are fixed.

The value of this attribute can depend on a package's arguments, including `stdenv`.
Expand Down Expand Up @@ -181,6 +181,15 @@ This means that `broken` can be used to express constraints, for example:
This makes `broken` strictly more powerful than `meta.badPlatforms`.
However `meta.availableOn` currently examines only `meta.platforms` and `meta.badPlatforms`, so `meta.broken` does not influence the default values for optional dependencies.

Underneath, `meta.broken = true;` is the same as
```nix
{
meta.problems.broken.message = "This package is broken.";
}
```

By specifying this manually, the error message can be customised.

## `knownVulnerabilities` {#var-meta-knownVulnerabilities}

A list of known vulnerabilities affecting the package, usually identified by CVE identifiers.
Expand Down
5 changes: 3 additions & 2 deletions doc/using/configuration.chapter.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,11 @@ There are several ways to try compiling a package which has been marked as broke
$ export NIXPKGS_ALLOW_BROKEN=1
```

- For permanently allowing broken packages that match some condition to be built, you may add `allowBrokenPredicate` to your user's configuration file with the desired condition, for example:
- For permanently allowing broken packages with a specific name to be built, you may add a corresponding `problems.handlers` to your user's configuration file, for example:

```nix
{
allowBrokenPredicate = pkg: builtins.elem (pkgs.lib.getName pkg) [ "hello" ];
problems.handlers.hello.broken = "warn"; # or "ignore"
}
```

Expand Down Expand Up @@ -179,6 +179,7 @@ Currently, the following problem kinds are known (with more reserved to be added
- "removal": The package is planned to be removed some time in the future. Unique.
- "deprecated": The package relies on software which has reached its end of life.
- "maintainerless": Automatically generated for packages with `meta.maintainers == []`. Unique, not manually specifiable.
- "broken": Automatically generated for packages with `meta.broken = true`.

Each problem has a handler that deals with it, which can be one of "error", "warn" or "ignore".
"error" will disallow evaluating a package, while "warn" will simply print a message to the log.
Expand Down
23 changes: 1 addition & 22 deletions pkgs/stdenv/generic/check-meta.nix
Original file line number Diff line number Diff line change
Expand Up @@ -99,8 +99,6 @@ let

hasBlocklistedLicense = hasListedLicense blocklist;

allowBroken = config.allowBroken || getEnv "NIXPKGS_ALLOW_BROKEN" == "1";

allowUnsupportedSystem =
config.allowUnsupportedSystem || getEnv "NIXPKGS_ALLOW_UNSUPPORTED_SYSTEM" == "1";

Expand All @@ -121,18 +119,6 @@ let

isMarkedBroken = attrs: attrs.meta.broken or false;

# Allow granular checks to allow only some broken packages
# Example:
# { pkgs, ... }:
# {
# allowBroken = false;
# allowBrokenPredicate = pkg: builtins.elem (pkgs.lib.getName pkg) [ "hello" ];
# }
allowBrokenPredicate = config.allowBrokenPredicate or (x: false);

hasDeniedBroken =
attrs: (attrs.meta.broken or false) && !allowBroken && !allowBrokenPredicate attrs;

hasUnsupportedPlatform = pkg: !(availableOn hostPlatform pkg);

isMarkedInsecure = attrs: (attrs.meta.knownVulnerabilities or [ ]) != [ ];
Expand Down Expand Up @@ -203,7 +189,6 @@ let
allow_attr:
{
Unfree = "NIXPKGS_ALLOW_UNFREE";
Broken = "NIXPKGS_ALLOW_BROKEN";
UnsupportedSystem = "NIXPKGS_ALLOW_UNSUPPORTED_SYSTEM";
NonSource = "NIXPKGS_ALLOW_NONSOURCE";
}
Expand All @@ -212,7 +197,6 @@ let
allow_attr:
{
Unfree = "unfree packages";
Broken = "broken packages";
UnsupportedSystem = "packages that are unsupported for this system";
NonSource = "packages not built from source";
}
Expand Down Expand Up @@ -357,6 +341,7 @@ let
pkgConfigModules = listOf str;
inherit platforms;
hydraPlatforms = listOf str;
# Automatically turns into meta.problems.broken, see ./problems.nix
broken = bool;
unfree = bool;
unsupported = bool;
Expand Down Expand Up @@ -453,12 +438,6 @@ let
msg = "contains elements not built from source (‘${showSourceType attrs.meta.sourceProvenance}’)";
remediation = remediate_allowlist "NonSource" (remediate_predicate "allowNonSourcePredicate" attrs);
}
else if hasDeniedBroken attrs then
{
reason = "broken";
msg = "is marked as broken";
remediation = remediate_allowlist "Broken" "";
}
else if hasUnsupportedPlatform attrs && !allowUnsupportedSystem then
let
toPretty' = toPretty {
Expand Down
34 changes: 29 additions & 5 deletions pkgs/stdenv/generic/problems.nix
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ rec {
manual = [
"removal"
"deprecated"
"broken"
];
# Problem kinds that are currently only allowed to be specified once
unique = [
Expand All @@ -101,21 +102,40 @@ rec {
# If `description` is not defined, the derivation is probably not a package.
# Simply checking whether `meta` is defined is insufficient,
# as some fetchers and trivial builders do define meta.
attrs:
config: attrs:
# Order of checks optimised for short-circuiting the common case of having maintainers
(attrs.meta.maintainers or [ ] == [ ])
&& (attrs.meta.teams or [ ] == [ ])
&& (!attrs ? outputHash)
&& (attrs ? meta.description);
value.message = "This package has no declared maintainer, i.e. an empty `meta.maintainers` and `meta.teams` attribute.";
}
{
kindName = "broken";
condition =
config:
let
# TODO: Consider deprecating this or making it generic for all problems
allowBroken = config.allowBroken || builtins.getEnv "NIXPKGS_ALLOW_BROKEN" == "1";

allowBrokenPredicate =
if config ? allowBrokenPredicate then
lib.warnIf (lib.oldestSupportedReleaseIsAtLeast 2605)
"config.allowBrokenPredicate is deprecated, use config.problems.handlers.myPackage.broken = \"warn\" for individual packages instead."
config.allowBrokenPredicate
else
x: false;
in
attrs: attrs.meta.broken or false && !allowBroken && !allowBrokenPredicate attrs;
value.message = "This package is broken.";
}
];

genAutomaticProblems =
attrs:
config: attrs:
listToAttrs (
map (problem: lib.nameValuePair problem.kindName problem.value) (
filter (problem: problem.condition attrs) automaticProblems
filter (problem: problem.condition config attrs) automaticProblems
)
);

Expand Down Expand Up @@ -419,6 +439,10 @@ rec {
inherit (genHandlerSwitch config)
handlerForProblem
;
# Makes sure that automatic problems can cache with just config applied
automaticProblemsConfigCache = map (
problem: problem // { condition = problem.condition config; }
) automaticProblems;
in
attrs:
let
Expand All @@ -431,7 +455,7 @@ rec {
all (
problem:
problem.condition attrs -> handlerForProblem pname problem.kindName problem.kindName == "ignore"
) automaticProblems
) automaticProblemsConfigCache
&& (
# No manual problems
manualProblems == { }
Expand All @@ -445,7 +469,7 @@ rec {
else
# Slow path, only here we actually figure out which problems we need to handle
let
problems = attrs.meta.problems or { } // genAutomaticProblems attrs;
problems = attrs.meta.problems or { } // genAutomaticProblems config attrs;
problemsToHandle = filter (v: v.handler != "ignore") (
mapAttrsToList (name: problem: rec {
inherit name;
Expand Down
15 changes: 15 additions & 0 deletions pkgs/test/problems/cases/allow-broken-env/default.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{ nixpkgs }:
let
pkgs = import nixpkgs {
system = "x86_64-linux";
overlays = [ ];
config = { };
};
in
pkgs.stdenvNoCC.mkDerivation {
pname = "a";
version = "0";
meta.maintainers = [ "hello" ];
meta.description = "Some package";
meta.broken = true;
}
3 changes: 3 additions & 0 deletions pkgs/test/problems/cases/allow-broken-env/env.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
NIXPKGS_ALLOW_BROKEN = 1;
}
1 change: 1 addition & 0 deletions pkgs/test/problems/cases/allow-broken-env/expected-stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
warning: you did not specify '--add-root'; the result might be removed by the garbage collector
18 changes: 18 additions & 0 deletions pkgs/test/problems/cases/allow-broken-predicate-match/default.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{ nixpkgs }:
let
lib = pkgs.lib;
pkgs = import nixpkgs {
system = "x86_64-linux";
overlays = [ ];
config = {
allowBrokenPredicate = attrs: lib.getName attrs == "a";
};
};
in
pkgs.stdenvNoCC.mkDerivation {
pname = "a";
version = "0";
meta.maintainers = [ "hello" ];
meta.description = "Some package";
meta.broken = true;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
warning: you did not specify '--add-root'; the result might be removed by the garbage collector
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{ nixpkgs }:
let
lib = pkgs.lib;
pkgs = import nixpkgs {
system = "x86_64-linux";
overlays = [ ];
config = {
allowBrokenPredicate = attrs: lib.getName attrs == "b";
};
};
in
pkgs.stdenvNoCC.mkDerivation {
pname = "a";
version = "0";
meta.maintainers = [ "hello" ];
meta.description = "Some package";
meta.broken = true;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
(stack trace truncated; use '--show-trace' to show the full, detailed trace)

error: Refusing to evaluate package 'a-0' in /nix/store/eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee-default.nix:16 because it has problems:
- broken: This package is broken.

See also https://nixos.org/manual/nixpkgs/unstable#sec-problems
To allow evaluation regardless, use:
- Nixpkgs import: import nixpkgs { config = <below code>; }
- NixOS: nixpkgs.config = <below code>;
- nix-* commands: Put below code in ~/.config/nixpkgs/config.nix

{
problems.handlers = {
a.broken = "warn"; # or "ignore"
};
}
17 changes: 17 additions & 0 deletions pkgs/test/problems/cases/allow-broken/default.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{ nixpkgs }:
let
pkgs = import nixpkgs {
system = "x86_64-linux";
overlays = [ ];
config = {
allowBroken = true;
};
};
in
pkgs.stdenvNoCC.mkDerivation {
pname = "a";
version = "0";
meta.maintainers = [ "hello" ];
meta.description = "Some package";
meta.broken = true;
}
1 change: 1 addition & 0 deletions pkgs/test/problems/cases/allow-broken/expected-stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
warning: you did not specify '--add-root'; the result might be removed by the garbage collector
14 changes: 14 additions & 0 deletions pkgs/test/problems/cases/broken-manual/default.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{ nixpkgs }:
let
pkgs = import nixpkgs {
system = "x86_64-linux";
overlays = [ ];
config = { };
};
in
pkgs.stdenvNoCC.mkDerivation {
pname = "a";
version = "0";
meta.description = "Some package";
meta.problems.broken.message = "This package is broken because horse.";
}
16 changes: 16 additions & 0 deletions pkgs/test/problems/cases/broken-manual/expected-stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
(stack trace truncated; use '--show-trace' to show the full, detailed trace)

error: Refusing to evaluate package 'a-0' in /nix/store/eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee-default.nix:12 because it has problems:
- broken: This package is broken because horse.

See also https://nixos.org/manual/nixpkgs/unstable#sec-problems
To allow evaluation regardless, use:
- Nixpkgs import: import nixpkgs { config = <below code>; }
- NixOS: nixpkgs.config = <below code>;
- nix-* commands: Put below code in ~/.config/nixpkgs/config.nix

{
problems.handlers = {
a.broken = "warn"; # or "ignore"
};
}
14 changes: 14 additions & 0 deletions pkgs/test/problems/cases/broken/default.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{ nixpkgs }:
let
pkgs = import nixpkgs {
system = "x86_64-linux";
overlays = [ ];
config = { };
};
in
pkgs.stdenvNoCC.mkDerivation {
pname = "a";
version = "0";
meta.description = "Some package";
meta.broken = true;
}
16 changes: 16 additions & 0 deletions pkgs/test/problems/cases/broken/expected-stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
(stack trace truncated; use '--show-trace' to show the full, detailed trace)

error: Refusing to evaluate package 'a-0' in /nix/store/eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee-default.nix:12 because it has problems:
- broken: This package is broken.

See also https://nixos.org/manual/nixpkgs/unstable#sec-problems
To allow evaluation regardless, use:
- Nixpkgs import: import nixpkgs { config = <below code>; }
- NixOS: nixpkgs.config = <below code>;
- nix-* commands: Put below code in ~/.config/nixpkgs/config.nix

{
problems.handlers = {
a.broken = "warn"; # or "ignore"
};
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
(stack trace truncated; use '--show-trace' to show the full, detailed trace)

error: Refusing to evaluate package 'a-0' in /nix/store/eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee-default.nix:11 because it has an invalid meta attrset:
- a.meta.problems.invalid: Problem kind invalid, inferred from the problem name, is invalid; expected enum<removal,deprecated>. You can specify an explicit problem kind with `a.meta.problems.invalid.kind`
- a.meta.problems.invalid: Problem kind invalid, inferred from the problem name, is invalid; expected enum<removal,deprecated,broken>. You can specify an explicit problem kind with `a.meta.problems.invalid.kind`
12 changes: 11 additions & 1 deletion pkgs/test/problems/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,17 @@ lib.mapAttrs (
export NIX_STATE_DIR=$(mktemp -d)
mkdir $out

command=(

command=()
${lib.optionalString (builtins.pathExists (./cases + "/${name}/env.nix")) ''
command+=(
env
${lib.concatMapAttrsStringSep "\n" (name: value: "${name}=${toString value}") (
import (./cases + "/${name}/env.nix")
)}
)
''}
command+=(
# FIXME: Using this version because it doesn't print a trace by default
# Probably should have some regex-style error matching instead
"${lib.getBin nix}/bin/nix-instantiate"
Expand Down
4 changes: 4 additions & 0 deletions pkgs/top-level/config.nix
Original file line number Diff line number Diff line change
Expand Up @@ -498,6 +498,10 @@ in
# Put the default value for matchers in here (as in, not as an *actual* mkDefault default value),
# to force it being merged with any custom values instead of being overridden.
problems.matchers = [
{
kind = "broken";
handler = "error";
}
# Be loud and clear about package removals
{
kind = "removal";
Expand Down
Loading