-
-
Notifications
You must be signed in to change notification settings - Fork 494
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Loading status checks…
github-runners: init module
Adds a new module which allows to configure multiple GitHub self-hosted runners on Darwin. The module is heavily inspired by the nixpkgs NixOS module. Its implementation differs in some ways: - There's currently no way to configure the user/group which runs the runner. All configured runners share the same user and group. - No automatic cleanup. - No advanced sandboxing apart from user/group isolation
- Loading branch information
Showing
6 changed files
with
322 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
{ config, lib, pkgs, ... }: | ||
let | ||
mkSvcName = name: "github-runner-${name}"; | ||
mkRootDir = name: "${config.users.users.github-runner.home}/.github-runner/${name}"; | ||
mkWorkDir = name: "${mkRootDir name}/_work"; | ||
in | ||
with lib; | ||
{ | ||
launchd.daemons = flip mapAttrs' config.services.github-runners (name: cfg: | ||
nameValuePair | ||
(mkSvcName name) | ||
(mkIf cfg.enable { | ||
environment = { | ||
RUNNER_ROOT = mkRootDir name; | ||
} // cfg.extraEnvironment; | ||
|
||
# Minimal package set for `actions/checkout` | ||
path = (with pkgs; [ | ||
bash | ||
coreutils | ||
git | ||
gnutar | ||
gzip | ||
]) ++ [ | ||
config.nix.package | ||
] ++ cfg.extraPackages; | ||
|
||
script = '' | ||
echo "Configuring GitHub Actions Runner" | ||
mkdir -p ${escapeShellArg (mkRootDir name)} | ||
cd ${escapeShellArg (mkRootDir name)} | ||
args=( | ||
--unattended | ||
--disableupdate | ||
--work ${escapeShellArg (mkWorkDir name)} | ||
--url ${escapeShellArg cfg.url} | ||
--labels ${escapeShellArg (concatStringsSep "," cfg.extraLabels)} | ||
--name ${escapeShellArg cfg.name} | ||
${optionalString cfg.replace "--replace"} | ||
${optionalString (cfg.runnerGroup != null) "--runnergroup ${escapeShellArg cfg.runnerGroup}"} | ||
${optionalString cfg.ephemeral "--ephemeral"} | ||
) | ||
# If the token file contains a PAT (i.e., it starts with "ghp_" or "github_pat_"), we have to use the --pat option, | ||
# if it is not a PAT, we assume it contains a registration token and use the --token option | ||
token=$(<"${cfg.tokenFile}") | ||
if [[ "$token" =~ ^ghp_* ]] || [[ "$token" =~ ^github_pat_* ]]; then | ||
args+=(--pat "$token") | ||
else | ||
args+=(--token "$token") | ||
fi | ||
${cfg.package}/bin/config.sh "''${args[@]}" | ||
# Start the service | ||
${cfg.package}/bin/Runner.Listener run --startuptype service | ||
''; | ||
|
||
serviceConfig = mkMerge [ | ||
{ | ||
KeepAlive = { | ||
Crashed = false; | ||
} // mkIf cfg.ephemeral { | ||
SuccessfulExit = true; | ||
}; | ||
GroupName = "github-runner"; | ||
ProcessType = "Interactive"; | ||
RunAtLoad = true; | ||
ThrottleInterval = 30; | ||
UserName = "github-runner"; | ||
WatchPaths = [ | ||
"/etc/resolv.conf" | ||
"/Library/Preferences/SystemConfiguration/NetworkInterfaces.plist" | ||
]; | ||
WorkingDirectory = config.users.users.github-runner.home; | ||
} | ||
cfg.serviceOverrides | ||
]; | ||
})); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
{ config, lib, ... }: | ||
let | ||
anyEnabled = lib.any (cfg: cfg.enable) (lib.attrValues config.services.github-runners); | ||
in | ||
{ | ||
imports = [ | ||
./options.nix | ||
./config.nix | ||
]; | ||
|
||
config.assertions = lib.mkIf anyEnabled [ | ||
{ | ||
assertion = lib.elem "github-runner" config.users.knownGroups; | ||
message = "set `users.knownGroups` to enable `github-runner` group"; | ||
} | ||
{ | ||
assertion = lib.elem "github-runner" config.users.knownUsers; | ||
message = "set `users.knownUsers` to enable `github-runner` user"; | ||
} | ||
]; | ||
|
||
config.users = lib.mkIf anyEnabled { | ||
users."github-runner" = { | ||
createHome = true; | ||
uid = lib.mkDefault 533; | ||
gid = lib.mkDefault config.users.groups.github-runner.gid; | ||
home = lib.mkDefault "/var/lib/github-runners"; | ||
shell = "/bin/bash"; | ||
description = "GitHub Runner service user"; | ||
}; | ||
|
||
groups."github-runner" = { | ||
gid = lib.mkDefault 533; | ||
description = "GitHub Runner service user group"; | ||
}; | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,181 @@ | ||
{ lib | ||
, pkgs | ||
, ... | ||
}: | ||
|
||
with lib; | ||
{ | ||
options.services.github-runners = mkOption { | ||
default = { }; | ||
description = mdDoc '' | ||
Configure multiple GitHub Runners. | ||
''; | ||
example = literalExpression '' | ||
{ | ||
m1-runner = { | ||
enable = true; | ||
ephemeral = true; | ||
replace = true; | ||
tokenFile = "/secrets/github-org-pat.token"; | ||
url = "https://github.com/nixos"; | ||
}; | ||
m2-runner = { | ||
enable = true; | ||
extraLabels = [ "nixpkgs" ]; | ||
replace = true; | ||
tokenFile = "/secrets/github-repo-pat.token"; | ||
url = "https://github.com/nixos/nixpkgs"; | ||
}; | ||
} | ||
''; | ||
type = with types; attrsOf (submodule ({ name, ... }: { | ||
options = { | ||
enable = mkOption { | ||
default = false; | ||
example = true; | ||
description = mdDoc '' | ||
Whether to enable GitHub Actions runner. | ||
Note: GitHub recommends using self-hosted runners with private repositories only. Learn more here: | ||
[About self-hosted runners](https://docs.github.com/en/actions/hosting-your-own-runners/about-self-hosted-runners). | ||
''; | ||
type = lib.types.bool; | ||
}; | ||
|
||
url = mkOption { | ||
type = types.str; | ||
description = mdDoc '' | ||
Repository to add the runner to. | ||
Changing this option triggers a new runner registration. | ||
IMPORTANT: If your token is org-wide (not per repository), you need to | ||
provide a github org link, not a single repository, so do it like this | ||
`https://github.com/nixos`, not like this | ||
`https://github.com/nixos/nixpkgs`. | ||
Otherwise, you are going to get a `404 NotFound` | ||
from `POST https://api.github.com/actions/runner-registration` | ||
in the configure script. | ||
''; | ||
example = "https://github.com/nixos/nixpkgs"; | ||
}; | ||
|
||
tokenFile = mkOption { | ||
type = types.path; | ||
description = mdDoc '' | ||
The full path to a file which contains either a runner registration token or a | ||
(fine-grained) personal access token (PAT). | ||
The file should contain exactly one line with the token without any newline. | ||
If a registration token is given, it can be used to re-register a runner of the same | ||
name but is time-limited. If the file contains a PAT, the service creates a new | ||
registration token on startup as needed. Make sure the PAT has a scope of | ||
`admin:org` for organization-wide registrations or a scope of | ||
`repo` for a single repository. Fine-grained PATs need read and write permission | ||
to the "Adminstration" resources. | ||
Changing this option or the file's content triggers a new runner registration. | ||
''; | ||
example = "/run/secrets/github-runner/nixos.token"; | ||
}; | ||
|
||
name = mkOption { | ||
type = types.str; | ||
description = mdDoc '' | ||
Name of the runner to configure. Defaults to the attribute name. | ||
Changing this option triggers a new runner registration. | ||
''; | ||
example = "nixos"; | ||
default = name; | ||
}; | ||
|
||
runnerGroup = mkOption { | ||
type = types.nullOr types.str; | ||
description = mdDoc '' | ||
Name of the runner group to add this runner to (defaults to the default runner group). | ||
Changing this option triggers a new runner registration. | ||
''; | ||
default = null; | ||
}; | ||
|
||
extraLabels = mkOption { | ||
type = types.listOf types.str; | ||
description = mdDoc '' | ||
Extra labels in addition to the default (`["self-hosted", "Linux", "X64"]`). | ||
Changing this option triggers a new runner registration. | ||
''; | ||
example = literalExpression ''[ "nixos" ]''; | ||
default = [ ]; | ||
}; | ||
|
||
replace = mkOption { | ||
type = types.bool; | ||
description = mdDoc '' | ||
Replace any existing runner with the same name. | ||
Without this flag, registering a new runner with the same name fails. | ||
''; | ||
default = false; | ||
}; | ||
|
||
extraPackages = mkOption { | ||
type = types.listOf types.package; | ||
description = mdDoc '' | ||
Extra packages to add to `PATH` of the service to make them available to workflows. | ||
''; | ||
default = [ ]; | ||
}; | ||
|
||
extraEnvironment = mkOption { | ||
type = types.attrs; | ||
description = mdDoc '' | ||
Extra environment variables to set for the runner, as an attrset. | ||
''; | ||
example = { | ||
GIT_CONFIG = "/path/to/git/config"; | ||
}; | ||
default = { }; | ||
}; | ||
|
||
serviceOverrides = mkOption { | ||
type = types.attrs; | ||
description = mdDoc '' | ||
Overrides for the systemd service. Can be used to adjust the sandboxing options. | ||
''; | ||
example = { | ||
ProtectHome = false; | ||
}; | ||
default = { }; | ||
}; | ||
|
||
package = mkOption { | ||
type = types.package; | ||
description = mdDoc '' | ||
Which github-runner derivation to use. | ||
''; | ||
default = pkgs.github-runner; | ||
defaultText = literalExpression "pkgs.github-runner"; | ||
}; | ||
|
||
ephemeral = mkOption { | ||
type = types.bool; | ||
description = mdDoc '' | ||
If enabled, causes the following behavior: | ||
- Passes the `--ephemeral` flag to the runner configuration script | ||
- De-registers and stops the runner with GitHub after it has processed one job | ||
- The runner wipes some state before it exists | ||
You should only enable this option if `tokenFile` points to a file which contains a | ||
personal access token (PAT). If you're using the option with a registration token, restarting the | ||
service will fail as soon as the registration token expired. | ||
''; | ||
default = false; | ||
}; | ||
}; | ||
})); | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
{ config, pkgs, ... }: | ||
{ | ||
users = { | ||
knownUsers = [ "github-runner" ]; | ||
knownGroups = [ "github-runner" ]; | ||
}; | ||
|
||
services.github-runners."a-runner" = { | ||
enable = true; | ||
url = "https://github.com/nixos/nixpkgs"; | ||
tokenFile = pkgs.writeText "fake-token" "not-a-token"; | ||
package = pkgs.runCommand "github-runner-0.0.0" { } "touch $out"; | ||
}; | ||
|
||
test = '' | ||
echo >&2 "checking github-runner service in /Library/LaunchDaemons" | ||
grep "org.nixos.github-runner-a-runner" ${config.out}/Library/LaunchDaemons/org.nixos.github-runner-a-runner.plist | ||
grep "<string>github-runner</string>" ${config.out}/Library/LaunchDaemons/org.nixos.github-runner-a-runner.plist | ||
echo >&2 "checking for user in /activate" | ||
grep "GitHub Runner service user" ${config.out}/activate | ||
''; | ||
} |