diff --git a/nixos/modules/misc/ids.nix b/nixos/modules/misc/ids.nix index ad344dfbc11..6b41c7c7c0e 100644 --- a/nixos/modules/misc/ids.nix +++ b/nixos/modules/misc/ids.nix @@ -117,6 +117,7 @@ couchdb = 106; searx = 107; kippo = 108; + jenkins = 109; # When adding a uid, make sure it doesn't match an existing gid. @@ -212,6 +213,7 @@ couchdb = 106; searx = 107; kippo = 108; + jenkins = 109; # When adding a gid, make sure it doesn't match an existing uid. diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix index 8a7d32adf34..b419942057a 100644 --- a/nixos/modules/module-list.nix +++ b/nixos/modules/module-list.nix @@ -81,6 +81,8 @@ ./services/backup/rsnapshot.nix ./services/backup/sitecopy-backup.nix ./services/backup/tarsnap.nix + ./services/continuous-integration/jenkins/default.nix + ./services/continuous-integration/jenkins/slave.nix ./services/databases/4store-endpoint.nix ./services/databases/4store.nix ./services/databases/couchdb.nix diff --git a/nixos/modules/services/continuous-integration/jenkins/default.nix b/nixos/modules/services/continuous-integration/jenkins/default.nix new file mode 100644 index 00000000000..c3dc59a9fbd --- /dev/null +++ b/nixos/modules/services/continuous-integration/jenkins/default.nix @@ -0,0 +1,118 @@ +{ config, pkgs, ... }: +with pkgs.lib; +let + cfg = config.services.jenkins; +in { + options = { + services.jenkins = { + enable = mkOption { + type = types.bool; + default = false; + description = '' + Whether to enable the jenkins continuous integration server. + ''; + }; + + user = mkOption { + default = "jenkins"; + type = with types; string; + description = '' + User the jenkins server should execute under. + ''; + }; + + group = mkOption { + default = "jenkins"; + type = with types; string; + description = '' + User the jenkins server should execute under. + ''; + }; + + home = mkOption { + default = "/var/lib/jenkins"; + type = with types; string; + description = '' + The path to use as JENKINS_HOME. If the default user "jenkins" is configured then + this is the home of the "jenkins" user. + ''; + }; + + port = mkOption { + default = 8080; + type = types.uniq types.int; + description = '' + Specifies port number on which the jenkins HTTP interface listens. The default is 8080 + ''; + }; + + packages = mkOption { + default = [ pkgs.stdenv pkgs.git pkgs.jdk pkgs.openssh pkgs.nix ]; + type = types.listOf types.package; + description = '' + Packages to add to PATH for the jenkins process. + ''; + }; + + environment = mkOption { + default = { NIX_REMOTE = "daemon"; }; + type = with types; attrsOf string; + description = '' + Additional environment variables to be passed to the jenkins process. + The environment will always include JENKINS_HOME. + ''; + }; + }; + }; + + config = mkIf cfg.enable { + users.extraGroups = optional (cfg.group == "jenkins") { + name = "jenkins"; + gid = config.ids.gids.jenkins; + }; + + users.extraUsers = optional (cfg.user == "jenkins") { + name = "jenkins"; + description = "jenkins user"; + createHome = true; + home = cfg.home; + group = cfg.group; + useDefaultShell = true; + uid = config.ids.uids.jenkins; + }; + + systemd.services.jenkins = { + description = "Jenkins Continuous Integration Server"; + after = [ "network.target" ]; + wantedBy = [ "multi-user.target" ]; + + environment = { + JENKINS_HOME = cfg.home; + } // cfg.environment; + + path = cfg.packages; + + script = '' + ${pkgs.jdk}/bin/java -jar ${pkgs.jenkins} --httpPort=${toString cfg.port} + ''; + + postStart = '' + until ${pkgs.curl}/bin/curl -s -L localhost:${toString cfg.port} ; do + sleep 10 + done + while true ; do + index=`${pkgs.curl}/bin/curl -s -L localhost:${toString cfg.port}` + if [[ !("$index" =~ 'Please wait while Jenkins is restarting' || + "$index" =~ 'Please wait while Jenkins is getting ready to work') ]]; then + exit 0 + fi + sleep 30 + done + ''; + + serviceConfig = { + User = cfg.user; + }; + }; + }; +} diff --git a/nixos/modules/services/continuous-integration/jenkins/slave.nix b/nixos/modules/services/continuous-integration/jenkins/slave.nix new file mode 100644 index 00000000000..1d31ab830f6 --- /dev/null +++ b/nixos/modules/services/continuous-integration/jenkins/slave.nix @@ -0,0 +1,67 @@ +{ config, pkgs, ... }: +with pkgs.lib; +let + cfg = config.services.jenkinsSlave; + masterCfg = config.services.jenkins; +in { + options = { + services.jenkinsSlave = { + # todo: + # * assure the profile of the jenkins user has a JRE and any specified packages. This would + # enable ssh slaves. + # * Optionally configure the node as a jenkins ad-hoc slave. This would imply configuration + # properties for the master node. + enable = mkOption { + type = types.bool; + default = false; + description = '' + If true the system will be configured to work as a jenkins slave. + If the system is also configured to work as a jenkins master then this has no effect. + In progress: Currently only assures the jenkins user is configured. + ''; + }; + + user = mkOption { + default = "jenkins"; + type = with types; string; + description = '' + User the jenkins slave agent should execute under. + ''; + }; + + group = mkOption { + default = "jenkins"; + type = with types; string; + description = '' + User the jenkins slave agent should execute under. + ''; + }; + + home = mkOption { + default = "/var/lib/jenkins"; + type = with types; string; + description = '' + The path to use as JENKINS_HOME. If the default user "jenkins" is configured then + this is the home of the "jenkins" user. + ''; + }; + }; + }; + + config = mkIf (cfg.enable && !masterCfg.enable) { + users.extraGroups = optional (cfg.group == "jenkins") { + name = "jenkins"; + gid = config.ids.gids.jenkins; + }; + + users.extraUsers = optional (cfg.user == "jenkins") { + name = "jenkins"; + description = "jenkins user"; + createHome = true; + home = cfg.home; + group = cfg.group; + useDefaultShell = true; + uid = config.ids.uids.jenkins; + }; + }; +} diff --git a/nixos/tests/default.nix b/nixos/tests/default.nix index b37a0d5fa0c..5b68862a2cd 100644 --- a/nixos/tests/default.nix +++ b/nixos/tests/default.nix @@ -14,6 +14,7 @@ with import ../lib/testing.nix { inherit system minimal; }; efi-installer = makeTests (import ./efi-installer.nix); gnome3 = makeTest (import ./gnome3.nix); ipv6 = makeTest (import ./ipv6.nix); + jenkins = makeTest (import ./jenkins.nix); kde4 = makeTest (import ./kde4.nix); #kexec = makeTest (import ./kexec.nix); login = makeTest (import ./login.nix {}); diff --git a/nixos/tests/jenkins.nix b/nixos/tests/jenkins.nix new file mode 100644 index 00000000000..e6524ec5653 --- /dev/null +++ b/nixos/tests/jenkins.nix @@ -0,0 +1,35 @@ +# verifies: +# 1. jenkins service starts on master node +# 2. jenkins user can be extended on both master and slave +# 3. jenkins service not started on slave node +{ pkgs, ... }: +{ + nodes = { + master = { pkgs, config, ... }: { + services.jenkins.enable = true; + + # should have no effect + services.jenkinsSlave.enable = true; + + users.extraUsers.jenkins.extraGroups = [ "users" ]; + }; + slave = { pkgs, config, ... }: { + services.jenkinsSlave.enable = true; + + users.extraUsers.jenkins.extraGroups = [ "users" ]; + }; + }; + + testScript = '' + startAll; + + $master->waitForUnit("jenkins"); + print $master->execute("sudo -u jenkins groups"); + $master->mustSucceed("sudo -u jenkins groups | grep jenkins | grep users"); + + print $slave->execute("sudo -u jenkins groups"); + $slave->mustSucceed("sudo -u jenkins groups | grep jenkins | grep users"); + + $slave->mustFail("systemctl status jenkins.service"); + ''; +} diff --git a/pkgs/development/tools/continuous-integration/jenkins/default.nix b/pkgs/development/tools/continuous-integration/jenkins/default.nix new file mode 100644 index 00000000000..5194684261c --- /dev/null +++ b/pkgs/development/tools/continuous-integration/jenkins/default.nix @@ -0,0 +1,20 @@ +{ stdenv, fetchurl }: + +stdenv.mkDerivation rec { + name = "jenkins"; + version = "1.550"; + + src = fetchurl { + url = "http://mirrors.jenkins-ci.org/war/${version}/jenkins.war"; + sha256 = "1ziimbfs9kylga0xmxlfsfcc7qsirs5bnx00pa99m2l5sz2ki793"; + }; + meta = { + description = "An extendable open source continuous integration server."; + homepage = http://jenkins-ci.org; + license = stdenv.lib.licenses.mit; + platforms = stdenv.lib.platforms.all; + maintainers = [ stdenv.lib.maintainers.coconnor ]; + }; + + buildCommand = "ln -s $src $out"; +} diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix index 4603179fafc..4bb7acfba1f 100644 --- a/pkgs/top-level/all-packages.nix +++ b/pkgs/top-level/all-packages.nix @@ -3686,6 +3686,8 @@ let jikespg = callPackage ../development/tools/parsing/jikespg { }; + jenkins = callPackage ../development/tools/continuous-integration/jenkins { }; + lcov = callPackage ../development/tools/analysis/lcov { }; leiningen = callPackage ../development/tools/build-managers/leiningen { };