nixpkgs/nixos/modules/services/web-apps/gerrit.nix
pennae fc614c37c6 nixos/documentation: split options doc build
most modules can be evaluated for their documentation in a very
restricted environment that doesn't include all of nixpkgs. this
evaluation can then be cached and reused for subsequent builds, merging
only documentation that has changed into the cached set. since nixos
ships with a large number of modules of which only a few are used in any
given config this can save evaluation a huge percentage of nixos
options available in any given config.

in tests of this caching, despite having to copy most of nixos/, saves
about 80% of the time needed to build the system manual, or about two
second on the machine used for testing. build time for a full system
config shrank from 9.4s to 7.4s, while turning documentation off
entirely shortened the build to 7.1s.
2022-01-02 19:46:13 +01:00

243 lines
6.6 KiB
Nix

{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.services.gerrit;
# NixOS option type for git-like configs
gitIniType = with types;
let
primitiveType = either str (either bool int);
multipleType = either primitiveType (listOf primitiveType);
sectionType = lazyAttrsOf multipleType;
supersectionType = lazyAttrsOf (either multipleType sectionType);
in lazyAttrsOf supersectionType;
gerritConfig = pkgs.writeText "gerrit.conf" (
lib.generators.toGitINI cfg.settings
);
replicationConfig = pkgs.writeText "replication.conf" (
lib.generators.toGitINI cfg.replicationSettings
);
# Wrap the gerrit java with all the java options so it can be called
# like a normal CLI app
gerrit-cli = pkgs.writeShellScriptBin "gerrit" ''
set -euo pipefail
jvmOpts=(
${lib.escapeShellArgs cfg.jvmOpts}
-Xmx${cfg.jvmHeapLimit}
)
exec ${cfg.jvmPackage}/bin/java \
"''${jvmOpts[@]}" \
-jar ${cfg.package}/webapps/${cfg.package.name}.war \
"$@"
'';
gerrit-plugins = pkgs.runCommand
"gerrit-plugins"
{
buildInputs = [ gerrit-cli ];
}
''
shopt -s nullglob
mkdir $out
for name in ${toString cfg.builtinPlugins}; do
echo "Installing builtin plugin $name.jar"
gerrit cat plugins/$name.jar > $out/$name.jar
done
for file in ${toString cfg.plugins}; do
name=$(echo "$file" | cut -d - -f 2-)
echo "Installing plugin $name"
ln -sf "$file" $out/$name
done
'';
in
{
options = {
services.gerrit = {
enable = mkEnableOption "Gerrit service";
package = mkOption {
type = types.package;
default = pkgs.gerrit;
defaultText = literalExpression "pkgs.gerrit";
description = "Gerrit package to use";
};
jvmPackage = mkOption {
type = types.package;
default = pkgs.jre_headless;
defaultText = literalExpression "pkgs.jre_headless";
description = "Java Runtime Environment package to use";
};
jvmOpts = mkOption {
type = types.listOf types.str;
default = [
"-Dflogger.backend_factory=com.google.common.flogger.backend.log4j.Log4jBackendFactory#getInstance"
"-Dflogger.logging_context=com.google.gerrit.server.logging.LoggingContext#getInstance"
];
description = "A list of JVM options to start gerrit with.";
};
jvmHeapLimit = mkOption {
type = types.str;
default = "1024m";
description = ''
How much memory to allocate to the JVM heap
'';
};
listenAddress = mkOption {
type = types.str;
default = "[::]:8080";
description = ''
<literal>hostname:port</literal> to listen for HTTP traffic.
This is bound using the systemd socket activation.
'';
};
settings = mkOption {
type = gitIniType;
default = {};
description = ''
Gerrit configuration. This will be generated to the
<literal>etc/gerrit.config</literal> file.
'';
};
replicationSettings = mkOption {
type = gitIniType;
default = {};
description = ''
Replication configuration. This will be generated to the
<literal>etc/replication.config</literal> file.
'';
};
plugins = mkOption {
type = types.listOf types.package;
default = [];
description = ''
List of plugins to add to Gerrit. Each derivation is a jar file
itself where the name of the derivation is the name of plugin.
'';
};
builtinPlugins = mkOption {
type = types.listOf (types.enum cfg.package.passthru.plugins);
default = [];
description = ''
List of builtins plugins to install. Those are shipped in the
<literal>gerrit.war</literal> file.
'';
};
serverId = mkOption {
type = types.str;
description = ''
Set a UUID that uniquely identifies the server.
This can be generated with
<literal>nix-shell -p util-linux --run uuidgen</literal>.
'';
};
};
};
config = mkIf cfg.enable {
assertions = [
{
assertion = cfg.replicationSettings != {} -> elem "replication" cfg.builtinPlugins;
message = "Gerrit replicationSettings require enabling the replication plugin";
}
];
services.gerrit.settings = {
cache.directory = "/var/cache/gerrit";
container.heapLimit = cfg.jvmHeapLimit;
gerrit.basePath = lib.mkDefault "git";
gerrit.serverId = cfg.serverId;
httpd.inheritChannel = "true";
httpd.listenUrl = lib.mkDefault "http://${cfg.listenAddress}";
index.type = lib.mkDefault "lucene";
};
# Add the gerrit CLI to the system to run `gerrit init` and friends.
environment.systemPackages = [ gerrit-cli ];
systemd.sockets.gerrit = {
unitConfig.Description = "Gerrit HTTP socket";
wantedBy = [ "sockets.target" ];
listenStreams = [ cfg.listenAddress ];
};
systemd.services.gerrit = {
description = "Gerrit";
wantedBy = [ "multi-user.target" ];
requires = [ "gerrit.socket" ];
after = [ "gerrit.socket" "network.target" ];
path = [
gerrit-cli
pkgs.bash
pkgs.coreutils
pkgs.git
pkgs.openssh
];
environment = {
GERRIT_HOME = "%S/gerrit";
GERRIT_TMP = "%T";
HOME = "%S/gerrit";
XDG_CONFIG_HOME = "%S/gerrit/.config";
};
preStart = ''
set -euo pipefail
# bootstrap if nothing exists
if [[ ! -d git ]]; then
gerrit init --batch --no-auto-start
fi
# install gerrit.war for the plugin manager
rm -rf bin
mkdir bin
ln -sfv ${cfg.package}/webapps/${cfg.package.name}.war bin/gerrit.war
# copy the config, keep it mutable because Gerrit
ln -sfv ${gerritConfig} etc/gerrit.config
ln -sfv ${replicationConfig} etc/replication.config
# install the plugins
rm -rf plugins
ln -sv ${gerrit-plugins} plugins
''
;
serviceConfig = {
CacheDirectory = "gerrit";
DynamicUser = true;
ExecStart = "${gerrit-cli}/bin/gerrit daemon --console-log";
LimitNOFILE = 4096;
StandardInput = "socket";
StandardOutput = "journal";
StateDirectory = "gerrit";
WorkingDirectory = "%S/gerrit";
};
};
};
meta.maintainers = with lib.maintainers; [ edef zimbatm ];
# uses attributes of the linked package
meta.buildDocsInSandbox = false;
}