1# NixOS module for Buildbot Worker. 2 3{ config, lib, pkgs, ... }: 4 5with lib; 6 7let 8 cfg = config.services.buildbot-worker; 9 10 python = cfg.package.pythonModule; 11 12 tacFile = pkgs.writeText "aur-buildbot-worker.tac" '' 13 import os 14 from io import open 15 16 from buildbot_worker.bot import Worker 17 from twisted.application import service 18 19 basedir = '${cfg.buildbotDir}' 20 21 # note: this line is matched against to check that this is a worker 22 # directory; do not edit it. 23 application = service.Application('buildbot-worker') 24 25 master_url_split = '${cfg.masterUrl}'.split(':') 26 buildmaster_host = master_url_split[0] 27 port = int(master_url_split[1]) 28 workername = '${cfg.workerUser}' 29 30 with open('${cfg.workerPassFile}', 'r', encoding='utf-8') as passwd_file: 31 passwd = passwd_file.read().strip('\r\n') 32 keepalive = ${toString cfg.keepalive} 33 umask = None 34 maxdelay = 300 35 numcpus = None 36 allow_shutdown = None 37 38 s = Worker(buildmaster_host, port, workername, passwd, basedir, 39 keepalive, umask=umask, maxdelay=maxdelay, 40 numcpus=numcpus, allow_shutdown=allow_shutdown) 41 s.setServiceParent(application) 42 ''; 43 44in { 45 options = { 46 services.buildbot-worker = { 47 48 enable = mkOption { 49 type = types.bool; 50 default = false; 51 description = "Whether to enable the Buildbot Worker."; 52 }; 53 54 user = mkOption { 55 default = "bbworker"; 56 type = types.str; 57 description = "User the buildbot Worker should execute under."; 58 }; 59 60 group = mkOption { 61 default = "bbworker"; 62 type = types.str; 63 description = "Primary group of buildbot Worker user."; 64 }; 65 66 extraGroups = mkOption { 67 type = types.listOf types.str; 68 default = []; 69 description = "List of extra groups that the Buildbot Worker user should be a part of."; 70 }; 71 72 home = mkOption { 73 default = "/home/bbworker"; 74 type = types.path; 75 description = "Buildbot home directory."; 76 }; 77 78 buildbotDir = mkOption { 79 default = "${cfg.home}/worker"; 80 type = types.path; 81 description = "Specifies the Buildbot directory."; 82 }; 83 84 workerUser = mkOption { 85 default = "example-worker"; 86 type = types.str; 87 description = "Specifies the Buildbot Worker user."; 88 }; 89 90 workerPass = mkOption { 91 default = "pass"; 92 type = types.str; 93 description = "Specifies the Buildbot Worker password."; 94 }; 95 96 workerPassFile = mkOption { 97 type = types.path; 98 description = "File used to store the Buildbot Worker password"; 99 }; 100 101 hostMessage = mkOption { 102 default = null; 103 type = types.nullOr types.str; 104 description = "Description of this worker"; 105 }; 106 107 adminMessage = mkOption { 108 default = null; 109 type = types.nullOr types.str; 110 description = "Name of the administrator of this worker"; 111 }; 112 113 masterUrl = mkOption { 114 default = "localhost:9989"; 115 type = types.str; 116 description = "Specifies the Buildbot Worker connection string."; 117 }; 118 119 keepalive = mkOption { 120 default = 600; 121 type = types.int; 122 description = " 123 This is a number that indicates how frequently keepalive messages should be sent 124 from the worker to the buildmaster, expressed in seconds. 125 "; 126 }; 127 128 package = mkOption { 129 type = types.package; 130 default = pkgs.python3Packages.buildbot-worker; 131 defaultText = "pkgs.python3Packages.buildbot-worker"; 132 description = "Package to use for buildbot worker."; 133 example = literalExample "pkgs.python2Packages.buildbot-worker"; 134 }; 135 136 packages = mkOption { 137 default = with pkgs; [ git ]; 138 example = literalExample "[ pkgs.git ]"; 139 type = types.listOf types.package; 140 description = "Packages to add to PATH for the buildbot process."; 141 }; 142 }; 143 }; 144 145 config = mkIf cfg.enable { 146 services.buildbot-worker.workerPassFile = mkDefault (pkgs.writeText "buildbot-worker-password" cfg.workerPass); 147 148 users.groups = optionalAttrs (cfg.group == "bbworker") { 149 bbworker = { }; 150 }; 151 152 users.users = optionalAttrs (cfg.user == "bbworker") { 153 bbworker = { 154 description = "Buildbot Worker User."; 155 isNormalUser = true; 156 createHome = true; 157 home = cfg.home; 158 group = cfg.group; 159 extraGroups = cfg.extraGroups; 160 useDefaultShell = true; 161 }; 162 }; 163 164 systemd.services.buildbot-worker = { 165 description = "Buildbot Worker."; 166 after = [ "network.target" "buildbot-master.service" ]; 167 wantedBy = [ "multi-user.target" ]; 168 path = cfg.packages; 169 environment.PYTHONPATH = "${python.withPackages (p: [ cfg.package ])}/${python.sitePackages}"; 170 171 preStart = '' 172 mkdir -vp "${cfg.buildbotDir}/info" 173 ${optionalString (cfg.hostMessage != null) '' 174 ln -sf "${pkgs.writeText "buildbot-worker-host" cfg.hostMessage}" "${cfg.buildbotDir}/info/host" 175 ''} 176 ${optionalString (cfg.adminMessage != null) '' 177 ln -sf "${pkgs.writeText "buildbot-worker-admin" cfg.adminMessage}" "${cfg.buildbotDir}/info/admin" 178 ''} 179 ''; 180 181 serviceConfig = { 182 Type = "simple"; 183 User = cfg.user; 184 Group = cfg.group; 185 WorkingDirectory = cfg.home; 186 187 # NOTE: call twistd directly with stdout logging for systemd 188 ExecStart = "${python.pkgs.twisted}/bin/twistd --nodaemon --pidfile= --logfile - --python ${tacFile}"; 189 }; 190 191 }; 192 }; 193 194 meta.maintainers = with lib.maintainers; [ ]; 195 196}