Skip to content

Commit 3db1d87

Browse files
authored
Merge pull request LnL7#586 from hercules-ci/add-hercules-ci-agent
Add `services.hercules-ci-agent`
2 parents 267040e + 7ec26a9 commit 3db1d87

File tree

6 files changed

+404
-0
lines changed

6 files changed

+404
-0
lines changed

README.md

+13
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,19 @@ information on the `-I` flag look at the nix-build [manpage](https://nixos.org/m
225225
darwin-rebuild switch -I darwin=.
226226
```
227227

228+
If you're adding a module, please add yourself to `meta.maintainers`, for example
229+
230+
```nix
231+
meta.maintainers = [
232+
lib.maintainers.alice or "alice"
233+
];
234+
235+
options.services.alicebot = # ...
236+
```
237+
238+
The `or` operator takes care of graceful degradation when `lib` from Nixpkgs
239+
goes out of sync.
240+
228241
Also feel free to contact me if you have questions,
229242
- Matrix - @daiderd:matrix.org, you can find me in [#macos:nixos.org](https://matrix.to/#/#macos:nixos.org)
230243
- @lnl7 on twitter

modules/meta.nix

+54
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
# This module was derived from
2+
# https://github.com/NixOS/nixpkgs/blob/000387627d26f245a6d9a0a7a60b7feddecaeec0/nixos/modules/misc/meta.nix
3+
{ lib, ... }:
4+
5+
with lib;
6+
7+
let
8+
maintainer = mkOptionType {
9+
name = "maintainer";
10+
check = email: elem email (attrValues lib.maintainers);
11+
merge = loc: defs: listToAttrs (singleton (nameValuePair (last defs).file (last defs).value));
12+
};
13+
14+
listOfMaintainers = types.listOf maintainer // {
15+
# Returns list of
16+
# { "module-file" = [
17+
# "maintainer1 <[email protected]>"
18+
# "maintainer2 <[email protected]>" ];
19+
# }
20+
merge = loc: defs:
21+
zipAttrs
22+
(flatten (imap1 (n: def: imap1 (m: def':
23+
maintainer.merge (loc ++ ["[${toString n}-${toString m}]"])
24+
[{ inherit (def) file; value = def'; }]) def.value) defs));
25+
};
26+
27+
in
28+
29+
{
30+
options = {
31+
meta = {
32+
33+
maintainers = mkOption {
34+
type = listOfMaintainers;
35+
internal = true;
36+
default = [];
37+
example = [ lib.maintainers.all ];
38+
description = ''
39+
List of maintainers of each module. This option should be defined at
40+
most once per module.
41+
42+
NOTE: <literal>lib</literal> comes from Nixpkgs, which can go out of
43+
sync with nix-darwin. For this reason, use definitions like
44+
<literal>maintainers.alice or "alice"</literal>.
45+
'';
46+
};
47+
48+
};
49+
};
50+
51+
meta.maintainers = [
52+
maintainers.roberth or "roberth"
53+
];
54+
}

modules/module-list.nix

+2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
[
22
./alias.nix
33
./documentation
4+
./meta.nix
45
./misc/ids.nix
56
./misc/lib.nix
67
./security/pam.nix
@@ -49,6 +50,7 @@
4950
./services/dnsmasq.nix
5051
./services/emacs.nix
5152
./services/gitlab-runner.nix
53+
./services/hercules-ci-agent
5254
./services/karabiner-elements
5355
./services/khd
5456
./services/kwm
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
/*
2+
3+
This file is for options that NixOS and nix-darwin have in common.
4+
5+
Platform-specific code is in the respective default.nix files.
6+
7+
*/
8+
9+
{ config, lib, options, pkgs, ... }:
10+
let
11+
inherit (lib)
12+
filterAttrs
13+
literalExpression
14+
mkIf
15+
mkOption
16+
mkRemovedOptionModule
17+
mkRenamedOptionModule
18+
types
19+
;
20+
literalMD = lib.literalMD or (x: lib.literalDocBook "Documentation not rendered. Please upgrade to a newer NixOS with markdown support.");
21+
mdDoc = lib.mdDoc or (x: "Documentation not rendered. Please upgrade to a newer NixOS with markdown support.");
22+
23+
cfg = config.services.hercules-ci-agent;
24+
25+
inherit (import ./settings.nix { inherit pkgs lib; }) format settingsModule;
26+
27+
in
28+
{
29+
imports = [
30+
(mkRenamedOptionModule [ "services" "hercules-ci-agent" "extraOptions" ] [ "services" "hercules-ci-agent" "settings" ])
31+
(mkRenamedOptionModule [ "services" "hercules-ci-agent" "baseDirectory" ] [ "services" "hercules-ci-agent" "settings" "baseDirectory" ])
32+
(mkRenamedOptionModule [ "services" "hercules-ci-agent" "concurrentTasks" ] [ "services" "hercules-ci-agent" "settings" "concurrentTasks" ])
33+
(mkRemovedOptionModule [ "services" "hercules-ci-agent" "patchNix" ] "Nix versions packaged in this version of Nixpkgs don't need a patched nix-daemon to work correctly in Hercules CI Agent clusters.")
34+
];
35+
36+
options.services.hercules-ci-agent = {
37+
enable = mkOption {
38+
type = types.bool;
39+
default = false;
40+
description = mdDoc ''
41+
Enable to run Hercules CI Agent as a system service.
42+
43+
[Hercules CI](https://hercules-ci.com) is a
44+
continuous integation service that is centered around Nix.
45+
46+
Support is available at [[email protected]](mailto:[email protected]).
47+
'';
48+
};
49+
package = mkOption {
50+
description = mdDoc ''
51+
Package containing the bin/hercules-ci-agent executable.
52+
'';
53+
type = types.package;
54+
default = pkgs.hercules-ci-agent;
55+
defaultText = literalExpression "pkgs.hercules-ci-agent";
56+
};
57+
settings = mkOption {
58+
description = mdDoc ''
59+
These settings are written to the `agent.toml` file.
60+
61+
Not all settings are listed as options, can be set nonetheless.
62+
63+
For the exhaustive list of settings, see <https://docs.hercules-ci.com/hercules-ci/reference/agent-config/>.
64+
'';
65+
type = types.submoduleWith { modules = [ settingsModule ]; };
66+
};
67+
68+
/*
69+
Internal and/or computed values.
70+
71+
These are written as options instead of let binding to allow sharing with
72+
default.nix on both NixOS and nix-darwin.
73+
*/
74+
tomlFile = mkOption {
75+
type = types.path;
76+
internal = true;
77+
defaultText = literalMD "generated `hercules-ci-agent.toml`";
78+
description = mdDoc ''
79+
The fully assembled config file.
80+
'';
81+
};
82+
};
83+
84+
config = mkIf cfg.enable {
85+
nix.extraOptions = ''
86+
# A store path that was missing at first may well have finished building,
87+
# even shortly after the previous lookup. This *also* applies to the daemon.
88+
narinfo-cache-negative-ttl = 0
89+
'';
90+
services.hercules-ci-agent = {
91+
tomlFile =
92+
format.generate "hercules-ci-agent.toml" cfg.settings;
93+
settings.config._module.args = {
94+
packageOption = options.services.hercules-ci-agent.package;
95+
inherit pkgs;
96+
};
97+
};
98+
};
99+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
{ config, lib, pkgs, ... }:
2+
3+
with lib;
4+
let
5+
cfg = config.services.hercules-ci-agent;
6+
user = config.users.users._hercules-ci-agent;
7+
in
8+
{
9+
imports = [ ./common.nix ];
10+
11+
meta.maintainers = [
12+
lib.maintainers.roberth or "roberth"
13+
];
14+
15+
options.services.hercules-ci-agent = {
16+
17+
logFile = mkOption {
18+
type = types.path;
19+
default = "/var/log/hercules-ci-agent.log";
20+
description = "Stdout and sterr of hercules-ci-agent process.";
21+
};
22+
};
23+
24+
config = mkIf cfg.enable {
25+
launchd.daemons.hercules-ci-agent = {
26+
script = "exec ${cfg.package}/bin/hercules-ci-agent --config ${cfg.tomlFile}";
27+
28+
path = [ config.nix.package ];
29+
environment = {
30+
NIX_SSL_CERT_FILE = "${pkgs.cacert}/etc/ssl/certs/ca-bundle.crt";
31+
};
32+
33+
serviceConfig.KeepAlive = true;
34+
serviceConfig.RunAtLoad = true;
35+
serviceConfig.StandardErrorPath = cfg.logFile;
36+
serviceConfig.StandardOutPath = cfg.logFile;
37+
serviceConfig.GroupName = "_hercules-ci-agent";
38+
serviceConfig.UserName = "_hercules-ci-agent";
39+
serviceConfig.WorkingDirectory = user.home;
40+
serviceConfig.WatchPaths = [
41+
cfg.settings.staticSecretsDirectory
42+
];
43+
};
44+
45+
system.activationScripts.preActivation.text = ''
46+
touch '${cfg.logFile}'
47+
chown ${toString user.uid}:${toString user.gid} '${cfg.logFile}'
48+
'';
49+
50+
# Trusted user allows simplified configuration and better performance
51+
# when operating in a cluster.
52+
nix.settings.trusted-users = [ "_hercules-ci-agent" ];
53+
services.hercules-ci-agent.settings.nixUserIsTrusted = true;
54+
55+
users.knownGroups = [ "hercules-ci-agent" "_hercules-ci-agent" ];
56+
users.knownUsers = [ "hercules-ci-agent" "_hercules-ci-agent" ];
57+
58+
users.users._hercules-ci-agent = {
59+
uid = mkDefault 399;
60+
gid = mkDefault config.users.groups._hercules-ci-agent.gid;
61+
home = mkDefault cfg.settings.baseDirectory;
62+
name = "_hercules-ci-agent";
63+
createHome = true;
64+
shell = "/bin/bash";
65+
description = "System user for the Hercules CI Agent";
66+
};
67+
users.groups._hercules-ci-agent = {
68+
gid = mkDefault 32001;
69+
name = "_hercules-ci-agent";
70+
description = "System group for the Hercules CI Agent";
71+
};
72+
73+
services.hercules-ci-agent.settings.labels = {
74+
darwin.label = config.system.darwinLabel;
75+
darwin.revision = config.system.darwinRevision;
76+
darwin.version = config.system.darwinVersion;
77+
darwin.nix.daemon = config.nix.useDaemon;
78+
darwin.nix.sandbox = config.nix.settings.sandbox;
79+
};
80+
};
81+
}

0 commit comments

Comments
 (0)