213 lines
6.3 KiB
Nix
213 lines
6.3 KiB
Nix
{
|
|
lib,
|
|
config,
|
|
pkgs,
|
|
...
|
|
}: let
|
|
cfg = config.services.my-hydra;
|
|
toSpec = {
|
|
name,
|
|
owner,
|
|
...
|
|
}: let
|
|
spec = {
|
|
enabled = 1;
|
|
hidden = false;
|
|
description = "Declarative specification jobset automatically generated";
|
|
checkinterval = 120;
|
|
schedulingshares = 10000;
|
|
enableemail = false;
|
|
emailoverride = "";
|
|
keepnr = 1;
|
|
nixexprinput = "src";
|
|
nixexprpath = "jobsets.nix";
|
|
inputs = {
|
|
src = {
|
|
type = "path";
|
|
value = pkgs.writeTextFile {
|
|
name = "src";
|
|
text = builtins.readFile ./jobsets.nix;
|
|
destination = "/jobsets.nix";
|
|
};
|
|
emailresponsible = false;
|
|
};
|
|
repoInfoPath = {
|
|
type = "path";
|
|
value = pkgs.writeTextFile {
|
|
name = "repo";
|
|
text = builtins.toJSON {
|
|
inherit name owner;
|
|
};
|
|
};
|
|
emailresponsible = false;
|
|
};
|
|
prs = {
|
|
type = "githubpulls";
|
|
value = "${owner} ${name}";
|
|
emailresponsible = false;
|
|
};
|
|
};
|
|
};
|
|
drv = pkgs.writeTextFile {
|
|
name = "hydra-jobset-specification-${name}";
|
|
text = builtins.toJSON spec;
|
|
destination = "/spec.json";
|
|
};
|
|
in "${drv}";
|
|
in {
|
|
imports = [
|
|
./config.nix
|
|
../nginx-base
|
|
];
|
|
|
|
options.services.my-hydra = {
|
|
domain = lib.mkOption {
|
|
type = lib.types.str;
|
|
default = "hydra.aciceri.dev";
|
|
};
|
|
repos = lib.mkOption {
|
|
type = lib.types.attrsOf (lib.types.submodule ({
|
|
name,
|
|
config,
|
|
...
|
|
}: {
|
|
options = {
|
|
name = lib.mkOption {
|
|
type = lib.types.str;
|
|
default = name;
|
|
};
|
|
owner = lib.mkOption {
|
|
type = lib.types.str;
|
|
default = "aciceri";
|
|
};
|
|
description = lib.mkOption {
|
|
type = lib.types.str;
|
|
default = config.homepage;
|
|
};
|
|
homepage = lib.mkOption {
|
|
type = lib.types.str;
|
|
default = "https://github.com/${config.owner}/${config.name}";
|
|
};
|
|
reportStatus = lib.mkOption {
|
|
type = lib.types.bool;
|
|
default = true;
|
|
};
|
|
};
|
|
}));
|
|
default = {};
|
|
};
|
|
};
|
|
|
|
config = {
|
|
# TODO manage `hydra` user ssh key declaratively
|
|
nix.extraOptions = ''
|
|
allowed-uris = https://github.com/ git://git.savannah.gnu.org/ https://git.sr.ht
|
|
'';
|
|
|
|
services.hydra-dev = {
|
|
enable = true;
|
|
hydraURL = "https://${cfg.domain}";
|
|
notificationSender = "hydra@mothership.fleet";
|
|
useSubstitutes = true;
|
|
extraConfig =
|
|
''
|
|
<github_authorization>
|
|
include ${config.age.secrets.hydra-github-token.path}
|
|
</github_authorization>
|
|
''
|
|
+ (lib.concatMapStrings (repo:
|
|
lib.optionalString repo.reportStatus
|
|
''
|
|
<githubstatus>
|
|
jobs = ${repo.name}.*
|
|
excludeBuildFromContext = 1
|
|
useShortContext = 1
|
|
</githubstatus>
|
|
'') (builtins.attrValues cfg.repos));
|
|
};
|
|
|
|
systemd.services.hydra-setup = {
|
|
description = "Hydra CI setup";
|
|
serviceConfig.Type = "oneshot";
|
|
serviceConfig.RemainAfterExit = true;
|
|
wantedBy = ["multi-user.target"];
|
|
requires = ["hydra-init.service"];
|
|
after = ["hydra-init.service"];
|
|
environment = builtins.removeAttrs (config.systemd.services.hydra-init.environment) ["PATH"];
|
|
script =
|
|
''
|
|
PATH=$PATH:${lib.makeBinPath (with pkgs; [yq-go curl config.services.hydra.package])}
|
|
PASSWORD="$(cat ${config.age.secrets.hydra-admin-password.path})"
|
|
if [ ! -e ~hydra/.setup-is-complete ]; then
|
|
hydra-create-user admin \
|
|
--full-name "Andrea Ciceri" \
|
|
--email-address "andrea.ciceri@autistici.org" \
|
|
--password "$PASSWORD" \
|
|
--role admin
|
|
touch ~hydra/.setup-is-complete
|
|
fi
|
|
|
|
mkdir -p /var/lib/hydra/.ssh
|
|
cp /home/ccr/.ssh/id_rsa* /var/lib/hydra/.ssh/
|
|
chown -R hydra:hydra /var/lib/hydra/.ssh
|
|
|
|
mkdir -p /var/lib/hydra/queue-runner/.ssh
|
|
cp /home/ccr/.ssh/id_rsa* /var/lib/hydra/queue-runner/.ssh/
|
|
chown -R hydra-queue-runner:hydra /var/lib/hydra/queue-runner/.ssh
|
|
|
|
curl --head -X GET --retry 5 --retry-connrefused --retry-delay 1 http://localhost:3000
|
|
|
|
CURRENT_REPOS=$(curl -s -H "Accept: application/json" http://localhost:3000 | yq ".[].name")
|
|
DECLARED_REPOS="${lib.concatStringsSep " " (builtins.attrNames cfg.repos)}"
|
|
|
|
curl -H "Accept: application/json" \
|
|
-H 'Origin: http://localhost:3000' \
|
|
-H 'Content-Type: application/json' \
|
|
-d "{\"username\": \"admin\", \"password\": \"$PASSWORD\"}" \
|
|
--request "POST" localhost:3000/login \
|
|
--cookie-jar cookie
|
|
|
|
for repo in $CURRENT_REPOS; do
|
|
echo $repo
|
|
[[ ! "$DECLARED_REPOS" =~ (\ |^)$repo(\ |$) ]] && \
|
|
curl -H "Accept: application/json" \
|
|
--request "DELETE" \
|
|
--cookie cookie \
|
|
http://localhost:3000/project/$repo
|
|
done
|
|
''
|
|
+ lib.concatMapStrings (repo: ''
|
|
curl -H "Accept: application/json" \
|
|
-H 'Content-Type: application/json' \
|
|
--request "PUT" \
|
|
localhost:3000/project/${repo.name} \
|
|
--cookie cookie \
|
|
-d '{
|
|
"name": "${repo.name}",
|
|
"displayname": "${repo.name}",
|
|
"description": "${repo.description}",
|
|
"homepage": "${repo.homepage}",
|
|
"owner": "admin",
|
|
"enabled": true,
|
|
"visible": true,
|
|
"declarative": {
|
|
"file": "spec.json",
|
|
"type": "path",
|
|
"value": "${toSpec repo}"
|
|
}
|
|
}'
|
|
'') (builtins.attrValues cfg.repos)
|
|
+ ''
|
|
rm cookie
|
|
'';
|
|
};
|
|
|
|
services.nginx.virtualHosts."${cfg.domain}" = {
|
|
forceSSL = true;
|
|
enableACME = true;
|
|
locations."/" = {
|
|
proxyPass = "http://127.0.0.1:${builtins.toString config.services.hydra.port}";
|
|
};
|
|
};
|
|
};
|
|
}
|