github-runner: org-friendly now. can have multiple runners per repo even.

This commit is contained in:
Sridhar Ratnakumar 2024-02-14 05:41:56 -05:00
parent 8d10865115
commit 18902feee0

View file

@ -2,17 +2,15 @@
Limitations
- A runner can run only one job at a time: https://github.com/orgs/community/discussions/26769
- This makes sharing an org-wide runner less useful.
- This makes sharing an org-wide runner less useful, unless we create multiple runners.
TODOs
- [x] Run runners in containers
- [ ] macOS runners: https://github.com/LnL7/nix-darwin/issues/582
- [ ] Support github orgs
- [x] Support github orgs
- [ ] Unbreak cachix? https://github.com/cachix/cachix-action/issues/169
- [x] Or switch to nix-serve or attic
- [ ] Document PAC token
- For user accounts, create a legacy PAC token with 'repo' scope. New-style could also work.
*/
top@{ pkgs, lib, config, ... }:
@ -23,35 +21,47 @@ in
options = {
# TODO: Make this general enough to support organizations and other users.
services.personal-github-runners = lib.mkOption {
default = { };
type = types.submodule {
description = ''
Attrset of runners.
The key is either org name or the repo path.
'';
default = {
"srid/emanote" = { };
"srid/haskell-flake" = { };
"srid/nixos-config" = { };
"srid/ema" = { };
};
type = types.lazyAttrsOf (types.submodule ({ config, name, ... }: {
options = {
owner = lib.mkOption {
type = types.str;
default = "srid";
default = lib.head (lib.splitString "/" config.githubPath);
};
repositories = lib.mkOption {
type = types.listOf types.str;
description = ''
My repositories configured to use self-hosted runners
*Before* adding an entry, make sure the token exists in
secrets.json (use the `gh` command above to create this token
from CLI)
'';
default = [
"emanote"
"haskell-flake"
"nixos-config"
"ema"
];
};
sopsPrefix = lib.mkOption {
url = lib.mkOption {
type = types.str;
default = "gh-selfhosted-tokens";
description = ''Github URL for this runner'';
default = "https://github.com/${config.githubPath}";
};
githubPath = lib.mkOption {
type = types.str;
default = name;
description = ''
The path after https://github.com in the URL for this runner
By default, it uses the attr key. If you are running multiple
runners per org or per repo, you may want to explicitly specify
the githubPath to disambiguate.
'';
};
tokenSecretPath = lib.mkOption {
type = types.str;
# By default, we expect personal access token (not runner registeration token)
# Thus, it is bucket by the owner.
default = "gh-selfhosted-tokens/${config.owner}";
readOnly = true;
description = ''
sops-nix parent key path containing the tokens
sops-nix key path containing the token for this runner.
'';
};
nixosConfig = lib.mkOption {
@ -81,7 +91,7 @@ in
};
};
};
};
}));
};
};
config =
@ -98,7 +108,11 @@ in
};
in
userModule // {
sops.secrets."${cfg.sopsPrefix}/${cfg.owner}".mode = "0440";
sops.secrets =
lib.flip lib.mapAttrs' cfg (name: cfg:
lib.nameValuePair cfg.tokenSecretPath {
mode = "0440";
});
nix.settings = {
trusted-users = [ user ];
@ -106,15 +120,13 @@ in
};
containers =
lib.listToAttrs (builtins.map
(name:
lib.flip lib.mapAttrs' cfg
(name: cfg:
let
tokenFile = top.config.sops.secrets."${cfg.sopsPrefix}/${cfg.owner}".path;
githubPath = "${cfg.owner}/${name}";
url = "https://github.com/${githubPath}";
githubPathLegal = lib.replaceStrings [ "/" ] [ "-" ] githubPath;
tokenFile = top.config.sops.secrets."${cfg.tokenSecretPath}".path;
nameLegal = lib.replaceStrings [ "/" ] [ "-" ] name;
in
lib.nameValuePair ''github-runner-${githubPathLegal}'' {
lib.nameValuePair ''github-runner-${nameLegal}'' {
autoStart = true;
bindMounts."${tokenFile}" = {
hostPath = tokenFile;
@ -127,13 +139,12 @@ in
cfg.nixosConfig
];
nix.settings.trusted-users = [ user ]; # for cachix
services.github-runners."${githubPathLegal}" = cfg.runnerConfig // {
services.github-runners."${nameLegal}" = cfg.runnerConfig // {
enable = true;
inherit user url tokenFile;
inherit user tokenFile;
inherit (cfg) url;
};
};
})
cfg.repositories);
});
};
}