nixos: add services.jenkins.jobBuilder option
This option allows to define (declarative) Jenkins jobs, using Jenkins Job Builder (JJB) as backend. Example: services.jenkins = { enable = true; jobBuilder = { enable = true; yamlJobs = '' - job: name: jenkins-job-test builders: - shell: echo 'Hello world!' ''; }; }; Jobs can be defined using YAML, JSON and Nix. Note that it really is declarative configuration; if you remove a previously defined job, the module will remove the jobdir under $JENKINS_HOME. Jobs managed through the Jenkins WebUI (or by other means) are not touched by this module. Changes v1 -> v2: * add nixJobs * let jsonJobs take a list of strings (allows merge) * 4 space indent in shell code
This commit is contained in:
parent
a487b3326b
commit
27f41d8c0a
|
@ -118,6 +118,7 @@
|
||||||
./services/computing/slurm/slurm.nix
|
./services/computing/slurm/slurm.nix
|
||||||
./services/continuous-integration/jenkins/default.nix
|
./services/continuous-integration/jenkins/default.nix
|
||||||
./services/continuous-integration/jenkins/slave.nix
|
./services/continuous-integration/jenkins/slave.nix
|
||||||
|
./services/continuous-integration/jenkins/job-builder.nix
|
||||||
./services/databases/4store-endpoint.nix
|
./services/databases/4store-endpoint.nix
|
||||||
./services/databases/4store.nix
|
./services/databases/4store.nix
|
||||||
./services/databases/couchdb.nix
|
./services/databases/couchdb.nix
|
||||||
|
|
|
@ -0,0 +1,155 @@
|
||||||
|
{ config, lib, pkgs, ... }:
|
||||||
|
|
||||||
|
with lib;
|
||||||
|
|
||||||
|
let
|
||||||
|
jenkinsCfg = config.services.jenkins;
|
||||||
|
cfg = config.services.jenkins.jobBuilder;
|
||||||
|
|
||||||
|
in {
|
||||||
|
options = {
|
||||||
|
services.jenkins.jobBuilder = {
|
||||||
|
enable = mkOption {
|
||||||
|
type = types.bool;
|
||||||
|
default = false;
|
||||||
|
description = ''
|
||||||
|
Whether or not to enable the Jenkins Job Builder (JJB) service. It
|
||||||
|
allows defining jobs for Jenkins in a declarative manner.
|
||||||
|
|
||||||
|
Jobs managed through the Jenkins WebUI (or by other means) are left
|
||||||
|
unchanged.
|
||||||
|
|
||||||
|
Note that it really is declarative configuration; if you remove a
|
||||||
|
previously defined job, the corresponding job directory will be
|
||||||
|
deleted.
|
||||||
|
|
||||||
|
Please see the Jenkins Job Builder documentation for more info:
|
||||||
|
<link xlink:href="http://docs.openstack.org/infra/jenkins-job-builder/">
|
||||||
|
http://docs.openstack.org/infra/jenkins-job-builder/</link>
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
yamlJobs = mkOption {
|
||||||
|
default = "";
|
||||||
|
type = types.lines;
|
||||||
|
example = ''
|
||||||
|
- job:
|
||||||
|
name: jenkins-job-test-1
|
||||||
|
builders:
|
||||||
|
- shell: echo 'Hello world!'
|
||||||
|
'';
|
||||||
|
description = ''
|
||||||
|
Job descriptions for Jenkins Job Builder in YAML format.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
jsonJobs = mkOption {
|
||||||
|
default = [ ];
|
||||||
|
type = types.listOf types.str;
|
||||||
|
example = literalExample ''
|
||||||
|
[
|
||||||
|
'''
|
||||||
|
[ { "job":
|
||||||
|
{ "name": "jenkins-job-test-2",
|
||||||
|
"builders": [ "shell": "echo 'Hello world!'" ]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
'''
|
||||||
|
]
|
||||||
|
'';
|
||||||
|
description = ''
|
||||||
|
Job descriptions for Jenkins Job Builder in JSON format.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
nixJobs = mkOption {
|
||||||
|
default = [ ];
|
||||||
|
type = types.listOf types.attrs;
|
||||||
|
example = literalExample ''
|
||||||
|
[ { job =
|
||||||
|
{ name = "jenkins-job-test-3";
|
||||||
|
builders = [
|
||||||
|
{ shell = "echo 'Hello world!'"; }
|
||||||
|
];
|
||||||
|
};
|
||||||
|
}
|
||||||
|
];
|
||||||
|
'';
|
||||||
|
description = ''
|
||||||
|
Job descriptions for Jenkins Job Builder in Nix format.
|
||||||
|
|
||||||
|
This is a trivial wrapper around jsonJobs, using builtins.toJSON
|
||||||
|
behind the scene.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = mkIf (jenkinsCfg.enable && cfg.enable) {
|
||||||
|
systemd.services.jenkins-job-builder = {
|
||||||
|
description = "Jenkins Job Builder Service";
|
||||||
|
# JJB can run either before or after jenkins. We chose after, so we can
|
||||||
|
# always use curl to notify (running) jenkins to reload its config.
|
||||||
|
after = [ "jenkins.service" ];
|
||||||
|
wantedBy = [ "multi-user.target" ];
|
||||||
|
|
||||||
|
path = with pkgs; [ jenkins-job-builder curl ];
|
||||||
|
|
||||||
|
# Q: Why manipulate files directly instead of using "jenkins-jobs upload [...]"?
|
||||||
|
# A: Because this module is for administering a local jenkins install,
|
||||||
|
# and using local file copy allows us to not worry about
|
||||||
|
# authentication.
|
||||||
|
script =
|
||||||
|
let
|
||||||
|
yamlJobsFile = builtins.toFile "jobs.yaml" cfg.yamlJobs;
|
||||||
|
jsonJobsFiles =
|
||||||
|
map (x: (builtins.toFile "jobs.json" x))
|
||||||
|
(cfg.jsonJobs ++ [(builtins.toJSON cfg.nixJobs)]);
|
||||||
|
jobBuilderOutputDir = "/run/jenkins-job-builder/output";
|
||||||
|
# Stamp file is placed in $JENKINS_HOME/jobs/$JOB_NAME/ to indicate
|
||||||
|
# ownership. Enables tracking and removal of stale jobs.
|
||||||
|
ownerStamp = ".config-xml-managed-by-nixos-jenkins-job-builder";
|
||||||
|
in
|
||||||
|
''
|
||||||
|
rm -rf ${jobBuilderOutputDir}
|
||||||
|
cur_decl_jobs=/run/jenkins-job-builder/declarative-jobs
|
||||||
|
rm -f "$cur_decl_jobs"
|
||||||
|
|
||||||
|
# Create / update jobs
|
||||||
|
mkdir -p ${jobBuilderOutputDir}
|
||||||
|
for inputFile in ${yamlJobsFile} ${concatStringsSep " " jsonJobsFiles}; do
|
||||||
|
HOME="${jenkinsCfg.home}" "${pkgs.jenkins-job-builder}/bin/jenkins-jobs" --ignore-cache test -o "${jobBuilderOutputDir}" "$inputFile"
|
||||||
|
done
|
||||||
|
|
||||||
|
for file in "${jobBuilderOutputDir}/"*; do
|
||||||
|
test -f "$file" || continue
|
||||||
|
jobname="$(basename $file)"
|
||||||
|
jobdir="${jenkinsCfg.home}/jobs/$jobname"
|
||||||
|
echo "Creating / updating job \"$jobname\""
|
||||||
|
mkdir -p "$jobdir"
|
||||||
|
touch "$jobdir/${ownerStamp}"
|
||||||
|
cp "$file" "$jobdir/config.xml"
|
||||||
|
echo "$jobname" >> "$cur_decl_jobs"
|
||||||
|
done
|
||||||
|
|
||||||
|
# Remove stale jobs
|
||||||
|
for file in "${jenkinsCfg.home}"/jobs/*/${ownerStamp}; do
|
||||||
|
test -f "$file" || continue
|
||||||
|
jobdir="$(dirname $file)"
|
||||||
|
jobname="$(basename "$jobdir")"
|
||||||
|
grep --quiet --line-regexp "$jobname" "$cur_decl_jobs" 2>/dev/null && continue
|
||||||
|
echo "Deleting stale job \"$jobname\""
|
||||||
|
rm -rf "$jobdir"
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "Asking Jenkins to reload config"
|
||||||
|
curl --silent -X POST http://localhost:${toString jenkinsCfg.port}/reload
|
||||||
|
'';
|
||||||
|
serviceConfig = {
|
||||||
|
User = jenkinsCfg.user;
|
||||||
|
RuntimeDirectory = "jenkins-job-builder";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
Loading…
Reference in a new issue