summaryrefslogtreecommitdiff
path: root/modules/services/github-runner
diff options
context:
space:
mode:
authorMike Vink <59492084+ivi-vink@users.noreply.github.com>2025-01-16 22:22:34 +0100
committerGitHub <noreply@github.com>2025-01-16 22:22:34 +0100
commit8e7bd91f353caacc0bc4105f573eb3e17f09e03a (patch)
treec5059edcbebd9644290cad7c653c49a36d593021 /modules/services/github-runner
parent6bd39d420578aacf7c0bab7de3e7027b952115ae (diff)
parentbd921223ba7cdac346477d7ea5204d6f4736fcc6 (diff)
Merge branch 'LnL7:master' into masterHEADmaster
Diffstat (limited to 'modules/services/github-runner')
-rw-r--r--modules/services/github-runner/options.nix49
-rw-r--r--modules/services/github-runner/service.nix50
2 files changed, 62 insertions, 37 deletions
diff --git a/modules/services/github-runner/options.nix b/modules/services/github-runner/options.nix
index 300ca32..5152cc4 100644
--- a/modules/services/github-runner/options.nix
+++ b/modules/services/github-runner/options.nix
@@ -3,10 +3,12 @@
, ...
}:
-with lib;
+let
+ inherit (lib) literalExpression mkOption mkPackageOption types;
+in
{
options.services.github-runners = mkOption {
- description = mdDoc ''
+ description = ''
Multiple GitHub Runners.
If `user` and `group` are set to `null`, the module will configure nix-darwin to
@@ -22,12 +24,12 @@ with lib;
* `/var/lib/github-runners/<name>`:
State directory to store the runner registration credentials
+ * `/var/lib/github-runners/_work/<name>`:
+ Working directory for workflow files. The runner only uses this
+ directory if `workDir` is `null` (see the `workDir` option for details).
* `/var/log/github-runners/<name>`:
The launchd service writes the stdout and stderr streams to this
directory.
- * `/var/run/github-runners/<name>`:
- Working directory for workflow files. The runner only uses this
- directory if `workDir` is `null` (see the `workDir` option for details).
'';
example = {
runner1 = {
@@ -50,7 +52,7 @@ with lib;
enable = mkOption {
default = false;
example = true;
- description = mdDoc ''
+ description = ''
Whether to enable GitHub Actions runner.
Note: GitHub recommends using self-hosted runners with private repositories only. Learn more here:
@@ -61,7 +63,7 @@ with lib;
url = mkOption {
type = types.str;
- description = mdDoc ''
+ description = ''
Repository to add the runner to.
Changing this option triggers a new runner registration.
@@ -79,7 +81,7 @@ with lib;
tokenFile = mkOption {
type = types.path;
- description = mdDoc ''
+ description = ''
The full path to a file which contains either
* a fine-grained personal access token (PAT),
@@ -88,6 +90,9 @@ with lib;
Changing this option or the `tokenFile`’s content triggers a new runner registration.
+ You can also manually trigger a new runner registration by deleting
+ {file}`/var/lib/github-runners/<name>/.runner` and restarting the service.
+
We suggest using the fine-grained PATs. A runner registration token is valid
only for 1 hour after creation, so the next time the runner configuration changes
this will give you hard-to-debug HTTP 404 errors in the configure step.
@@ -122,7 +127,7 @@ with lib;
name = mkOption {
type = types.nullOr types.str;
- description = mdDoc ''
+ description = ''
Name of the runner to configure. If null, defaults to the hostname.
Changing this option triggers a new runner registration.
@@ -133,7 +138,7 @@ with lib;
runnerGroup = mkOption {
type = types.nullOr types.str;
- description = mdDoc ''
+ description = ''
Name of the runner group to add this runner to (defaults to the default runner group).
Changing this option triggers a new runner registration.
@@ -143,7 +148,7 @@ with lib;
extraLabels = mkOption {
type = types.listOf types.str;
- description = mdDoc ''
+ description = ''
Extra labels in addition to the default (unless disabled through the `noDefaultLabels` option).
Changing this option triggers a new runner registration.
@@ -154,7 +159,7 @@ with lib;
noDefaultLabels = mkOption {
type = types.bool;
- description = mdDoc ''
+ description = ''
Disables adding the default labels. Also see the `extraLabels` option.
Changing this option triggers a new runner registration.
@@ -164,7 +169,7 @@ with lib;
replace = mkOption {
type = types.bool;
- description = mdDoc ''
+ description = ''
Replace any existing runner with the same name.
Without this flag, registering a new runner with the same name fails.
@@ -174,7 +179,7 @@ with lib;
extraPackages = mkOption {
type = types.listOf types.package;
- description = mdDoc ''
+ description = ''
Extra packages to add to `PATH` of the service to make them available to workflows.
'';
default = [ ];
@@ -182,7 +187,7 @@ with lib;
extraEnvironment = mkOption {
type = types.attrs;
- description = mdDoc ''
+ description = ''
Extra environment variables to set for the runner, as an attrset.
'';
example = {
@@ -193,17 +198,17 @@ with lib;
serviceOverrides = mkOption {
type = types.attrs;
- description = mdDoc ''
+ description = ''
Modify the service. Can be used to, e.g., adjust the sandboxing options.
'';
default = { };
};
- package = mkPackageOptionMD pkgs "github-runner" { };
+ package = mkPackageOption pkgs "github-runner" { };
ephemeral = mkOption {
type = types.bool;
- description = mdDoc ''
+ description = ''
If enabled, causes the following behavior:
- Passes the `--ephemeral` flag to the runner configuration script
@@ -222,7 +227,7 @@ with lib;
user = mkOption {
type = types.nullOr types.str;
- description = mdDoc ''
+ description = ''
User under which to run the service.
If this option and the `group` option is set to `null`, nix-darwin creates
@@ -234,7 +239,7 @@ with lib;
group = mkOption {
type = types.nullOr types.str;
- description = mdDoc ''
+ description = ''
Group under which to run the service.
If this option and the `user` option is set to `null`, nix-darwin creates
@@ -246,7 +251,7 @@ with lib;
workDir = mkOption {
type = with types; nullOr str;
- description = mdDoc ''
+ description = ''
Working directory, available as `$GITHUB_WORKSPACE` during workflow runs
and used as a default for [repository checkouts](https://github.com/actions/checkout).
The service cleans this directory on every service start.
@@ -259,7 +264,7 @@ with lib;
nodeRuntimes = mkOption {
type = with types; nonEmptyListOf (enum [ "node20" ]);
default = [ "node20" ];
- description = mdDoc ''
+ description = ''
List of Node.js runtimes the runner should support.
'';
};
diff --git a/modules/services/github-runner/service.nix b/modules/services/github-runner/service.nix
index 53f2cdd..029f863 100644
--- a/modules/services/github-runner/service.nix
+++ b/modules/services/github-runner/service.nix
@@ -1,10 +1,14 @@
{ config, lib, pkgs, ... }:
-with lib;
+
let
+ inherit (lib) any attrValues boolToString concatStringsSep escapeShellArg
+ flatten flip getExe getExe' hasAttr hasPrefix mapAttrsToList mapAttrs' mkBefore
+ mkDefault mkIf mkMerge nameValuePair optionalAttrs optionalString replaceStrings;
+
mkSvcName = name: "github-runner-${name}";
mkStateDir = cfg: "/var/lib/github-runners/${cfg.name}";
mkLogDir = cfg: "/var/log/github-runners/${cfg.name}";
- mkWorkDir = cfg: if (cfg.workDir != null) then cfg.workDir else "/var/run/github-runners/${cfg.name}";
+ mkWorkDir = cfg: if (cfg.workDir != null) then cfg.workDir else "/var/lib/github-runners/_work/${cfg.name}";
in
{
config.assertions = flatten (
@@ -17,6 +21,10 @@ in
assertion = !cfg.noDefaultLabels || (cfg.extraLabels != [ ]);
message = "`services.github-runners.${name}`: The `extraLabels` option is mandatory if `noDefaultLabels` is set";
}
+ {
+ assertion = cfg.workDir == null || !(hasPrefix "/run/" cfg.workDir || hasPrefix "/var/run/" cfg.workDir || hasPrefix "/private/var/run/");
+ message = "`services.github-runners.${name}`: `workDir` being inside /run is not supported";
+ }
])
);
@@ -44,14 +52,22 @@ in
text = mkBefore (''
echo >&2 "setting up GitHub Runner '${cfg.name}'..."
- ${pkgs.coreutils}/bin/mkdir -p -m 0750 ${escapeShellArg (mkStateDir cfg)}
- ${pkgs.coreutils}/bin/chown ${user}:${group} ${escapeShellArg (mkStateDir cfg)}
+ (
+ umask -S u=rwx,g=rx,o= > /dev/null
+
+ ${getExe' pkgs.coreutils "mkdir"} -p ${escapeShellArg (mkStateDir cfg)}
+ ${getExe' pkgs.coreutils "chown"} ${user}:${group} ${escapeShellArg (mkStateDir cfg)}
+
+ ${getExe' pkgs.coreutils "mkdir"} -p ${escapeShellArg (mkLogDir cfg)}
+ # launchd will fail to start the service if the outer direction doesn't have sufficient permissions
+ ${getExe' pkgs.coreutils "chmod"} o+rx ${escapeShellArg (mkLogDir { name = ""; })}
+ ${getExe' pkgs.coreutils "chown"} ${user}:${group} ${escapeShellArg (mkLogDir cfg)}
- ${pkgs.coreutils}/bin/mkdir -p -m 0750 ${escapeShellArg (mkLogDir cfg)}
- ${pkgs.coreutils}/bin/chown ${user}:${group} ${escapeShellArg (mkLogDir cfg)}
- '' + optionalString (cfg.workDir == null) ''
- ${pkgs.coreutils}/bin/mkdir -p -m 0750 ${escapeShellArg (mkWorkDir cfg)}
- ${pkgs.coreutils}/bin/chown ${user}:${group} ${escapeShellArg (mkWorkDir cfg)}
+ ${optionalString (cfg.workDir == null) ''
+ ${getExe' pkgs.coreutils "mkdir"} -p ${escapeShellArg (mkWorkDir cfg)}
+ ${getExe' pkgs.coreutils "chown"} ${user}:${group} ${escapeShellArg (mkWorkDir cfg)}
+ ''}
+ )
'');
};
}));
@@ -84,9 +100,13 @@ in
script =
let
+ # https://github.com/NixOS/nixpkgs/pull/333744 introduced an inconsistency with different
+ # versions of nixpkgs. Use the old version of escapeShellArg to make sure that labels
+ # are always escaped to avoid https://www.shellcheck.net/wiki/SC2054
+ escapeShellArgAlways = string: "'${replaceStrings ["'"] ["'\\''"] (toString string)}'";
configure = pkgs.writeShellApplication {
name = "configure-github-runner-${name}";
- text = ''
+ text = /*bash*/''
export RUNNER_ROOT
args=(
@@ -94,7 +114,7 @@ in
--disableupdate
--work ${escapeShellArg workDir}
--url ${escapeShellArg cfg.url}
- --labels ${escapeShellArg (concatStringsSep "," cfg.extraLabels)}
+ --labels ${escapeShellArgAlways (concatStringsSep "," cfg.extraLabels)}
${optionalString (cfg.name != null ) "--name ${escapeShellArg cfg.name}"}
${optionalString cfg.replace "--replace"}
${optionalString (cfg.runnerGroup != null) "--runnergroup ${escapeShellArg cfg.runnerGroup}"}
@@ -109,7 +129,7 @@ in
else
args+=(--token "$token")
fi
- ${package}/bin/config.sh "''${args[@]}"
+ ${getExe' package "config.sh"} "''${args[@]}"
'';
};
in
@@ -117,12 +137,12 @@ in
echo "Configuring GitHub Actions Runner"
# Always clean the working directory
- ${pkgs.findutils}/bin/find ${escapeShellArg workDir} -mindepth 1 -delete
+ ${getExe pkgs.findutils} ${escapeShellArg workDir} -mindepth 1 -delete
# Clean the $RUNNER_ROOT if we are in ephemeral mode
if ${boolToString cfg.ephemeral}; then
echo "Cleaning $RUNNER_ROOT"
- ${pkgs.findutils}/bin/find "$RUNNER_ROOT" -mindepth 1 -delete
+ ${getExe pkgs.findutils} "$RUNNER_ROOT" -mindepth 1 -delete
fi
# If the `.runner` file does not exist, we assume the runner is not configured
@@ -131,7 +151,7 @@ in
fi
# Start the service
- ${package}/bin/Runner.Listener run --startuptype service
+ ${getExe' package "Runner.Listener"} run --startuptype service
'';
serviceConfig = mkMerge [