nixos/gitea-actions-runner: init
This commit is contained in:
parent
8dd0f0a459
commit
1c963cea48
|
@ -49,6 +49,8 @@ In addition to numerous new and upgraded packages, this release has the followin
|
||||||
|
|
||||||
- [gemstash](https://github.com/rubygems/gemstash), a RubyGems.org cache and private gem server. Available as [services.gemstash](#opt-services.gemstash.enable).
|
- [gemstash](https://github.com/rubygems/gemstash), a RubyGems.org cache and private gem server. Available as [services.gemstash](#opt-services.gemstash.enable).
|
||||||
|
|
||||||
|
- [gitea-actions-runner](https://gitea.com/gitea/act_runner), a CI runner for Gitea/Forgejo Actions. Available as [services.gitea-actions-runner](#opt-services.gitea-actions-runner.instances).
|
||||||
|
|
||||||
- [gmediarender](https://github.com/hzeller/gmrender-resurrect), a simple, headless UPnP/DLNA renderer. Available as [services.gmediarender](options.html#opt-services.gmediarender.enable).
|
- [gmediarender](https://github.com/hzeller/gmrender-resurrect), a simple, headless UPnP/DLNA renderer. Available as [services.gmediarender](options.html#opt-services.gmediarender.enable).
|
||||||
|
|
||||||
- [hyprland](https://github.com/hyprwm/hyprland), a dynamic tiling Wayland compositor that doesn't sacrifice on its looks. Available as [programs.hyprland](#opt-programs.hyprland.enable).
|
- [hyprland](https://github.com/hyprwm/hyprland), a dynamic tiling Wayland compositor that doesn't sacrifice on its looks. Available as [programs.hyprland](#opt-programs.hyprland.enable).
|
||||||
|
|
|
@ -370,6 +370,7 @@
|
||||||
./services/continuous-integration/buildbot/master.nix
|
./services/continuous-integration/buildbot/master.nix
|
||||||
./services/continuous-integration/buildbot/worker.nix
|
./services/continuous-integration/buildbot/worker.nix
|
||||||
./services/continuous-integration/buildkite-agents.nix
|
./services/continuous-integration/buildkite-agents.nix
|
||||||
|
./services/continuous-integration/gitea-actions-runner.nix
|
||||||
./services/continuous-integration/github-runner.nix
|
./services/continuous-integration/github-runner.nix
|
||||||
./services/continuous-integration/github-runners.nix
|
./services/continuous-integration/github-runners.nix
|
||||||
./services/continuous-integration/gitlab-runner.nix
|
./services/continuous-integration/gitlab-runner.nix
|
||||||
|
|
|
@ -0,0 +1,237 @@
|
||||||
|
{ config
|
||||||
|
, lib
|
||||||
|
, pkgs
|
||||||
|
, utils
|
||||||
|
, ...
|
||||||
|
}:
|
||||||
|
|
||||||
|
let
|
||||||
|
inherit (lib)
|
||||||
|
any
|
||||||
|
attrValues
|
||||||
|
concatStringsSep
|
||||||
|
escapeShellArg
|
||||||
|
hasInfix
|
||||||
|
hasSuffix
|
||||||
|
optionalAttrs
|
||||||
|
optionals
|
||||||
|
literalExpression
|
||||||
|
mapAttrs'
|
||||||
|
mkEnableOption
|
||||||
|
mkOption
|
||||||
|
mkPackageOptionMD
|
||||||
|
mkIf
|
||||||
|
nameValuePair
|
||||||
|
types
|
||||||
|
;
|
||||||
|
|
||||||
|
inherit (utils)
|
||||||
|
escapeSystemdPath
|
||||||
|
;
|
||||||
|
|
||||||
|
cfg = config.services.gitea-actions-runner;
|
||||||
|
|
||||||
|
# Check whether any runner instance label requires a container runtime
|
||||||
|
# Empty label strings result in the upstream defined defaultLabels, which require docker
|
||||||
|
# https://gitea.com/gitea/act_runner/src/tag/v0.1.5/internal/app/cmd/register.go#L93-L98
|
||||||
|
hasDockerScheme = instance:
|
||||||
|
instance.labels == [] || any (label: hasInfix ":docker:" label) instance.labels;
|
||||||
|
wantsContainerRuntime = any hasDockerScheme (attrValues cfg.instances);
|
||||||
|
|
||||||
|
hasHostScheme = instance: any (label: hasSuffix ":host" label) instance.labels;
|
||||||
|
|
||||||
|
# provide shorthands for whether container runtimes are enabled
|
||||||
|
hasDocker = config.virtualisation.docker.enable;
|
||||||
|
hasPodman = config.virtualisation.podman.enable;
|
||||||
|
|
||||||
|
tokenXorTokenFile = instance:
|
||||||
|
(instance.token == null && instance.tokenFile != null) ||
|
||||||
|
(instance.token != null && instance.tokenFile == null);
|
||||||
|
in
|
||||||
|
{
|
||||||
|
meta.maintainers = with lib.maintainers; [
|
||||||
|
hexa
|
||||||
|
];
|
||||||
|
|
||||||
|
options.services.gitea-actions-runner = with types; {
|
||||||
|
package = mkPackageOptionMD pkgs "gitea-actions-runner" { };
|
||||||
|
|
||||||
|
instances = mkOption {
|
||||||
|
default = {};
|
||||||
|
description = lib.mdDoc ''
|
||||||
|
Gitea Actions Runner instances.
|
||||||
|
'';
|
||||||
|
type = attrsOf (submodule {
|
||||||
|
options = {
|
||||||
|
enable = mkEnableOption (lib.mdDoc "Gitea Actions Runner instance");
|
||||||
|
|
||||||
|
name = mkOption {
|
||||||
|
type = str;
|
||||||
|
example = literalExpression "config.networking.hostName";
|
||||||
|
description = lib.mdDoc ''
|
||||||
|
The name identifying the runner instance towards the Gitea/Forgejo instance.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
url = mkOption {
|
||||||
|
type = str;
|
||||||
|
example = "https://forge.example.com";
|
||||||
|
description = lib.mdDoc ''
|
||||||
|
Base URL of your Gitea/Forgejo instance.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
token = mkOption {
|
||||||
|
type = nullOr str;
|
||||||
|
default = null;
|
||||||
|
description = lib.mdDoc ''
|
||||||
|
Plain token to register at the configured Gitea/Forgejo instance.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
tokenFile = mkOption {
|
||||||
|
type = nullOr (either str path);
|
||||||
|
default = null;
|
||||||
|
description = lib.mdDoc ''
|
||||||
|
Path to an environment file, containing the `TOKEN` environment
|
||||||
|
variable, that holds a token to register at the configured
|
||||||
|
Gitea/Forgejo instance.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
labels = mkOption {
|
||||||
|
type = listOf str;
|
||||||
|
example = literalExpression ''
|
||||||
|
[
|
||||||
|
# provide a debian base with nodejs for actions
|
||||||
|
"debian-latest:docker://node:18-bullseye"
|
||||||
|
# fake the ubuntu name, because node provides no ubuntu builds
|
||||||
|
"ubuntu-latest:docker://node:18-bullseye"
|
||||||
|
# provide native execution on the host
|
||||||
|
#"native:host"
|
||||||
|
]
|
||||||
|
'';
|
||||||
|
description = lib.mdDoc ''
|
||||||
|
Labels used to map jobs to their runtime environment. Changing these
|
||||||
|
labels currently requires a new registration token.
|
||||||
|
|
||||||
|
Many common actions require bash, git and nodejs, as well as a filesystem
|
||||||
|
that follows the filesystem hierarchy standard.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
hostPackages = mkOption {
|
||||||
|
type = listOf package;
|
||||||
|
default = with pkgs; [
|
||||||
|
bash
|
||||||
|
coreutils
|
||||||
|
curl
|
||||||
|
gawk
|
||||||
|
gitMinimal
|
||||||
|
gnused
|
||||||
|
nodejs
|
||||||
|
wget
|
||||||
|
];
|
||||||
|
defaultText = literalExpression ''
|
||||||
|
with pkgs; [
|
||||||
|
bash
|
||||||
|
coreutils
|
||||||
|
curl
|
||||||
|
gawk
|
||||||
|
gitMinimal
|
||||||
|
gnused
|
||||||
|
nodejs
|
||||||
|
wget
|
||||||
|
]
|
||||||
|
'';
|
||||||
|
description = lib.mdDoc ''
|
||||||
|
List of packages, that are available to actions, when the runner is configured
|
||||||
|
with a host execution label.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
});
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = mkIf (cfg.instances != {}) {
|
||||||
|
assertions = [ {
|
||||||
|
assertion = any tokenXorTokenFile (attrValues cfg.instances);
|
||||||
|
message = "Instances of gitea-actions-runner can have `token` or `tokenFile`, not both.";
|
||||||
|
} {
|
||||||
|
assertion = wantsContainerRuntime -> hasDocker || hasPodman;
|
||||||
|
message = "Label configuration on gitea-actions-runner instance requires either docker or podman.";
|
||||||
|
} ];
|
||||||
|
|
||||||
|
systemd.services = let
|
||||||
|
mkRunnerService = name: instance: let
|
||||||
|
wantsContainerRuntime = hasDockerScheme instance;
|
||||||
|
wantsHost = hasHostScheme instance;
|
||||||
|
wantsDocker = wantsContainerRuntime && config.virtualisation.docker.enable;
|
||||||
|
wantsPodman = wantsContainerRuntime && config.virtualisation.podman.enable;
|
||||||
|
in
|
||||||
|
nameValuePair "gitea-runner-${escapeSystemdPath name}" {
|
||||||
|
inherit (instance) enable;
|
||||||
|
description = "Gitea Actions Runner";
|
||||||
|
after = [
|
||||||
|
"network-online.target"
|
||||||
|
] ++ optionals (wantsDocker) [
|
||||||
|
"docker.service"
|
||||||
|
] ++ optionals (wantsPodman) [
|
||||||
|
"podman.service"
|
||||||
|
];
|
||||||
|
wantedBy = [
|
||||||
|
"multi-user.target"
|
||||||
|
];
|
||||||
|
environment = optionalAttrs (instance.token != null) {
|
||||||
|
TOKEN = "${instance.token}";
|
||||||
|
} // optionalAttrs (wantsPodman) {
|
||||||
|
DOCKER_HOST = "unix:///run/podman/podman.sock";
|
||||||
|
};
|
||||||
|
path = with pkgs; [
|
||||||
|
coreutils
|
||||||
|
] ++ lib.optionals wantsHost instance.hostPackages;
|
||||||
|
serviceConfig = {
|
||||||
|
DynamicUser = true;
|
||||||
|
User = "gitea-runner";
|
||||||
|
StateDirectory = "gitea-runner";
|
||||||
|
WorkingDirectory = "-/var/lib/gitea-runner/${name}";
|
||||||
|
ExecStartPre = pkgs.writeShellScript "gitea-register-runner-${name}" ''
|
||||||
|
export INSTANCE_DIR="$STATE_DIRECTORY/${name}"
|
||||||
|
mkdir -vp "$INSTANCE_DIR"
|
||||||
|
cd "$INSTANCE_DIR"
|
||||||
|
|
||||||
|
# force reregistration on changed labels
|
||||||
|
export LABELS_FILE="$INSTANCE_DIR/.labels"
|
||||||
|
export LABELS_WANTED="$(echo ${escapeShellArg (concatStringsSep "\n" instance.labels)} | sort)"
|
||||||
|
export LABELS_CURRENT="$(cat $LABELS_FILE 2>/dev/null || echo 0)"
|
||||||
|
|
||||||
|
if [ ! -e "$INSTANCE_DIR/.runner" ] || [ "$LABELS_WANTED" != "$LABELS_CURRENT" ]; then
|
||||||
|
# remove existing registration file, so that changing the labels forces a re-registation
|
||||||
|
rm -v "$INSTANCE_DIR/.runner" || true
|
||||||
|
|
||||||
|
# perform the registration
|
||||||
|
${cfg.package}/bin/act_runner register --no-interactive \
|
||||||
|
--instance ${escapeShellArg instance.url} \
|
||||||
|
--token "$TOKEN" \
|
||||||
|
--name ${escapeShellArg instance.name} \
|
||||||
|
--labels ${escapeShellArg (concatStringsSep "," instance.labels)}
|
||||||
|
|
||||||
|
# and write back the configured labels
|
||||||
|
echo "$LABELS_WANTED" > "$LABELS_FILE"
|
||||||
|
fi
|
||||||
|
|
||||||
|
'';
|
||||||
|
ExecStart = "${cfg.package}/bin/act_runner daemon";
|
||||||
|
SupplementaryGroups = optionals (wantsDocker) [
|
||||||
|
"docker"
|
||||||
|
] ++ optionals (wantsPodman) [
|
||||||
|
"podman"
|
||||||
|
];
|
||||||
|
} // optionalAttrs (instance.tokenFile != null) {
|
||||||
|
EnvironmentFile = instance.tokenFile;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
in mapAttrs' mkRunnerService cfg.instances;
|
||||||
|
};
|
||||||
|
}
|
Loading…
Reference in a new issue