aboutsummaryrefslogtreecommitdiff
path: root/modules/pkgs/jenkinsWithPlugins/default.nix
blob: ebc12db8b2fbc24a5c2fafefaa66f224fcf24dcb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
{ pkgs, lib, stdenv, fetchurl }:

/*

  `pluginsFunc` is a function that should return an attribute set of plugins
  to be included in the WAR.

  The plugins are provided by `pkgs.jenkinsUpdateCenter.plugins`.
  Dependencies between those plugins are automatically resolved within the
  same jenkinsUpdateCenter.

  Example:

    pkgs.jenkinsWithPlugins
      (plugins: {
        inherit (plugins) BlameSubversion ... ;
        inherit (pkgs) my-plugin;
      })

  Each attribute of `plugins` is a derivation and you can return in
  the set any other plugins that are not available in Jenkins registry
  (https://updates.jenkins-ci.org/) or replacing plugins in the registry.

  Non-optional dependencies, if any, are automatically added. Optional
  dependencies are ignored, you have to add them explicitly.

*/

pluginsFunc:

let

  inherit (builtins)
    attrNames fromJSON readFile ;

  inherit (lib)
    concatStrings filter filterAttrs flatten genAttrs mapAttrs
    mapAttrsToList unique ;

  fromBase64 = import ./fromBase64.nix;

  updateCenter =
    let
      registry = fromJSON (readFile pkgs.jenkinsUpdateCenter);
    in
      registry // {
        core = with registry.core; fetchurl {
          inherit url;
          name = "jenkins-core-${version}.war";
          sha1 = fromBase64 sha1;
          meta = registry.core;
        };

        plugins = mapAttrs (
          _: plugin: fetchurl {
            inherit (plugin) url;
            sha1 = fromBase64 plugin.sha1;
            name = "jenkins-plugin-${plugin.name}-${plugin.version}.hpi";
            meta = plugin;
          }
        ) registry.plugins;
      };

  inherit (updateCenter) core;

  neededPlugins =
    let
      rootPlugins = pluginsFunc updateCenter.plugins;
      hasDeps = _: p: (p ? meta) && (p.meta ? dependencies);
      directDeps = nn:
        let
          isRequired = d: ! (d ? optional && d.optional);
          deps = p: map (d: d.name) (filter isRequired p.meta.dependencies);
        in flatten (map (n: deps updateCenter.plugins.${n}) nn);

      getDepsRecursive = nn: if nn == [] then [] else nn ++ getDepsRecursive (directDeps nn);
      depNames = unique (getDepsRecursive (attrNames (filterAttrs hasDeps rootPlugins)));
      deps = genAttrs depNames (n: updateCenter.plugins.${n});
    in deps // rootPlugins;

  pluginsPack = stdenv.mkDerivation {
    name = "jenkins-plugins-pack";
    phases = [ "installPhase" ];
    installPhase = ''
      mkdir -p $out
      ${concatStrings (
        mapAttrsToList (n: p: ''
          ln -svf '${p}' "$out/${n}.hpi"
        '') neededPlugins)}
    '';
  };

  pack =  stdenv.mkDerivation rec {
    name = "jenkins-${core.meta.version}+plugins.war";

    # https://wiki.jenkins-ci.org/display/JENKINS/Bundling+plugins+with+Jenkins
    build-xml = pkgs.writeXML "jenkins.build.xml"
      ''
      <?xml version="1.0" encoding="UTF-8"?>
      <project basedir="." name="Jenkins-Bundle">
        <target name="bundle" description="Merge plugins into jenkins.war">
          <zip destfile="jenkins.war" level="9">
            <zipfileset src="${core}" />
            <zipfileset dir="${pluginsPack}" prefix="WEB-INF/plugins" />
          </zip>
        </target>
      </project>
      '';

    meta = with stdenv.lib; {
      description = "An extendable open source continuous integration server";
      homepage = http://jenkins-ci.org;
      license = licenses.mit;
      platforms = platforms.all;
    };

    buildInputs = with pkgs; [ ant jdk ];

    phases = [ "buildPhase" "installPhase" ];
    buildPhase = ''
      ln -sf ${build-xml} build.xml
      ant bundle
    '';
    installPhase = "cp jenkins.war $out";
  };

in if neededPlugins == [] then core else pack