diff --git a/README.md b/README.md index 81dbdcd..a38d2b8 100644 --- a/README.md +++ b/README.md @@ -57,7 +57,8 @@ To integrate with GitHub: 1. **GitHub App**: Set up a GitHub app for Buildbot to enable GitHub user authentication on the Buildbot dashboard. 2. **OAuth Credentials**: After installing the app, generate OAuth credentials - and configure them in the buildbot-nix NixOS module. + and configure them in the buildbot-nix NixOS module. Set the callback url to + `https:///auth/login`. 3. **GitHub Token**: Obtain a GitHub token with `admin:repo_hook` and `repo` permissions. For GitHub organizations, it's advisable to create a separate GitHub user for managing repository webhooks. diff --git a/buildbot_nix/worker.py b/buildbot_nix/worker.py index 3f7139d..31ae821 100644 --- a/buildbot_nix/worker.py +++ b/buildbot_nix/worker.py @@ -11,7 +11,7 @@ from twisted.python import components def require_env(key: str) -> str: val = os.environ.get(key) - assert val is not None, "val is not set" + assert val is not None, f"{key} environment variable is not set" return val @@ -22,6 +22,9 @@ class WorkerConfig: .read_text() .rstrip("\r\n") ) + worker_name: str = field( + default_factory=lambda: os.environ.get("WORKER_NAME", socket.gethostname()) + ) worker_count: int = int( os.environ.get("WORKER_COUNT", str(multiprocessing.cpu_count())), ) @@ -39,8 +42,7 @@ def setup_worker( basedir = config.buildbot_dir.parent / f"{config.buildbot_dir.name}-{builder_id:03}" basedir.mkdir(parents=True, exist_ok=True, mode=0o700) - hostname = socket.gethostname() - workername = f"{hostname}-{builder_id:03}" + workername = f"{config.worker_name}-{builder_id:03}" keepalive = 600 umask = None maxdelay = 300 diff --git a/examples/default.nix b/examples/default.nix index f9fb42e..fcc3aae 100644 --- a/examples/default.nix +++ b/examples/default.nix @@ -15,61 +15,47 @@ let inherit (lib) nixosSystem; in { + # This runs both master and worker on the same machine. + # As the actual build is offloaded with remote builder, + # this also works well for production setups. + "example-master-worker-combined-${system}" = nixosSystem { + inherit system; + modules = [ + dummy + buildbot-nix.nixosModules.buildbot-master + buildbot-nix.nixosModules.buildbot-worker + ./master.nix + ./worker.nix + ]; + }; "example-master-${system}" = nixosSystem { inherit system; modules = [ dummy - ({ pkgs, ... }: { - services.buildbot-nix.master = { - enable = true; - domain = "buildbot2.thalheim.io"; - workersFile = pkgs.writeText "workers.json" '' - [ - { "name": "eve", "pass": "XXXXXXXXXXXXXXXXXXXX", "cores": 16 } - ] - ''; - github = { - tokenFile = pkgs.writeText "github-token" "ghp_000000000000000000000000000000000000"; - webhookSecretFile = pkgs.writeText "webhookSecret" "00000000000000000000"; - oauthSecretFile = pkgs.writeText "oauthSecret" "ffffffffffffffffffffffffffffffffffffffff"; - oauthId = "aaaaaaaaaaaaaaaaaaaa"; - user = "mic92-buildbot"; - admins = [ "Mic92" ]; - # All github projects with this topic will be added to buildbot. - # One can trigger a project scan by visiting the Builds -> Builders page and looking for the "reload-github-project" builder. - # This builder has a "Update Github Projects" button that everyone in the github organization can use. - topic = "buildbot-mic92"; - }; - # optional expose latest store path as text file - # outputsPath = "/var/www/buildbot/nix-outputs"; - - # optional nix-eval-jobs settings - # evalWorkerCount = 8; # limit number of concurrent evaluations - # evalMaxMemorySize = "2048"; # limit memory usage per evaluation - - # optional cachix - #cachix = { - # name = "my-cachix"; - # # One of the following is required: - # signingKey = "/var/lib/secrets/cachix-key"; - # authToken = "/var/lib/secrets/cachix-token"; - #}; - }; - }) buildbot-nix.nixosModules.buildbot-master + ./master.nix + # When master and worker run on different machines, + # we need to configure the master to listen on a public address. + # Also check out the buildbot upstream documentation on the master-worker protocol, + # including tls encryption + { + # exposes the master build protocol on port 9989 + services.buildbot-master.extraConfig = '' + c["protocols"] = {"pb": {"port": "tcp:9989:interface=\\:\\:"}} + ''; + networking.firewall.allowedTCPPorts = [ 9989 ]; + } ]; }; + "example-worker-${system}" = nixosSystem { inherit system; modules = [ dummy - ({ pkgs, ... }: { - services.buildbot-nix.worker = { - enable = true; - workerPasswordFile = pkgs.writeText "worker-password-file" ""; - }; - }) buildbot-nix.nixosModules.buildbot-worker + ./worker.nix + # Connects to a master on the ipv6 address 2a09:80c0:102::1 + { services.buildbot-nix.worker.masterUrl = ''tcp:host=2a09\:80c0\:102\:\:1:port=9989''; } ]; }; } diff --git a/examples/master.nix b/examples/master.nix new file mode 100644 index 0000000..4ced75f --- /dev/null +++ b/examples/master.nix @@ -0,0 +1,59 @@ +{ pkgs, ... }: +{ + services.buildbot-nix.master = { + enable = true; + # Domain name under which the buildbot frontend is reachable + domain = "buildbot2.thalheim.io"; + # The workers file configures credentials for the buildbot workers to connect to the master. + # "name" is the configured worker name in services.buildbot-nix.worker.name of a worker + # (defaults to the hostname of the machine) + # "pass" is the password for the worker configured in `services.buildbot-nix.worker.workerPasswordFile` + # "cores" is the number of cpu cores the worker has. + # The number must match as otherwise potentially not enought buildbot-workers are created. + workersFile = pkgs.writeText "workers.json" '' + [ + { "name": "eve", "pass": "XXXXXXXXXXXXXXXXXXXX", "cores": 16 } + ] + ''; + github = { + # Github user used as a CI identity + user = "mic92-buildbot"; + # Github token of the same user + tokenFile = pkgs.writeText "github-token" "ghp_000000000000000000000000000000000000"; + # A random secret used to verify incoming webhooks from GitHub + # buildbot-nix will set up a webhook for each project in the organization + webhookSecretFile = pkgs.writeText "webhookSecret" "00000000000000000000"; + # Either create a GitHub app or an OAuth app + # After creating the app, press "Generate a new client secret" and fill in the client ID and secret below + oauthId = "aaaaaaaaaaaaaaaaaaaa"; + oauthSecretFile = pkgs.writeText "oauthSecret" "ffffffffffffffffffffffffffffffffffffffff"; + # Users in this list will be able to reload the project list. + # All other user in the organization will be able to restart builds or evaluations. + admins = [ "Mic92" ]; + # All github projects with this topic will be added to buildbot. + # One can trigger a project scan by visiting the Builds -> Builders page and looking for the "reload-github-project" builder. + # This builder has a "Update Github Projects" button that everyone in the github organization can use. + topic = "buildbot-mic92"; + }; + # optional expose latest store path as text file + # outputsPath = "/var/www/buildbot/nix-outputs"; + + # optional nix-eval-jobs settings + # evalWorkerCount = 8; # limit number of concurrent evaluations + # evalMaxMemorySize = "2048"; # limit memory usage per evaluation + + # optional cachix + #cachix = { + # name = "my-cachix"; + # # One of the following is required: + # signingKey = "/var/lib/secrets/cachix-key"; + # authToken = "/var/lib/secrets/cachix-token"; + #}; + }; + + # Optional: Enable acme/TLS in nginx (recommended) + #services.nginx.virtualHosts.${config.services.buildbot-nix.master.domain} = { + # forceSSL = true; + # useACME = true; + #}; +} diff --git a/examples/worker.nix b/examples/worker.nix new file mode 100644 index 0000000..54bbc7c --- /dev/null +++ b/examples/worker.nix @@ -0,0 +1,7 @@ +{ pkgs, ... }: +{ + services.buildbot-nix.worker = { + enable = true; + workerPasswordFile = pkgs.writeText "worker-password-file" "XXXXXXXXXXXXXXXXXXXX"; + }; +} diff --git a/nix/worker.nix b/nix/worker.nix index cf804fa..f7f1ae5 100644 --- a/nix/worker.nix +++ b/nix/worker.nix @@ -13,6 +13,11 @@ in options = { services.buildbot-nix.worker = { enable = lib.mkEnableOption "buildbot-worker"; + name = lib.mkOption { + type = lib.types.str; + default = config.networking.hostName; + description = "The buildbot worker name."; + }; package = lib.mkOption { type = lib.types.package; default = pkgs.buildbot-worker; @@ -70,7 +75,10 @@ in OOMPolicy = "continue"; LoadCredential = [ "worker-password-file:${cfg.workerPasswordFile}" ]; - Environment = [ "WORKER_PASSWORD_FILE=%d/worker-password-file" ]; + Environment = [ + "WORKER_PASSWORD_FILE=%d/worker-password-file" + "WORKER_NAME=${cfg.name}" + ]; Type = "simple"; User = "buildbot-worker"; Group = "buildbot-worker";