aboutsummaryrefslogtreecommitdiff
path: root/nixpkgs/nixos/modules/services/continuous-integration/buildbot/master.nix
diff options
context:
space:
mode:
Diffstat (limited to 'nixpkgs/nixos/modules/services/continuous-integration/buildbot/master.nix')
-rw-r--r--nixpkgs/nixos/modules/services/continuous-integration/buildbot/master.nix267
1 files changed, 267 insertions, 0 deletions
diff --git a/nixpkgs/nixos/modules/services/continuous-integration/buildbot/master.nix b/nixpkgs/nixos/modules/services/continuous-integration/buildbot/master.nix
new file mode 100644
index 00000000000..9c615fbe885
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/continuous-integration/buildbot/master.nix
@@ -0,0 +1,267 @@
+# NixOS module for Buildbot continous integration server.
+
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+ cfg = config.services.buildbot-master;
+
+ python = cfg.package.pythonModule;
+
+ escapeStr = s: escape ["'"] s;
+
+ defaultMasterCfg = pkgs.writeText "master.cfg" ''
+ from buildbot.plugins import *
+ factory = util.BuildFactory()
+ c = BuildmasterConfig = dict(
+ workers = [${concatStringsSep "," cfg.workers}],
+ protocols = { 'pb': {'port': ${toString cfg.bpPort} } },
+ title = '${escapeStr cfg.title}',
+ titleURL = '${escapeStr cfg.titleUrl}',
+ buildbotURL = '${escapeStr cfg.buildbotUrl}',
+ db = dict(db_url='${escapeStr cfg.dbUrl}'),
+ www = dict(port=${toString cfg.port}),
+ change_source = [ ${concatStringsSep "," cfg.changeSource} ],
+ schedulers = [ ${concatStringsSep "," cfg.schedulers} ],
+ builders = [ ${concatStringsSep "," cfg.builders} ],
+ status = [ ${concatStringsSep "," cfg.status} ],
+ )
+ for step in [ ${concatStringsSep "," cfg.factorySteps} ]:
+ factory.addStep(step)
+
+ ${cfg.extraConfig}
+ '';
+
+ tacFile = pkgs.writeText "buildbot-master.tac" ''
+ import os
+
+ from twisted.application import service
+ from buildbot.master import BuildMaster
+
+ basedir = '${cfg.buildbotDir}'
+
+ configfile = '${cfg.masterCfg}'
+
+ # Default umask for server
+ umask = None
+
+ # note: this line is matched against to check that this is a buildmaster
+ # directory; do not edit it.
+ application = service.Application('buildmaster')
+
+ m = BuildMaster(basedir, configfile, umask)
+ m.setServiceParent(application)
+ '';
+
+in {
+ options = {
+ services.buildbot-master = {
+
+ factorySteps = mkOption {
+ type = types.listOf types.str;
+ description = "Factory Steps";
+ default = [];
+ example = [
+ "steps.Git(repourl='git://github.com/buildbot/pyflakes.git', mode='incremental')"
+ "steps.ShellCommand(command=['trial', 'pyflakes'])"
+ ];
+ };
+
+ changeSource = mkOption {
+ type = types.listOf types.str;
+ description = "List of Change Sources.";
+ default = [];
+ example = [
+ "changes.GitPoller('git://github.com/buildbot/pyflakes.git', workdir='gitpoller-workdir', branch='master', pollinterval=300)"
+ ];
+ };
+
+ enable = mkOption {
+ type = types.bool;
+ default = false;
+ description = "Whether to enable the Buildbot continuous integration server.";
+ };
+
+ extraConfig = mkOption {
+ type = types.str;
+ description = "Extra configuration to append to master.cfg";
+ default = "c['buildbotNetUsageData'] = None";
+ };
+
+ masterCfg = mkOption {
+ type = types.path;
+ description = "Optionally pass master.cfg path. Other options in this configuration will be ignored.";
+ default = defaultMasterCfg;
+ example = "/etc/nixos/buildbot/master.cfg";
+ };
+
+ schedulers = mkOption {
+ type = types.listOf types.str;
+ description = "List of Schedulers.";
+ default = [
+ "schedulers.SingleBranchScheduler(name='all', change_filter=util.ChangeFilter(branch='master'), treeStableTimer=None, builderNames=['runtests'])"
+ "schedulers.ForceScheduler(name='force',builderNames=['runtests'])"
+ ];
+ };
+
+ builders = mkOption {
+ type = types.listOf types.str;
+ description = "List of Builders.";
+ default = [
+ "util.BuilderConfig(name='runtests',workernames=['example-worker'],factory=factory)"
+ ];
+ };
+
+ workers = mkOption {
+ type = types.listOf types.str;
+ description = "List of Workers.";
+ default = [ "worker.Worker('example-worker', 'pass')" ];
+ };
+
+ status = mkOption {
+ default = [];
+ type = types.listOf types.str;
+ description = "List of status notification endpoints.";
+ };
+
+ user = mkOption {
+ default = "buildbot";
+ type = types.str;
+ description = "User the buildbot server should execute under.";
+ };
+
+ group = mkOption {
+ default = "buildbot";
+ type = types.str;
+ description = "Primary group of buildbot user.";
+ };
+
+ extraGroups = mkOption {
+ type = types.listOf types.str;
+ default = [];
+ description = "List of extra groups that the buildbot user should be a part of.";
+ };
+
+ home = mkOption {
+ default = "/home/buildbot";
+ type = types.path;
+ description = "Buildbot home directory.";
+ };
+
+ buildbotDir = mkOption {
+ default = "${cfg.home}/master";
+ type = types.path;
+ description = "Specifies the Buildbot directory.";
+ };
+
+ bpPort = mkOption {
+ default = 9989;
+ type = types.int;
+ description = "Port where the master will listen to Buildbot Worker.";
+ };
+
+ listenAddress = mkOption {
+ default = "0.0.0.0";
+ type = types.str;
+ description = "Specifies the bind address on which the buildbot HTTP interface listens.";
+ };
+
+ buildbotUrl = mkOption {
+ default = "http://localhost:8010/";
+ type = types.str;
+ description = "Specifies the Buildbot URL.";
+ };
+
+ title = mkOption {
+ default = "Buildbot";
+ type = types.str;
+ description = "Specifies the Buildbot Title.";
+ };
+
+ titleUrl = mkOption {
+ default = "Buildbot";
+ type = types.str;
+ description = "Specifies the Buildbot TitleURL.";
+ };
+
+ dbUrl = mkOption {
+ default = "sqlite:///state.sqlite";
+ type = types.str;
+ description = "Specifies the database connection string.";
+ };
+
+ port = mkOption {
+ default = 8010;
+ type = types.int;
+ description = "Specifies port number on which the buildbot HTTP interface listens.";
+ };
+
+ package = mkOption {
+ type = types.package;
+ default = pkgs.python3Packages.buildbot-full;
+ defaultText = "pkgs.python3Packages.buildbot-full";
+ description = "Package to use for buildbot.";
+ example = literalExample "pkgs.python3Packages.buildbot";
+ };
+
+ packages = mkOption {
+ default = [ pkgs.git ];
+ example = literalExample "[ pkgs.git ]";
+ type = types.listOf types.package;
+ description = "Packages to add to PATH for the buildbot process.";
+ };
+
+ pythonPackages = mkOption {
+ default = pythonPackages: with pythonPackages; [ ];
+ defaultText = "pythonPackages: with pythonPackages; [ ]";
+ description = "Packages to add the to the PYTHONPATH of the buildbot process.";
+ example = literalExample "pythonPackages: with pythonPackages; [ requests ]";
+ };
+ };
+ };
+
+ config = mkIf cfg.enable {
+ users.groups = optional (cfg.group == "buildbot") {
+ name = "buildbot";
+ };
+
+ users.users = optional (cfg.user == "buildbot") {
+ name = "buildbot";
+ description = "Buildbot User.";
+ isNormalUser = true;
+ createHome = true;
+ home = cfg.home;
+ group = cfg.group;
+ extraGroups = cfg.extraGroups;
+ useDefaultShell = true;
+ };
+
+ systemd.services.buildbot-master = {
+ description = "Buildbot Continuous Integration Server.";
+ after = [ "network-online.target" ];
+ wantedBy = [ "multi-user.target" ];
+ path = cfg.packages ++ cfg.pythonPackages python.pkgs;
+ environment.PYTHONPATH = "${python.withPackages (self: cfg.pythonPackages self ++ [ cfg.package ])}/${python.sitePackages}";
+
+ preStart = ''
+ mkdir -vp "${cfg.buildbotDir}"
+ # Link the tac file so buildbot command line tools recognize the directory
+ ln -sf "${tacFile}" "${cfg.buildbotDir}/buildbot.tac"
+ ${cfg.package}/bin/buildbot create-master --db "${cfg.dbUrl}" "${cfg.buildbotDir}"
+ rm -f buildbot.tac.new master.cfg.sample
+ '';
+
+ 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 -o --nodaemon --pidfile= --logfile - --python ${tacFile}";
+ };
+ };
+ };
+
+ meta.maintainers = with lib.maintainers; [ nand0p mic92 ];
+}