Merge pull request #205526 from newAM/github-runner-oom

nixos/github-runner: add workDir option

authored by

Aaron Andersen and committed by
GitHub
4769274f 3bc50ffb

+35 -14
+12
nixos/modules/services/continuous-integration/github-runner/options.nix
··· 170 default = null; 171 defaultText = literalExpression "username"; 172 }; 173 }
··· 170 default = null; 171 defaultText = literalExpression "username"; 172 }; 173 + 174 + workDir = mkOption { 175 + type = with types; nullOr str; 176 + description = lib.mdDoc '' 177 + Working directory, available as `$GITHUB_WORKSPACE` during workflow runs 178 + and used as a default for [repository checkouts](https://github.com/actions/checkout). 179 + The service cleans this directory on every service start. 180 + 181 + A value of `null` will default to the systemd `RuntimeDirectory`. 182 + ''; 183 + default = null; 184 + }; 185 }
+23 -14
nixos/modules/services/continuous-integration/github-runner/service.nix
··· 20 21 with lib; 22 23 { 24 description = "GitHub Actions runner"; 25 ··· 28 after = [ "network.target" "network-online.target" ]; 29 30 environment = { 31 - HOME = runtimeDir; 32 RUNNER_ROOT = stateDir; 33 } // cfg.extraEnvironment; 34 ··· 42 config.nix.package 43 ] ++ cfg.extraPackages; 44 45 - serviceConfig = rec { 46 ExecStart = "${cfg.package}/bin/Runner.Listener run --startuptype service"; 47 48 # Does the following, sequentially: ··· 54 # - Set up the directory structure by creating the necessary symlinks. 55 ExecStartPre = 56 let 57 - # Wrapper script which expects the full path of the state, runtime and logs 58 # directory as arguments. Overrides the respective systemd variables to provide 59 # unambiguous directory names. This becomes relevant, for example, if the 60 # caller overrides any of the StateDirectory=, RuntimeDirectory= or LogDirectory= ··· 65 set -euo pipefail 66 67 STATE_DIRECTORY="$1" 68 - RUNTIME_DIRECTORY="$2" 69 LOGS_DIRECTORY="$3" 70 71 ${lines} 72 ''; 73 - runnerRegistrationConfig = getAttrs [ "name" "tokenFile" "url" "runnerGroup" "extraLabels" "ephemeral" ] cfg; 74 newConfigPath = builtins.toFile "${svcName}-config.json" (builtins.toJSON runnerRegistrationConfig); 75 currentConfigPath = "$STATE_DIRECTORY/.nixos-current-config.json"; 76 newConfigTokenPath= "$STATE_DIRECTORY/.new-token"; ··· 119 else 120 # The state directory is entirely empty which indicates a first start 121 copy_tokens 122 - fi ''; 123 configureRunner = writeScript "configure" '' 124 if [[ -e "${newConfigTokenPath}" ]]; then 125 echo "Configuring GitHub Actions Runner" 126 args=( 127 --unattended 128 --disableupdate 129 - --work "$RUNTIME_DIRECTORY" 130 --url ${escapeShellArg cfg.url} 131 --labels ${escapeShellArg (concatStringsSep "," cfg.extraLabels)} 132 --name ${escapeShellArg cfg.name} ··· 153 ln -s '${newConfigPath}' "${currentConfigPath}" 154 fi 155 ''; 156 - setupRuntimeDir = writeScript "setup-runtime-dirs" '' 157 # Link _diag dir 158 - ln -s "$LOGS_DIRECTORY" "$RUNTIME_DIRECTORY/_diag" 159 160 - # Link the runner credentials to the runtime dir 161 - ln -s "$STATE_DIRECTORY"/{${lib.concatStringsSep "," runnerCredFiles}} "$RUNTIME_DIRECTORY/" 162 ''; 163 in 164 - map (x: "${x} ${escapeShellArgs [ stateDir runtimeDir logsDir ]}") [ 165 "+${unconfigureRunner}" # runs as root 166 configureRunner 167 - setupRuntimeDir 168 ]; 169 170 # If running in ephemeral mode, restart the service on-exit (i.e., successful de-registration of the runner) ··· 181 # Home of persistent runner data, e.g., credentials 182 StateDirectory = [ systemdDir ]; 183 StateDirectoryMode = "0700"; 184 - WorkingDirectory = runtimeDir; 185 186 InaccessiblePaths = [ 187 # Token file path given in the configuration, if visible to the service ··· 231 "~sethostname" 232 ]; 233 RestrictAddressFamilies = [ "AF_INET" "AF_INET6" "AF_UNIX" "AF_NETLINK" ]; 234 235 # Needs network access 236 PrivateNetwork = false;
··· 20 21 with lib; 22 23 + let 24 + workDir = if cfg.workDir == null then runtimeDir else cfg.workDir; 25 + in 26 { 27 description = "GitHub Actions runner"; 28 ··· 31 after = [ "network.target" "network-online.target" ]; 32 33 environment = { 34 + HOME = workDir; 35 RUNNER_ROOT = stateDir; 36 } // cfg.extraEnvironment; 37 ··· 45 config.nix.package 46 ] ++ cfg.extraPackages; 47 48 + serviceConfig = { 49 ExecStart = "${cfg.package}/bin/Runner.Listener run --startuptype service"; 50 51 # Does the following, sequentially: ··· 57 # - Set up the directory structure by creating the necessary symlinks. 58 ExecStartPre = 59 let 60 + # Wrapper script which expects the full path of the state, working and logs 61 # directory as arguments. Overrides the respective systemd variables to provide 62 # unambiguous directory names. This becomes relevant, for example, if the 63 # caller overrides any of the StateDirectory=, RuntimeDirectory= or LogDirectory= ··· 68 set -euo pipefail 69 70 STATE_DIRECTORY="$1" 71 + WORK_DIRECTORY="$2" 72 LOGS_DIRECTORY="$3" 73 74 ${lines} 75 ''; 76 + runnerRegistrationConfig = getAttrs [ "name" "tokenFile" "url" "runnerGroup" "extraLabels" "ephemeral" "workDir" ] cfg; 77 newConfigPath = builtins.toFile "${svcName}-config.json" (builtins.toJSON runnerRegistrationConfig); 78 currentConfigPath = "$STATE_DIRECTORY/.nixos-current-config.json"; 79 newConfigTokenPath= "$STATE_DIRECTORY/.new-token"; ··· 122 else 123 # The state directory is entirely empty which indicates a first start 124 copy_tokens 125 + fi 126 + ''; 127 configureRunner = writeScript "configure" '' 128 if [[ -e "${newConfigTokenPath}" ]]; then 129 echo "Configuring GitHub Actions Runner" 130 args=( 131 --unattended 132 --disableupdate 133 + --work "$WORK_DIRECTORY" 134 --url ${escapeShellArg cfg.url} 135 --labels ${escapeShellArg (concatStringsSep "," cfg.extraLabels)} 136 --name ${escapeShellArg cfg.name} ··· 157 ln -s '${newConfigPath}' "${currentConfigPath}" 158 fi 159 ''; 160 + setupWorkDir = writeScript "setup-work-dirs" '' 161 + # Cleanup previous service 162 + ${pkgs.findutils}/bin/find -H "$WORK_DIRECTORY" -mindepth 1 -delete 163 + 164 # Link _diag dir 165 + ln -s "$LOGS_DIRECTORY" "$WORK_DIRECTORY/_diag" 166 167 + # Link the runner credentials to the work dir 168 + ln -s "$STATE_DIRECTORY"/{${lib.concatStringsSep "," runnerCredFiles}} "$WORK_DIRECTORY/" 169 ''; 170 in 171 + map (x: "${x} ${escapeShellArgs [ stateDir workDir logsDir ]}") [ 172 "+${unconfigureRunner}" # runs as root 173 configureRunner 174 + setupWorkDir 175 ]; 176 177 # If running in ephemeral mode, restart the service on-exit (i.e., successful de-registration of the runner) ··· 188 # Home of persistent runner data, e.g., credentials 189 StateDirectory = [ systemdDir ]; 190 StateDirectoryMode = "0700"; 191 + WorkingDirectory = workDir; 192 193 InaccessiblePaths = [ 194 # Token file path given in the configuration, if visible to the service ··· 238 "~sethostname" 239 ]; 240 RestrictAddressFamilies = [ "AF_INET" "AF_INET6" "AF_UNIX" "AF_NETLINK" ]; 241 + 242 + BindPaths = lib.optionals (cfg.workDir != null) [ cfg.workDir ]; 243 244 # Needs network access 245 PrivateNetwork = false;