# NixOS module for Buildbot Worker. { config, lib, options, pkgs, ... }: with lib; let cfg = config.services.buildbot-worker; opt = options.services.buildbot-worker; python = cfg.package.pythonModule; tacFile = pkgs.writeText "aur-buildbot-worker.tac" '' import os from io import open from buildbot_worker.bot import Worker from twisted.application import service basedir = '${cfg.buildbotDir}' # note: this line is matched against to check that this is a worker # directory; do not edit it. application = service.Application('buildbot-worker') master_url_split = '${cfg.masterUrl}'.split(':') buildmaster_host = master_url_split[0] port = int(master_url_split[1]) workername = '${cfg.workerUser}' with open('${cfg.workerPassFile}', 'r', encoding='utf-8') as passwd_file: passwd = passwd_file.read().strip('\r\n') keepalive = ${toString cfg.keepalive} umask = None maxdelay = 300 numcpus = None allow_shutdown = None s = Worker(buildmaster_host, port, workername, passwd, basedir, keepalive, umask=umask, maxdelay=maxdelay, numcpus=numcpus, allow_shutdown=allow_shutdown) s.setServiceParent(application) ''; in { options = { services.buildbot-worker = { enable = mkOption { type = types.bool; default = false; description = lib.mdDoc "Whether to enable the Buildbot Worker."; }; user = mkOption { default = "bbworker"; type = types.str; description = lib.mdDoc "User the buildbot Worker should execute under."; }; group = mkOption { default = "bbworker"; type = types.str; description = lib.mdDoc "Primary group of buildbot Worker user."; }; extraGroups = mkOption { type = types.listOf types.str; default = []; description = lib.mdDoc "List of extra groups that the Buildbot Worker user should be a part of."; }; home = mkOption { default = "/home/bbworker"; type = types.path; description = lib.mdDoc "Buildbot home directory."; }; buildbotDir = mkOption { default = "${cfg.home}/worker"; defaultText = literalExpression ''"''${config.${opt.home}}/worker"''; type = types.path; description = lib.mdDoc "Specifies the Buildbot directory."; }; workerUser = mkOption { default = "example-worker"; type = types.str; description = lib.mdDoc "Specifies the Buildbot Worker user."; }; workerPass = mkOption { default = "pass"; type = types.str; description = lib.mdDoc "Specifies the Buildbot Worker password."; }; workerPassFile = mkOption { type = types.path; description = lib.mdDoc "File used to store the Buildbot Worker password"; }; hostMessage = mkOption { default = null; type = types.nullOr types.str; description = lib.mdDoc "Description of this worker"; }; adminMessage = mkOption { default = null; type = types.nullOr types.str; description = lib.mdDoc "Name of the administrator of this worker"; }; masterUrl = mkOption { default = "localhost:9989"; type = types.str; description = lib.mdDoc "Specifies the Buildbot Worker connection string."; }; keepalive = mkOption { default = 600; type = types.int; description = lib.mdDoc '' This is a number that indicates how frequently keepalive messages should be sent from the worker to the buildmaster, expressed in seconds. ''; }; package = mkOption { type = types.package; default = pkgs.python3Packages.buildbot-worker; defaultText = literalExpression "pkgs.python3Packages.buildbot-worker"; description = lib.mdDoc "Package to use for buildbot worker."; example = literalExpression "pkgs.python2Packages.buildbot-worker"; }; packages = mkOption { default = with pkgs; [ git ]; defaultText = literalExpression "[ pkgs.git ]"; type = types.listOf types.package; description = lib.mdDoc "Packages to add to PATH for the buildbot process."; }; }; }; config = mkIf cfg.enable { services.buildbot-worker.workerPassFile = mkDefault (pkgs.writeText "buildbot-worker-password" cfg.workerPass); users.groups = optionalAttrs (cfg.group == "bbworker") { bbworker = { }; }; users.users = optionalAttrs (cfg.user == "bbworker") { bbworker = { description = "Buildbot Worker User."; isNormalUser = true; createHome = true; home = cfg.home; group = cfg.group; extraGroups = cfg.extraGroups; useDefaultShell = true; }; }; systemd.services.buildbot-worker = { description = "Buildbot Worker."; after = [ "network.target" "buildbot-master.service" ]; wantedBy = [ "multi-user.target" ]; path = cfg.packages; environment.PYTHONPATH = "${python.withPackages (p: [ cfg.package ])}/${python.sitePackages}"; preStart = '' mkdir -vp "${cfg.buildbotDir}/info" ${optionalString (cfg.hostMessage != null) '' ln -sf "${pkgs.writeText "buildbot-worker-host" cfg.hostMessage}" "${cfg.buildbotDir}/info/host" ''} ${optionalString (cfg.adminMessage != null) '' ln -sf "${pkgs.writeText "buildbot-worker-admin" cfg.adminMessage}" "${cfg.buildbotDir}/info/admin" ''} ''; serviceConfig = { Type = "simple"; User = cfg.user; Group = cfg.group; WorkingDirectory = cfg.home; # NOTE: call twistd directly with stdout logging for systemd ExecStart = "${python.pkgs.twisted}/bin/twistd --nodaemon --pidfile= --logfile - --python ${tacFile}"; }; }; }; meta.maintainers = with lib.maintainers; [ ]; }