about summary refs log tree commit diff
path: root/nixos/modules/services/continuous-integration/gitlab-runner.nix
diff options
context:
space:
mode:
Diffstat (limited to 'nixos/modules/services/continuous-integration/gitlab-runner.nix')
-rw-r--r--nixos/modules/services/continuous-integration/gitlab-runner.nix232
1 files changed, 195 insertions, 37 deletions
diff --git a/nixos/modules/services/continuous-integration/gitlab-runner.nix b/nixos/modules/services/continuous-integration/gitlab-runner.nix
index 62c62c5d2360e..1771ca0b980b9 100644
--- a/nixos/modules/services/continuous-integration/gitlab-runner.nix
+++ b/nixos/modules/services/continuous-integration/gitlab-runner.nix
@@ -1,7 +1,43 @@
 { config, lib, pkgs, ... }:
-with builtins;
-with lib;
+
 let
+  inherit (builtins)
+    hashString
+    map
+    substring
+    toJSON
+    toString
+    unsafeDiscardStringContext
+    ;
+
+  inherit (lib)
+    any
+    assertMsg
+    attrValues
+    concatStringsSep
+    escapeShellArg
+    filterAttrs
+    hasPrefix
+    isStorePath
+    literalExpression
+    mapAttrs'
+    mapAttrsToList
+    mkDefault
+    mkEnableOption
+    mkIf
+    mkOption
+    mkPackageOption
+    mkRemovedOptionModule
+    mkRenamedOptionModule
+    nameValuePair
+    optional
+    optionalAttrs
+    optionals
+    teams
+    toShellVar
+    types
+    ;
+
   cfg = config.services.gitlab-runner;
   hasDocker = config.virtualisation.docker.enable;
 
@@ -20,17 +56,16 @@ let
   configPath = ''"$HOME"/.gitlab-runner/config.toml'';
   configureScript = pkgs.writeShellApplication {
     name = "gitlab-runner-configure";
-    runtimeInputs = with pkgs; [
+    runtimeInputs = [ cfg.package ] ++ (with pkgs; [
         bash
         gawk
         jq
         moreutils
         remarshal
         util-linux
-        cfg.package
         perl
         python3
-    ];
+    ]);
     text = if (cfg.configFile != null) then ''
       cp ${cfg.configFile} ${configPath}
       # make config file readable by service
@@ -84,15 +119,20 @@ let
         # TODO so here we should mention NEW_SERVICES
         if [ -v 'NEW_SERVICES["${name}"]' ] ; then
           bash -c ${escapeShellArg (concatStringsSep " \\\n " ([
-            "set -a && source ${service.registrationConfigFile} &&"
+            "set -a && source ${
+              if service.registrationConfigFile != null
+              then service.registrationConfigFile
+              else service.authenticationTokenConfigFile} &&"
             "gitlab-runner register"
             "--non-interactive"
             "--name '${name}'"
             "--executor ${service.executor}"
             "--limit ${toString service.limit}"
             "--request-concurrency ${toString service.requestConcurrency}"
+          ]
+            ++ optional (service.authenticationTokenConfigFile == null)
             "--maximum-timeout ${toString service.maximumTimeout}"
-          ] ++ service.registrationFlags
+            ++ service.registrationFlags
             ++ optional (service.buildsDir != null)
             "--builds-dir ${service.buildsDir}"
             ++ optional (service.cloneUrl != null)
@@ -103,11 +143,11 @@ let
             "--pre-build-script ${service.preBuildScript}"
             ++ optional (service.postBuildScript != null)
             "--post-build-script ${service.postBuildScript}"
-            ++ optional (service.tagList != [ ])
+            ++ optional (service.authenticationTokenConfigFile == null && service.tagList != [ ])
             "--tag-list ${concatStringsSep "," service.tagList}"
-            ++ optional service.runUntagged
+            ++ optional (service.authenticationTokenConfigFile == null && service.runUntagged)
             "--run-untagged"
-            ++ optional service.protected
+            ++ optional (service.authenticationTokenConfigFile == null && service.protected)
             "--access-level ref_protected"
             ++ optional service.debugTraceDisabled
             "--debug-trace-disabled"
@@ -214,9 +254,14 @@ in {
           # nix store will be readable in runner, might be insecure
           nix = {
             # File should contain at least these two variables:
-            # `CI_SERVER_URL`
-            # `REGISTRATION_TOKEN`
+            # - `CI_SERVER_URL`
+            # - `REGISTRATION_TOKEN`
+            #
+            # NOTE: Support for runner registration tokens will be removed in GitLab 18.0.
+            # Please migrate to runner authentication tokens soon. For reference, the example
+            # runners below this one are configured with authentication tokens instead.
             registrationConfigFile = "/run/secrets/gitlab-runner-registration";
+
             dockerImage = "alpine";
             dockerVolumes = [
               "/nix/store:/nix/store:ro"
@@ -255,8 +300,9 @@ in {
           docker-images = {
             # File should contain at least these two variables:
             # `CI_SERVER_URL`
-            # `REGISTRATION_TOKEN`
-            registrationConfigFile = "/run/secrets/gitlab-runner-registration";
+            # `CI_SERVER_TOKEN`
+            authenticationTokenConfigFile = "/run/secrets/gitlab-runner-docker-images-token-env";
+
             dockerImage = "docker:stable";
             dockerVolumes = [
               "/var/run/docker.sock:/var/run/docker.sock"
@@ -269,8 +315,9 @@ in {
           shell = {
             # File should contain at least these two variables:
             # `CI_SERVER_URL`
-            # `REGISTRATION_TOKEN`
-            registrationConfigFile = "/run/secrets/gitlab-runner-registration";
+            # `CI_SERVER_TOKEN`
+            authenticationTokenConfigFile = "/run/secrets/gitlab-runner-shell-token-env";
+
             executor = "shell";
             tagList = [ "shell" ];
           };
@@ -278,30 +325,67 @@ in {
           default = {
             # File should contain at least these two variables:
             # `CI_SERVER_URL`
-            # `REGISTRATION_TOKEN`
-            registrationConfigFile = "/run/secrets/gitlab-runner-registration";
+            # `CI_SERVER_TOKEN`
+            authenticationTokenConfigFile = "/run/secrets/gitlab-runner-default-token-env";
             dockerImage = "debian:stable";
           };
         }
       '';
       type = types.attrsOf (types.submodule {
         options = {
+          authenticationTokenConfigFile = mkOption {
+            type = with types; nullOr path;
+            default = null;
+            description = ''
+              Absolute path to a file containing environment variables used for
+              gitlab-runner registrations with *runner authentication tokens*.
+              They replace the deprecated *runner registration tokens*, as
+              outlined in the [GitLab documentation].
+
+              A list of all supported environment variables can be found with
+              `gitlab-runner register --help`.
+
+              The ones you probably want to set are:
+              - `CI_SERVER_URL=<CI server URL>`
+              - `CI_SERVER_TOKEN=<runner authentication token secret>`
+
+              ::: {.warning}
+              Make sure to use a quoted absolute path,
+              or it is going to be copied to Nix Store.
+              :::
+
+              [GitLab documentation]: https://docs.gitlab.com/17.0/ee/ci/runners/new_creation_workflow.html#estimated-time-frame-for-planned-changes
+            '';
+          };
           registrationConfigFile = mkOption {
-            type = types.path;
+            type = with types; nullOr path;
+            default = null;
             description = ''
               Absolute path to a file with environment variables
-              used for gitlab-runner registration.
+              used for gitlab-runner registration with *runner registration
+              tokens*.
+
               A list of all supported environment variables can be found in
               `gitlab-runner register --help`.
 
-              Ones that you probably want to set is
+              The ones you probably want to set are:
+              - `CI_SERVER_URL=<CI server URL>`
+              - `REGISTRATION_TOKEN=<registration secret>`
 
-              `CI_SERVER_URL=<CI server URL>`
+              Support for *runner registration tokens* is deprecated since
+              GitLab 16.0, has been disabled by default in GitLab 17.0 and
+              will be removed in GitLab 18.0, as outlined in the
+              [GitLab documentation]. Please consider migrating to
+              [runner authentication tokens] and check the documentation on
+              {option}`services.gitlab-runner.services.<name>.authenticationTokenConfigFile`.
 
-              `REGISTRATION_TOKEN=<registration secret>`
-
-              WARNING: make sure to use quoted absolute path,
+              ::: {.warning}
+              Make sure to use a quoted absolute path,
               or it is going to be copied to Nix Store.
+              :::
+
+              [GitLab documentation]: https://docs.gitlab.com/17.0/ee/ci/runners/new_creation_workflow.html#estimated-time-frame-for-planned-changes
+              [runner authentication tokens]: https://docs.gitlab.com/17.0/ee/ci/runners/new_creation_workflow.html#the-new-runner-registration-workflow
             '';
           };
           registrationFlags = mkOption {
@@ -439,6 +523,9 @@ in {
             default = [ ];
             description = ''
               Tag list.
+
+              This option has no effect for runners registered with an runner
+              authentication tokens and will be ignored.
             '';
           };
           runUntagged = mkOption {
@@ -447,6 +534,9 @@ in {
             description = ''
               Register to run untagged builds; defaults to
               `true` when {option}`tagList` is empty.
+
+              This option has no effect for runners registered with an runner
+              authentication tokens and will be ignored.
             '';
           };
           limit = mkOption {
@@ -470,6 +560,9 @@ in {
             description = ''
               What is the maximum timeout (in seconds) that will be set for
               job when using this Runner. 0 (default) simply means don't limit.
+
+              This option has no effect for runners registered with an runner
+              authentication tokens and will be ignored.
             '';
           };
           protected = mkOption {
@@ -478,6 +571,9 @@ in {
             description = ''
               When set to true Runner will only run on pipelines
               triggered on protected branches.
+
+              This option has no effect for runners registered with an runner
+              authentication tokens and will be ignored.
             '';
           };
           debugTraceDisabled = mkOption {
@@ -530,9 +626,67 @@ in {
     };
   };
   config = mkIf cfg.enable {
-    warnings = mapAttrsToList
-      (n: v: "services.gitlab-runner.services.${n}.`registrationConfigFile` points to a file in Nix Store. You should use quoted absolute path to prevent this.")
-      (filterAttrs (n: v: isStorePath v.registrationConfigFile) cfg.services);
+    assertions =
+      mapAttrsToList (name: serviceConfig: {
+        assertion = serviceConfig.registrationConfigFile == null || serviceConfig.authenticationTokenConfigFile == null;
+        message = "`services.gitlab-runner.${name}.registrationConfigFile` and `services.gitlab-runner.services.${name}.authenticationTokenConfigFile` are mutually exclusive.";
+      }) cfg.services;
+
+    warnings =
+      mapAttrsToList
+        (name: serviceConfig: "services.gitlab-runner.services.${name}.`registrationConfigFile` points to a file in Nix Store. You should use quoted absolute path to prevent this.")
+        (filterAttrs (name: serviceConfig: isStorePath serviceConfig.registrationConfigFile) cfg.services)
+      ++ mapAttrsToList
+        (name: serviceConfig: "services.gitlab-runner.services.${name}.`authenticationTokenConfigFile` points to a file in Nix Store. You should use quoted absolute path to prevent this.")
+        (filterAttrs (name: serviceConfig: isStorePath serviceConfig.authenticationTokenConfigFile) cfg.services)
+      ++ mapAttrsToList
+        (name: serviceConfig: ''
+          Runner registration tokens have been deprecated and disabled by default in GitLab >= 17.0.
+          Consider migrating to runner authentication tokens by setting `services.gitlab-runner.services.${name}.authenticationTokenConfigFile`.
+          https://docs.gitlab.com/17.0/ee/ci/runners/new_creation_workflow.html''
+        )
+        (
+          filterAttrs (name: serviceConfig:
+            serviceConfig.authenticationTokenConfigFile == null
+          ) cfg.services
+        )
+      ++ mapAttrsToList
+        (name: serviceConfig: ''
+          `services.gitlab-runner.services.${name}.protected` with runner authentication tokens has no effect and will be ignored. Please remove it from your configuration.''
+        )
+        (
+          filterAttrs (name: serviceConfig:
+            serviceConfig.authenticationTokenConfigFile != null && serviceConfig.protected == true
+          ) cfg.services
+        )
+      ++ mapAttrsToList
+        (name: serviceConfig: ''
+          `services.gitlab-runner.services.${name}.runUntagged` with runner authentication tokens has no effect and will be ignored. Please remove it from your configuration.''
+        )
+        (
+          filterAttrs (name: serviceConfig:
+            serviceConfig.authenticationTokenConfigFile != null && serviceConfig.runUntagged == true
+          ) cfg.services
+        )
+      ++ mapAttrsToList
+        (name: v: ''
+          `services.gitlab-runner.services.${name}.maximumTimeout` with runner authentication tokens has no effect and will be ignored. Please remove it from your configuration.''
+        )
+        (
+          filterAttrs (name: serviceConfig:
+            serviceConfig.authenticationTokenConfigFile != null && serviceConfig.maximumTimeout != 0
+          ) cfg.services
+        )
+      ++ mapAttrsToList
+        (name: v: ''
+          `services.gitlab-runner.services.${name}.tagList` with runner authentication tokens has no effect and will be ignored. Please remove it from your configuration.''
+        )
+        (
+          filterAttrs (serviceName: serviceConfig:
+            serviceConfig.authenticationTokenConfigFile != null && serviceConfig.tagList != [ ]
+          ) cfg.services
+        )
+      ;
 
     environment.systemPackages = [ cfg.package ];
     systemd.services.gitlab-runner = {
@@ -545,15 +699,19 @@ in {
       environment = config.networking.proxy.envVars // {
         HOME = "/var/lib/gitlab-runner";
       };
-      path = with pkgs; [
-        bash
-        gawk
-        jq
-        moreutils
-        remarshal
-        util-linux
-        cfg.package
-      ] ++ cfg.extraPackages;
+
+      path =
+        (with pkgs; [
+          bash
+          gawk
+          jq
+          moreutils
+          remarshal
+          util-linux
+        ])
+        ++ [ cfg.package ]
+        ++ cfg.extraPackages;
+
       reloadIfChanged = true;
       serviceConfig = {
         # Set `DynamicUser` under `systemd.services.gitlab-runner.serviceConfig`