summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--nixos/doc/manual/from_md/release-notes/rl-2211.section.xml8
-rw-r--r--nixos/doc/manual/release-notes/rl-2211.section.md3
-rw-r--r--pkgs/stdenv/generic/check-meta.nix45
-rw-r--r--pkgs/top-level/config.nix7
4 files changed, 50 insertions, 13 deletions
diff --git a/nixos/doc/manual/from_md/release-notes/rl-2211.section.xml b/nixos/doc/manual/from_md/release-notes/rl-2211.section.xml
index 0f1dffc798e..8f4a7dd002d 100644
--- a/nixos/doc/manual/from_md/release-notes/rl-2211.section.xml
+++ b/nixos/doc/manual/from_md/release-notes/rl-2211.section.xml
@@ -476,6 +476,14 @@
       </listitem>
       <listitem>
         <para>
+          The (previously undocumented) Nixpkgs configuration option
+          <literal>checkMeta</literal> now defaults to
+          <literal>true</literal>. This may cause evaluation failures
+          for packages with incorrect <literal>meta</literal> attribute.
+        </para>
+      </listitem>
+      <listitem>
+        <para>
           xow package removed along with the
           <literal>hardware.xow</literal> module, due to the project
           being deprecated in favor of <literal>xone</literal>, which is
diff --git a/nixos/doc/manual/release-notes/rl-2211.section.md b/nixos/doc/manual/release-notes/rl-2211.section.md
index 7214937781d..f6515256dbc 100644
--- a/nixos/doc/manual/release-notes/rl-2211.section.md
+++ b/nixos/doc/manual/release-notes/rl-2211.section.md
@@ -164,6 +164,9 @@ Available as [services.patroni](options.html#opt-services.patroni.enable).
 
 - riak package removed along with `services.riak` module, due to lack of maintainer to update the package.
 
+- The (previously undocumented) Nixpkgs configuration option `checkMeta` now defaults to `true`. This may cause evaluation
+  failures for packages with incorrect `meta` attribute.
+
 - xow package removed along with the `hardware.xow` module, due to the project being deprecated in favor of `xone`,  which is available via the `hardware.xone` module.
 
 - dd-agent package removed along with the `services.dd-agent` module, due to the project being deprecated in favor of `datadog-agent`,  which is available via the `services.datadog-agent` module.
diff --git a/pkgs/stdenv/generic/check-meta.nix b/pkgs/stdenv/generic/check-meta.nix
index f9bea506af6..85a9c9c4d41 100644
--- a/pkgs/stdenv/generic/check-meta.nix
+++ b/pkgs/stdenv/generic/check-meta.nix
@@ -13,10 +13,6 @@ let
 
   getName = attrs: attrs.name or ("${attrs.pname or "«name-missing»"}-${attrs.version or "«version-missing»"}");
 
-  # See discussion at https://github.com/NixOS/nixpkgs/pull/25304#issuecomment-298385426
-  # for why this defaults to false, but I (@copumpkin) want to default it to true soon.
-  shouldCheckMeta = config.checkMeta or false;
-
   allowUnfree = config.allowUnfree
     || builtins.getEnv "NIXPKGS_ALLOW_UNFREE" == "1";
 
@@ -248,6 +244,16 @@ let
       isEnabled = lib.findFirst (x: x == reason) null showWarnings;
     in if isEnabled != null then builtins.trace msg true else true;
 
+
+  # A shallow type check. We are using NixOS'
+  # option types here, which however have the major drawback
+  # of not providing full type checking (part of the type check is
+  # done by the module evaluation itself). Therefore, the checks
+  # will not recurse into attributes.
+  # We still provide the full type for documentation
+  # purposes and in the hope that they will be used eventually.
+  # See https://github.com/NixOS/nixpkgs/pull/191171 for an attempt
+  # to fix this, or mkOptionType in lib/types.nix for more information.
   metaTypes = with lib.types; rec {
     # These keys are documented
     description = str;
@@ -297,17 +303,23 @@ let
     badPlatforms = platforms;
   };
 
+  # WARNING: this does not check inner values of the attribute, like list elements or nested attributes.
+  # See metaTypes above and mkOptionType in lib/types.nix for more information
   checkMetaAttr = k: v:
     if metaTypes?${k} then
-      if metaTypes.${k}.check v then null else "key '${k}' has a value ${toString v} of an invalid type ${builtins.typeOf v}; expected ${metaTypes.${k}.description}"
-    else "key '${k}' is unrecognized; expected one of: \n\t      [${lib.concatMapStringsSep ", " (x: "'${x}'") (lib.attrNames metaTypes)}]";
-  checkMeta = meta: if shouldCheckMeta then lib.remove null (lib.mapAttrsToList checkMetaAttr meta) else [];
+      if metaTypes.${k}.check v then
+        null
+      else
+        "key 'meta.${k}' has a value of invalid type ${builtins.typeOf v}; expected ${metaTypes.${k}.description}"
+    else
+      "key 'meta.${k}' is unrecognized; expected one of: \n\t      [${lib.concatMapStringsSep ", " (x: "'${x}'") (lib.attrNames metaTypes)}]";
+  checkMeta = meta: if config.checkMeta then lib.remove null (lib.mapAttrsToList checkMetaAttr meta) else [];
 
   checkOutputsToInstall = attrs: let
       expectedOutputs = attrs.meta.outputsToInstall or [];
       actualOutputs = attrs.outputs or [ "out" ];
       missingOutputs = builtins.filter (output: ! builtins.elem output actualOutputs) expectedOutputs;
-    in if shouldCheckMeta
+    in if config.checkMeta
        then builtins.length missingOutputs > 0
        else false;
 
@@ -326,7 +338,17 @@ let
       unsupported = hasUnsupportedPlatform attrs;
       insecure = isMarkedInsecure attrs;
     }
-    // (if hasDeniedUnfreeLicense attrs && !(hasAllowlistedLicense attrs) then
+    // (
+    # Check meta attribute types first, to make sure it is always called even when there are other issues
+    # Note that this is not a full type check and functions below still need to by careful about their inputs!
+    let res = checkMeta (attrs.meta or {}); in if res != [] then
+      { valid = "no"; reason = "unknown-meta"; errormsg = "has an invalid meta attrset:${lib.concatMapStrings (x: "\n\t - " + x) res}"; }
+    # --- Put checks that cannot be ignored here ---
+    else if checkOutputsToInstall attrs then
+      { valid = "no"; reason = "broken-outputs"; errormsg = "has invalid meta.outputsToInstall"; }
+
+    # --- Put checks that can be ignored here ---
+    else if hasDeniedUnfreeLicense attrs && !(hasAllowlistedLicense attrs) then
       { valid = "no"; reason = "unfree"; errormsg = "has an unfree license (‘${showLicense attrs.meta.license}’)"; }
     else if hasBlocklistedLicense attrs then
       { valid = "no"; reason = "blocklisted"; errormsg = "has a blocklisted license (‘${showLicense attrs.meta.license}’)"; }
@@ -338,10 +360,7 @@ let
       { valid = "no"; reason = "unsupported"; errormsg = "is not supported on ‘${hostPlatform.system}’"; }
     else if !(hasAllowedInsecure attrs) then
       { valid = "no"; reason = "insecure"; errormsg = "is marked as insecure"; }
-    else if checkOutputsToInstall attrs then
-      { valid = "no"; reason = "broken-outputs"; errormsg = "has invalid meta.outputsToInstall"; }
-    else let res = checkMeta (attrs.meta or {}); in if res != [] then
-      { valid = "no"; reason = "unknown-meta"; errormsg = "has an invalid meta attrset:${lib.concatMapStrings (x: "\n\t - " + x) res}"; }
+
     # --- warnings ---
     # Please also update the type in /pkgs/top-level/config.nix alongside this.
     else if hasNoMaintainers attrs then
diff --git a/pkgs/top-level/config.nix b/pkgs/top-level/config.nix
index 4fedad00f24..6ddd647a2b1 100644
--- a/pkgs/top-level/config.nix
+++ b/pkgs/top-level/config.nix
@@ -128,6 +128,13 @@ let
       '';
     };
 
+    checkMeta = mkOption {
+      type = types.bool;
+      default = true;
+      description = ''
+        Whether to check that the `meta` attribute of derivations are correct during evaluation time.
+      '';
+    };
   };
 
 in {