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