Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add services.hercules-ci-agent #586

Merged
merged 4 commits into from Jan 3, 2023
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
13 changes: 13 additions & 0 deletions README.md
Expand Up @@ -227,6 +227,19 @@ information on the `-I` flag look at the nix-build [manpage](https://nixos.org/m
darwin-rebuild switch -I darwin=.
```

If you're adding a module, please add yourself to `meta.maintainers`, for example

```nix
meta.maintainers = [
lib.maintainers.alice or "alice"
];

options.services.alicebot = # ...
```

The `or` operator takes care of graceful degradation when `lib` from Nixpkgs
goes out of sync.

Also feel free to contact me if you have questions,
- Matrix - @daiderd:matrix.org, you can find me in [#macos:nixos.org](https://matrix.to/#/#macos:nixos.org)
- @lnl7 on twitter
54 changes: 54 additions & 0 deletions modules/meta.nix
@@ -0,0 +1,54 @@
# This module was derived from
# https://github.com/NixOS/nixpkgs/blob/000387627d26f245a6d9a0a7a60b7feddecaeec0/nixos/modules/misc/meta.nix
{ lib, ... }:

with lib;

let
maintainer = mkOptionType {
name = "maintainer";
check = email: elem email (attrValues lib.maintainers);
merge = loc: defs: listToAttrs (singleton (nameValuePair (last defs).file (last defs).value));
};

listOfMaintainers = types.listOf maintainer // {
# Returns list of
# { "module-file" = [
# "maintainer1 <first@nixos.org>"
# "maintainer2 <second@nixos.org>" ];
# }
merge = loc: defs:
zipAttrs
(flatten (imap1 (n: def: imap1 (m: def':
maintainer.merge (loc ++ ["[${toString n}-${toString m}]"])
[{ inherit (def) file; value = def'; }]) def.value) defs));
};

in

{
options = {
meta = {

maintainers = mkOption {
type = listOfMaintainers;
internal = true;
default = [];
example = [ lib.maintainers.all ];
description = ''
List of maintainers of each module. This option should be defined at
most once per module.

NOTE: <literal>lib</literal> comes from Nixpkgs, which can go out of
sync with nix-darwin. For this reason, use definitions like
<literal>maintainers.alice or "alice"</literal>.
'';
};

};
};

meta.maintainers = [
maintainers.roberth or "roberth"
];
}
2 changes: 2 additions & 0 deletions modules/module-list.nix
@@ -1,6 +1,7 @@
[
./alias.nix
./documentation
./meta.nix
./misc/ids.nix
./misc/lib.nix
./security/pam.nix
Expand Down Expand Up @@ -49,6 +50,7 @@
./services/dnsmasq.nix
./services/emacs.nix
./services/gitlab-runner.nix
./services/hercules-ci-agent
./services/karabiner-elements
./services/khd
./services/kwm
Expand Down
99 changes: 99 additions & 0 deletions modules/services/hercules-ci-agent/common.nix
@@ -0,0 +1,99 @@
/*

This file is for options that NixOS and nix-darwin have in common.

Platform-specific code is in the respective default.nix files.

*/

{ config, lib, options, pkgs, ... }:
let
inherit (lib)
filterAttrs
literalExpression
mkIf
mkOption
mkRemovedOptionModule
mkRenamedOptionModule
types
;
literalMD = lib.literalMD or (x: lib.literalDocBook "Documentation not rendered. Please upgrade to a newer NixOS with markdown support.");
mdDoc = lib.mdDoc or (x: "Documentation not rendered. Please upgrade to a newer NixOS with markdown support.");

cfg = config.services.hercules-ci-agent;

inherit (import ./settings.nix { inherit pkgs lib; }) format settingsModule;

in
{
imports = [
(mkRenamedOptionModule [ "services" "hercules-ci-agent" "extraOptions" ] [ "services" "hercules-ci-agent" "settings" ])
(mkRenamedOptionModule [ "services" "hercules-ci-agent" "baseDirectory" ] [ "services" "hercules-ci-agent" "settings" "baseDirectory" ])
(mkRenamedOptionModule [ "services" "hercules-ci-agent" "concurrentTasks" ] [ "services" "hercules-ci-agent" "settings" "concurrentTasks" ])
(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.")
];

options.services.hercules-ci-agent = {
enable = mkOption {
type = types.bool;
default = false;
description = mdDoc ''
Enable to run Hercules CI Agent as a system service.

[Hercules CI](https://hercules-ci.com) is a
continuous integation service that is centered around Nix.

Support is available at [help@hercules-ci.com](mailto:help@hercules-ci.com).
'';
};
package = mkOption {
description = mdDoc ''
Package containing the bin/hercules-ci-agent executable.
'';
type = types.package;
default = pkgs.hercules-ci-agent;
defaultText = literalExpression "pkgs.hercules-ci-agent";
};
settings = mkOption {
description = mdDoc ''
These settings are written to the `agent.toml` file.

Not all settings are listed as options, can be set nonetheless.

For the exhaustive list of settings, see <https://docs.hercules-ci.com/hercules-ci/reference/agent-config/>.
'';
type = types.submoduleWith { modules = [ settingsModule ]; };
};

/*
Internal and/or computed values.

These are written as options instead of let binding to allow sharing with
default.nix on both NixOS and nix-darwin.
*/
tomlFile = mkOption {
type = types.path;
internal = true;
defaultText = literalMD "generated `hercules-ci-agent.toml`";
description = mdDoc ''
The fully assembled config file.
'';
};
};

config = mkIf cfg.enable {
nix.extraOptions = ''
# A store path that was missing at first may well have finished building,
# even shortly after the previous lookup. This *also* applies to the daemon.
narinfo-cache-negative-ttl = 0
'';
services.hercules-ci-agent = {
tomlFile =
format.generate "hercules-ci-agent.toml" cfg.settings;
settings.config._module.args = {
packageOption = options.services.hercules-ci-agent.package;
inherit pkgs;
};
};
};
}
81 changes: 81 additions & 0 deletions modules/services/hercules-ci-agent/default.nix
@@ -0,0 +1,81 @@
{ config, lib, pkgs, ... }:

with lib;
let
cfg = config.services.hercules-ci-agent;
user = config.users.users._hercules-ci-agent;
in
{
imports = [ ./common.nix ];

meta.maintainers = [
lib.maintainers.roberth or "roberth"
];

options.services.hercules-ci-agent = {

logFile = mkOption {
type = types.path;
default = "/var/log/hercules-ci-agent.log";
description = "Stdout and sterr of hercules-ci-agent process.";
};
};

config = mkIf cfg.enable {
launchd.daemons.hercules-ci-agent = {
script = "exec ${cfg.package}/bin/hercules-ci-agent --config ${cfg.tomlFile}";

path = [ config.nix.package ];
environment = {
NIX_SSL_CERT_FILE = "${pkgs.cacert}/etc/ssl/certs/ca-bundle.crt";
};

serviceConfig.KeepAlive = true;
serviceConfig.RunAtLoad = true;
serviceConfig.StandardErrorPath = cfg.logFile;
serviceConfig.StandardOutPath = cfg.logFile;
serviceConfig.GroupName = "_hercules-ci-agent";
serviceConfig.UserName = "_hercules-ci-agent";
serviceConfig.WorkingDirectory = user.home;
serviceConfig.WatchPaths = [
cfg.settings.staticSecretsDirectory
];
};

system.activationScripts.preActivation.text = ''
touch '${cfg.logFile}'
chown ${toString user.uid}:${toString user.gid} '${cfg.logFile}'
'';

# Trusted user allows simplified configuration and better performance
# when operating in a cluster.
nix.settings.trusted-users = [ "_hercules-ci-agent" ];
services.hercules-ci-agent.settings.nixUserIsTrusted = true;

users.knownGroups = [ "hercules-ci-agent" "_hercules-ci-agent" ];
users.knownUsers = [ "hercules-ci-agent" "_hercules-ci-agent" ];

users.users._hercules-ci-agent = {
uid = mkDefault 399;
gid = mkDefault config.users.groups._hercules-ci-agent.gid;
home = mkDefault cfg.settings.baseDirectory;
name = "_hercules-ci-agent";
createHome = true;
shell = "/bin/bash";
description = "System user for the Hercules CI Agent";
};
users.groups._hercules-ci-agent = {
gid = mkDefault 32001;
name = "_hercules-ci-agent";
description = "System group for the Hercules CI Agent";
};

services.hercules-ci-agent.settings.labels = {
darwin.label = config.system.darwinLabel;
darwin.revision = config.system.darwinRevision;
darwin.version = config.system.darwinVersion;
darwin.nix.daemon = config.nix.useDaemon;
darwin.nix.sandbox = config.nix.settings.sandbox;
};
};
}