about summary refs log tree commit diff
path: root/nixos
diff options
context:
space:
mode:
authorRobert Hensing <roberth@users.noreply.github.com>2023-05-23 14:17:28 +0200
committerGitHub <noreply@github.com>2023-05-23 14:17:28 +0200
commit983bf78c16a81a8508a92d8cf304e7bfce35c773 (patch)
tree18a9247456c1fadab17aa105d9a8bccc146ce6c5 /nixos
parente89ce0502750f0e85d2756059caca1ce50d60e2c (diff)
parentb419a39f1f3283264ee63845cdcd526db10facae (diff)
downloadnixlib-983bf78c16a81a8508a92d8cf304e7bfce35c773.tar
nixlib-983bf78c16a81a8508a92d8cf304e7bfce35c773.tar.gz
nixlib-983bf78c16a81a8508a92d8cf304e7bfce35c773.tar.bz2
nixlib-983bf78c16a81a8508a92d8cf304e7bfce35c773.tar.lz
nixlib-983bf78c16a81a8508a92d8cf304e7bfce35c773.tar.xz
nixlib-983bf78c16a81a8508a92d8cf304e7bfce35c773.tar.zst
nixlib-983bf78c16a81a8508a92d8cf304e7bfce35c773.zip
Merge pull request #233397 from Kranzes/hci-module
nixos/hercules-ci-agent: sync module with upstream
Diffstat (limited to 'nixos')
-rw-r--r--nixos/modules/services/continuous-integration/hercules-ci-agent/common.nix203
-rw-r--r--nixos/modules/services/continuous-integration/hercules-ci-agent/default.nix8
-rw-r--r--nixos/modules/services/continuous-integration/hercules-ci-agent/settings.nix153
3 files changed, 188 insertions, 176 deletions
diff --git a/nixos/modules/services/continuous-integration/hercules-ci-agent/common.nix b/nixos/modules/services/continuous-integration/hercules-ci-agent/common.nix
index 663f3df775c3..ea9b5ffbf43c 100644
--- a/nixos/modules/services/continuous-integration/hercules-ci-agent/common.nix
+++ b/nixos/modules/services/continuous-integration/hercules-ci-agent/common.nix
@@ -10,171 +10,18 @@
 let
   inherit (lib)
     filterAttrs
-    literalMD
     literalExpression
     mkIf
     mkOption
     mkRemovedOptionModule
     mkRenamedOptionModule
     types
-    ;
-
-  cfg =
-    config.services.hercules-ci-agent;
-
-  format = pkgs.formats.toml { };
-
-  settingsModule = { config, ... }: {
-    freeformType = format.type;
-    options = {
-      apiBaseUrl = mkOption {
-        description = lib.mdDoc ''
-          API base URL that the agent will connect to.
-
-          When using Hercules CI Enterprise, set this to the URL where your
-          Hercules CI server is reachable.
-        '';
-        type = types.str;
-        default = "https://hercules-ci.com";
-      };
-      baseDirectory = mkOption {
-        type = types.path;
-        default = "/var/lib/hercules-ci-agent";
-        description = lib.mdDoc ''
-          State directory (secrets, work directory, etc) for agent
-        '';
-      };
-      concurrentTasks = mkOption {
-        description = lib.mdDoc ''
-          Number of tasks to perform simultaneously.
-
-          A task is a single derivation build, an evaluation or an effect run.
-          At minimum, you need 2 concurrent tasks for `x86_64-linux`
-          in your cluster, to allow for import from derivation.
-
-          `concurrentTasks` can be around the CPU core count or lower if memory is
-          the bottleneck.
-
-          The optimal value depends on the resource consumption characteristics of your workload,
-          including memory usage and in-task parallelism. This is typically determined empirically.
-
-          When scaling, it is generally better to have a double-size machine than two machines,
-          because each split of resources causes inefficiencies; particularly with regards
-          to build latency because of extra downloads.
-        '';
-        type = types.either types.ints.positive (types.enum [ "auto" ]);
-        default = "auto";
-      };
-      labels = mkOption {
-        description = lib.mdDoc ''
-          A key-value map of user data.
-
-          This data will be available to organization members in the dashboard and API.
-
-          The values can be of any TOML type that corresponds to a JSON type, but arrays
-          can not contain tables/objects due to limitations of the TOML library. Values
-          involving arrays of non-primitive types may not be representable currently.
-        '';
-        type = format.type;
-        defaultText = literalExpression ''
-          {
-            agent.source = "..."; # One of "nixpkgs", "flake", "override"
-            lib.version = "...";
-            pkgs.version = "...";
-          }
-        '';
-      };
-      workDirectory = mkOption {
-        description = lib.mdDoc ''
-          The directory in which temporary subdirectories are created for task state. This includes sources for Nix evaluation.
-        '';
-        type = types.path;
-        default = config.baseDirectory + "/work";
-        defaultText = literalExpression ''baseDirectory + "/work"'';
-      };
-      staticSecretsDirectory = mkOption {
-        description = lib.mdDoc ''
-          This is the default directory to look for statically configured secrets like `cluster-join-token.key`.
-
-          See also `clusterJoinTokenPath` and `binaryCachesPath` for fine-grained configuration.
-        '';
-        type = types.path;
-        default = config.baseDirectory + "/secrets";
-        defaultText = literalExpression ''baseDirectory + "/secrets"'';
-      };
-      clusterJoinTokenPath = mkOption {
-        description = lib.mdDoc ''
-          Location of the cluster-join-token.key file.
 
-          You can retrieve the contents of the file when creating a new agent via
-          <https://hercules-ci.com/dashboard>.
-
-          As this value is confidential, it should not be in the store, but
-          installed using other means, such as agenix, NixOps
-          `deployment.keys`, or manual installation.
-
-          The contents of the file are used for authentication between the agent and the API.
-        '';
-        type = types.path;
-        default = config.staticSecretsDirectory + "/cluster-join-token.key";
-        defaultText = literalExpression ''staticSecretsDirectory + "/cluster-join-token.key"'';
-      };
-      binaryCachesPath = mkOption {
-        description = lib.mdDoc ''
-          Path to a JSON file containing binary cache secret keys.
-
-          As these values are confidential, they should not be in the store, but
-          copied over using other means, such as agenix, NixOps
-          `deployment.keys`, or manual installation.
-
-          The format is described on <https://docs.hercules-ci.com/hercules-ci-agent/binary-caches-json/>.
-        '';
-        type = types.path;
-        default = config.staticSecretsDirectory + "/binary-caches.json";
-        defaultText = literalExpression ''staticSecretsDirectory + "/binary-caches.json"'';
-      };
-      secretsJsonPath = mkOption {
-        description = lib.mdDoc ''
-          Path to a JSON file containing secrets for effects.
-
-          As these values are confidential, they should not be in the store, but
-          copied over using other means, such as agenix, NixOps
-          `deployment.keys`, or manual installation.
-
-          The format is described on <https://docs.hercules-ci.com/hercules-ci-agent/secrets-json/>.
-        '';
-        type = types.path;
-        default = config.staticSecretsDirectory + "/secrets.json";
-        defaultText = literalExpression ''staticSecretsDirectory + "/secrets.json"'';
-      };
-    };
-  };
+    ;
 
-  # TODO (roberth, >=2022) remove
-  checkNix =
-    if !cfg.checkNix
-    then ""
-    else if lib.versionAtLeast config.nix.package.version "2.3.10"
-    then ""
-    else
-      pkgs.stdenv.mkDerivation {
-        name = "hercules-ci-check-system-nix-src";
-        inherit (config.nix.package) src patches;
-        dontConfigure = true;
-        buildPhase = ''
-          echo "Checking in-memory pathInfoCache expiry"
-          if ! grep 'PathInfoCacheValue' src/libstore/store-api.hh >/dev/null; then
-            cat 1>&2 <<EOF
+  cfg = config.services.hercules-ci-agent;
 
-            You are deploying Hercules CI Agent on a system with an incompatible
-            nix-daemon. Please make sure nix.package is set to a Nix version of at
-            least 2.3.10 or a master version more recent than Mar 12, 2020.
-          EOF
-            exit 1
-          fi
-        '';
-        installPhase = "touch $out";
-      };
+  inherit (import ./settings.nix { inherit pkgs lib; }) format settingsModule;
 
 in
 {
@@ -198,15 +45,6 @@ in
         Support is available at [help@hercules-ci.com](mailto:help@hercules-ci.com).
       '';
     };
-    checkNix = mkOption {
-      type = types.bool;
-      default = true;
-      description = lib.mdDoc ''
-        Whether to make sure that the system's Nix (nix-daemon) is compatible.
-
-        If you set this to false, please keep up with the change log.
-      '';
-    };
     package = mkOption {
       description = lib.mdDoc ''
         Package containing the bin/hercules-ci-agent executable.
@@ -235,7 +73,7 @@ in
     tomlFile = mkOption {
       type = types.path;
       internal = true;
-      defaultText = literalMD "generated `hercules-ci-agent.toml`";
+      defaultText = lib.literalMD "generated `hercules-ci-agent.toml`";
       description = lib.mdDoc ''
         The fully assembled config file.
       '';
@@ -243,7 +81,27 @@ in
   };
 
   config = mkIf cfg.enable {
-    nix.extraOptions = lib.addContextFrom checkNix ''
+    # Make sure that nix.extraOptions does not override trusted-users
+    assertions = [
+      {
+        assertion =
+          (cfg.settings.nixUserIsTrusted or false) ->
+          builtins.match ".*(^|\n)[ \t]*trusted-users[ \t]*=.*" config.nix.extraOptions == null;
+        message = ''
+          hercules-ci-agent: Please do not set `trusted-users` in `nix.extraOptions`.
+
+          The hercules-ci-agent module by default relies on `nix.settings.trusted-users`
+          to be effectful, but a line like `trusted-users = ...` in `nix.extraOptions`
+          will override the value set in `nix.settings.trusted-users`.
+
+          Instead of setting `trusted-users` in the `nix.extraOptions` string, you should
+          set an option with additive semantics, such as
+           - the NixOS option `nix.settings.trusted-users`, or
+           - the Nix option in the `extraOptions` string, `extra-trusted-users`
+        '';
+      }
+    ];
+    nix.extraOptions = ''
       # A store path that was missing at first may well have finished building,
       # even shortly after the previous lookup. This *also* applies to the daemon.
       narinfo-cache-negative-ttl = 0
@@ -251,14 +109,9 @@ in
     services.hercules-ci-agent = {
       tomlFile =
         format.generate "hercules-ci-agent.toml" cfg.settings;
-
-      settings.labels = {
-        agent.source =
-          if options.services.hercules-ci-agent.package.highestPrio == (lib.modules.mkOptionDefault { }).priority
-          then "nixpkgs"
-          else lib.mkOptionDefault "override";
-        pkgs.version = pkgs.lib.version;
-        lib.version = lib.version;
+      settings.config._module.args = {
+        packageOption = options.services.hercules-ci-agent.package;
+        inherit pkgs;
       };
     };
   };
diff --git a/nixos/modules/services/continuous-integration/hercules-ci-agent/default.nix b/nixos/modules/services/continuous-integration/hercules-ci-agent/default.nix
index e28493ce7767..ad26b5316dde 100644
--- a/nixos/modules/services/continuous-integration/hercules-ci-agent/default.nix
+++ b/nixos/modules/services/continuous-integration/hercules-ci-agent/default.nix
@@ -36,8 +36,14 @@ in
         Restart = "on-failure";
         RestartSec = 120;
 
-        LimitSTACK = 256 * 1024 * 1024;
+        # If a worker goes OOM, don't kill the main process. It needs to
+        # report the failure and it's unlikely to be part of the problem.
         OOMPolicy = "continue";
+
+        # Work around excessive stack use by libstdc++ regex
+        # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86164
+        # A 256 MiB stack allows between 400 KiB and 1.5 MiB file to be matched by ".*".
+        LimitSTACK = 256 * 1024 * 1024;
       };
     };
 
diff --git a/nixos/modules/services/continuous-integration/hercules-ci-agent/settings.nix b/nixos/modules/services/continuous-integration/hercules-ci-agent/settings.nix
new file mode 100644
index 000000000000..8eb902313ee8
--- /dev/null
+++ b/nixos/modules/services/continuous-integration/hercules-ci-agent/settings.nix
@@ -0,0 +1,153 @@
+# Not a module
+{ pkgs, lib }:
+let
+  inherit (lib)
+    types
+    literalExpression
+    mkOption
+    ;
+
+  format = pkgs.formats.toml { };
+
+  settingsModule = { config, packageOption, pkgs, ... }: {
+    freeformType = format.type;
+    options = {
+      apiBaseUrl = mkOption {
+        description = lib.mdDoc ''
+          API base URL that the agent will connect to.
+
+          When using Hercules CI Enterprise, set this to the URL where your
+          Hercules CI server is reachable.
+        '';
+        type = types.str;
+        default = "https://hercules-ci.com";
+      };
+      baseDirectory = mkOption {
+        type = types.path;
+        default = "/var/lib/hercules-ci-agent";
+        description = lib.mdDoc ''
+          State directory (secrets, work directory, etc) for agent
+        '';
+      };
+      concurrentTasks = mkOption {
+        description = lib.mdDoc ''
+          Number of tasks to perform simultaneously.
+
+          A task is a single derivation build, an evaluation or an effect run.
+          At minimum, you need 2 concurrent tasks for `x86_64-linux`
+          in your cluster, to allow for import from derivation.
+
+          `concurrentTasks` can be around the CPU core count or lower if memory is
+          the bottleneck.
+
+          The optimal value depends on the resource consumption characteristics of your workload,
+          including memory usage and in-task parallelism. This is typically determined empirically.
+
+          When scaling, it is generally better to have a double-size machine than two machines,
+          because each split of resources causes inefficiencies; particularly with regards
+          to build latency because of extra downloads.
+        '';
+        type = types.either types.ints.positive (types.enum [ "auto" ]);
+        default = "auto";
+        defaultText = lib.literalMD ''
+          `"auto"`, meaning equal to the number of CPU cores.
+        '';
+      };
+      labels = mkOption {
+        description = lib.mdDoc ''
+          A key-value map of user data.
+
+          This data will be available to organization members in the dashboard and API.
+
+          The values can be of any TOML type that corresponds to a JSON type, but arrays
+          can not contain tables/objects due to limitations of the TOML library. Values
+          involving arrays of non-primitive types may not be representable currently.
+        '';
+        type = format.type;
+        defaultText = literalExpression ''
+          {
+            agent.source = "..."; # One of "nixpkgs", "flake", "override"
+            lib.version = "...";
+            pkgs.version = "...";
+          }
+        '';
+      };
+      workDirectory = mkOption {
+        description = lib.mdDoc ''
+          The directory in which temporary subdirectories are created for task state. This includes sources for Nix evaluation.
+        '';
+        type = types.path;
+        default = config.baseDirectory + "/work";
+        defaultText = literalExpression ''baseDirectory + "/work"'';
+      };
+      staticSecretsDirectory = mkOption {
+        description = lib.mdDoc ''
+          This is the default directory to look for statically configured secrets like `cluster-join-token.key`.
+
+          See also `clusterJoinTokenPath` and `binaryCachesPath` for fine-grained configuration.
+        '';
+        type = types.path;
+        default = config.baseDirectory + "/secrets";
+        defaultText = literalExpression ''baseDirectory + "/secrets"'';
+      };
+      clusterJoinTokenPath = mkOption {
+        description = lib.mdDoc ''
+          Location of the cluster-join-token.key file.
+
+          You can retrieve the contents of the file when creating a new agent via
+          <https://hercules-ci.com/dashboard>.
+
+          As this value is confidential, it should not be in the store, but
+          installed using other means, such as agenix, NixOps
+          `deployment.keys`, or manual installation.
+
+          The contents of the file are used for authentication between the agent and the API.
+        '';
+        type = types.path;
+        default = config.staticSecretsDirectory + "/cluster-join-token.key";
+        defaultText = literalExpression ''staticSecretsDirectory + "/cluster-join-token.key"'';
+      };
+      binaryCachesPath = mkOption {
+        description = lib.mdDoc ''
+          Path to a JSON file containing binary cache secret keys.
+
+          As these values are confidential, they should not be in the store, but
+          copied over using other means, such as agenix, NixOps
+          `deployment.keys`, or manual installation.
+
+          The format is described on <https://docs.hercules-ci.com/hercules-ci-agent/binary-caches-json/>.
+        '';
+        type = types.path;
+        default = config.staticSecretsDirectory + "/binary-caches.json";
+        defaultText = literalExpression ''staticSecretsDirectory + "/binary-caches.json"'';
+      };
+      secretsJsonPath = mkOption {
+        description = lib.mdDoc ''
+          Path to a JSON file containing secrets for effects.
+
+          As these values are confidential, they should not be in the store, but
+          copied over using other means, such as agenix, NixOps
+          `deployment.keys`, or manual installation.
+
+          The format is described on <https://docs.hercules-ci.com/hercules-ci-agent/secrets-json/>.
+        '';
+        type = types.path;
+        default = config.staticSecretsDirectory + "/secrets.json";
+        defaultText = literalExpression ''staticSecretsDirectory + "/secrets.json"'';
+      };
+    };
+    config = {
+      labels = {
+        agent.source =
+          if packageOption.highestPrio == (lib.modules.mkOptionDefault { }).priority
+          then "nixpkgs"
+          else lib.mkOptionDefault "override";
+        pkgs.version = pkgs.lib.version;
+        lib.version = lib.version;
+      };
+    };
+  };
+in
+{
+  inherit format settingsModule;
+}