···371371 </listitem>
372372 <listitem>
373373 <para>
374374+ <literal>github-runner</literal> gained support for ephemeral
375375+ runners and registrations using a personal access token (PAT)
376376+ instead of a registration token. See
377377+ <literal>services.github-runner.ephemeral</literal> and
378378+ <literal>services.github-runner.tokenFile</literal> for
379379+ details.
380380+ </para>
381381+ </listitem>
382382+ <listitem>
383383+ <para>
374384 A new module was added for the Saleae Logic device family,
375385 providing the options
376386 <literal>hardware.saleae-logic.enable</literal> and
+2
nixos/doc/manual/release-notes/rl-2211.section.md
···137137138138- The `xplr` package has been updated from 0.18.0 to 0.19.0, which brings some breaking changes. See the [upstream release notes](https://github.com/sayanarijit/xplr/releases/tag/v0.19.0) for more details.
139139140140+- `github-runner` gained support for ephemeral runners and registrations using a personal access token (PAT) instead of a registration token. See `services.github-runner.ephemeral` and `services.github-runner.tokenFile` for details.
141141+140142- A new module was added for the Saleae Logic device family, providing the options `hardware.saleae-logic.enable` and `hardware.saleae-logic.package`.
141143142144- The Redis module now disables RDB persistence when `services.redis.servers.<name>.save = []` instead of using the Redis default.
···4848 tokenFile = mkOption {
4949 type = types.path;
5050 description = lib.mdDoc ''
5151- The full path to a file which contains the runner registration token.
5151+ The full path to a file which contains either a runner registration token or a
5252+ personal access token (PAT).
5253 The file should contain exactly one line with the token without any newline.
5353- The token can be used to re-register a runner of the same name but is time-limited.
5454+ If a registration token is given, it can be used to re-register a runner of the same
5555+ name but is time-limited. If the file contains a PAT, the service creates a new
5656+ registration token on startup as needed. Make sure the PAT has a scope of
5757+ `admin:org` for organization-wide registrations or a scope of
5858+ `repo` for a single repository.
54595560 Changing this option or the file's content triggers a new runner registration.
5661 '';
···117122 default = pkgs.github-runner;
118123 defaultText = literalExpression "pkgs.github-runner";
119124 };
125125+126126+ ephemeral = mkOption {
127127+ type = types.bool;
128128+ description = lib.mdDoc ''
129129+ If enabled, causes the following behavior:
130130+131131+ - Passes the `--ephemeral` flag to the runner configuration script
132132+ - De-registers and stops the runner with GitHub after it has processed one job
133133+ - On stop, systemd wipes the runtime directory (this always happens, even without using the ephemeral option)
134134+ - Restarts the service after its successful exit
135135+ - On start, wipes the state directory and configures a new runner
136136+137137+ You should only enable this option if `tokenFile` points to a file which contains a
138138+ personal access token (PAT). If you're using the option with a registration token, restarting the
139139+ service will fail as soon as the registration token expired.
140140+ '';
141141+ default = false;
142142+ };
120143 };
121144122145 config = mkIf cfg.enable {
···136159137160 environment = {
138161 HOME = runtimeDir;
139139- RUNNER_ROOT = runtimeDir;
162162+ RUNNER_ROOT = stateDir;
140163 };
141164142165 path = (with pkgs; [
···150173 ] ++ cfg.extraPackages;
151174152175 serviceConfig = rec {
153153- ExecStart = "${cfg.package}/bin/runsvc.sh";
176176+ ExecStart = "${cfg.package}/bin/Runner.Listener run --startuptype service";
154177155178 # Does the following, sequentially:
156179 # - If the module configuration or the token has changed, purge the state directory,
···178201 ${lines}
179202 '';
180203 currentConfigPath = "$STATE_DIRECTORY/.nixos-current-config.json";
181181- runnerRegistrationConfig = getAttrs [ "name" "tokenFile" "url" "runnerGroup" "extraLabels" ] cfg;
204204+ runnerRegistrationConfig = getAttrs [ "name" "tokenFile" "url" "runnerGroup" "extraLabels" "ephemeral" ] cfg;
182205 newConfigPath = builtins.toFile "${svcName}-config.json" (builtins.toJSON runnerRegistrationConfig);
183206 newConfigTokenFilename = ".new-token";
184207 runnerCredFiles = [
···188211 ];
189212 unconfigureRunner = writeScript "unconfigure" ''
190213 differs=
191191- # Set `differs = 1` if current and new runner config differ or if `currentConfigPath` does not exist
192192- ${pkgs.diffutils}/bin/diff -q '${newConfigPath}' "${currentConfigPath}" >/dev/null 2>&1 || differs=1
193193- # Also trigger a registration if the token content changed
194194- ${pkgs.diffutils}/bin/diff -q \
195195- "$STATE_DIRECTORY"/${currentConfigTokenFilename} \
196196- ${escapeShellArg cfg.tokenFile} \
197197- >/dev/null 2>&1 || differs=1
214214+215215+ if [[ "$(ls -A "$STATE_DIRECTORY")" ]]; then
216216+ # State directory is not empty
217217+ # Set `differs = 1` if current and new runner config differ or if `currentConfigPath` does not exist
218218+ ${pkgs.diffutils}/bin/diff -q '${newConfigPath}' "${currentConfigPath}" >/dev/null 2>&1 || differs=1
219219+ # Also trigger a registration if the token content changed
220220+ ${pkgs.diffutils}/bin/diff -q \
221221+ "$STATE_DIRECTORY"/${currentConfigTokenFilename} \
222222+ ${escapeShellArg cfg.tokenFile} \
223223+ >/dev/null 2>&1 || differs=1
224224+ # If .credentials does not exist, assume a previous run de-registered the runner on stop (ephemeral mode)
225225+ [[ ! -f "$STATE_DIRECTORY/.credentials" ]] && differs=1
226226+ fi
198227199228 if [[ -n "$differs" ]]; then
200229 echo "Config has changed, removing old runner state."
201201- echo "The old runner will still appear in the GitHub Actions UI." \
230230+ # In ephemeral mode, the runner deletes the `.credentials` file after de-registering it with GitHub
231231+ [[ -f "$STATE_DIRECTORY/.credentials" ]] && echo "The old runner will still appear in the GitHub Actions UI." \
202232 "You have to remove it manually."
203233 find "$STATE_DIRECTORY/" -mindepth 1 -delete
204234···212242 if [[ -e "$STATE_DIRECTORY/${newConfigTokenFilename}" ]]; then
213243 echo "Configuring GitHub Actions Runner"
214244215215- token=$(< "$STATE_DIRECTORY"/${newConfigTokenFilename})
216216- RUNNER_ROOT="$STATE_DIRECTORY" ${cfg.package}/bin/config.sh \
217217- --unattended \
218218- --disableupdate \
219219- --work "$RUNTIME_DIRECTORY" \
220220- --url ${escapeShellArg cfg.url} \
221221- --token "$token" \
222222- --labels ${escapeShellArg (concatStringsSep "," cfg.extraLabels)} \
223223- --name ${escapeShellArg cfg.name} \
224224- ${optionalString cfg.replace "--replace"} \
245245+ args=(
246246+ --unattended
247247+ --disableupdate
248248+ --work "$RUNTIME_DIRECTORY"
249249+ --url ${escapeShellArg cfg.url}
250250+ --labels ${escapeShellArg (concatStringsSep "," cfg.extraLabels)}
251251+ --name ${escapeShellArg cfg.name}
252252+ ${optionalString cfg.replace "--replace"}
225253 ${optionalString (cfg.runnerGroup != null) "--runnergroup ${escapeShellArg cfg.runnerGroup}"}
254254+ ${optionalString cfg.ephemeral "--ephemeral"}
255255+ )
256256+257257+ # If the token file contains a PAT (i.e., it starts with "ghp_"), we have to use the --pat option,
258258+ # if it is not a PAT, we assume it contains a registration token and use the --token option
259259+ token=$(<"$STATE_DIRECTORY/${newConfigTokenFilename}")
260260+ if [[ "$token" =~ ^ghp_* ]]; then
261261+ args+=(--pat "$token")
262262+ else
263263+ args+=(--token "$token")
264264+ fi
265265+266266+ ${cfg.package}/bin/config.sh "''${args[@]}"
226267227268 # Move the automatically created _diag dir to the logs dir
228269 mkdir -p "$STATE_DIRECTORY/_diag"
···250291 setupRuntimeDir
251292 ];
252293294294+ # If running in ephemeral mode, restart the service on-exit (i.e., successful de-registration of the runner)
295295+ # to trigger a fresh registration.
296296+ Restart = if cfg.ephemeral then "on-success" else "no";
297297+253298 # Contains _diag
254299 LogsDirectory = [ systemdDir ];
255300 # Default RUNNER_ROOT which contains ephemeral Runner data
···269314 # By default, use a dynamically allocated user
270315 DynamicUser = true;
271316272272- KillMode = "process";
273273- KillSignal = "SIGTERM";
317317+ KillSignal = "SIGINT";
274318275319 # Hardening (may overlap with DynamicUser=)
276320 # The following options are only for optimizing:
···55 /* Do not use "dev" as a version. If you do, Tilt will consider itself
66 running in development environment and try to serve assets from the
77 source tree, which is not there once build completes. */
88- version = "0.30.6";
88+ version = "0.30.7";
991010 src = fetchFromGitHub {
1111 owner = "tilt-dev";
1212 repo = pname;
1313 rev = "v${version}";
1414- sha256 = "sha256-i4i406Ys3MY77t4oN+kIeWopdjtfysm4xDFkTpuo+X0=";
1414+ sha256 = "sha256-zYP9bn3wC5FJwCdDJEBunaEHoFhRKlH7Mec/Stvp76A=";
1515 };
1616 vendorSha256 = null;
1717