diff options
author | github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> | 2024-06-12 06:01:24 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-06-12 06:01:24 +0000 |
commit | d4adfab6df6bdffe5608cd34708462bd4421bf67 (patch) | |
tree | 5a20402c230d1507e5a1f7dbaf356eef8da64de2 /nixos | |
parent | ad67554387c7816e13c8003e7d5820e0f47e8220 (diff) | |
parent | e145b7fb56806bd90267401d3b7bdc18189a792a (diff) |
Merge staging-next into staging
Diffstat (limited to 'nixos')
-rw-r--r-- | nixos/doc/manual/release-notes/rl-2411.section.md | 2 | ||||
-rw-r--r-- | nixos/modules/module-list.nix | 1 | ||||
-rw-r--r-- | nixos/modules/services/misc/renovate.nix | 153 | ||||
-rw-r--r-- | nixos/tests/all-tests.nix | 1 | ||||
-rw-r--r-- | nixos/tests/renovate.nix | 69 |
5 files changed, 226 insertions, 0 deletions
diff --git a/nixos/doc/manual/release-notes/rl-2411.section.md b/nixos/doc/manual/release-notes/rl-2411.section.md index cd080879a567f..499380a835bf8 100644 --- a/nixos/doc/manual/release-notes/rl-2411.section.md +++ b/nixos/doc/manual/release-notes/rl-2411.section.md @@ -14,6 +14,8 @@ - [Quickwit](https://quickwit.io), sub-second search & analytics engine on cloud storage. Available as [services.quickwit](options.html#opt-services.quickwit). +- [Renovate](https://github.com/renovatebot/renovate), a dependency updating tool for various git forges and language ecosystems. Available as [services.renovate](#opt-services.renovate.enable). + ## Backward Incompatibilities {#sec-release-24.11-incompatibilities} - `nginx` package no longer includes `gd` and `geoip` dependencies. For enabling it, override `nginx` package with the optionals `withImageFilter` and `withGeoIP`. diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix index 1bdb3aa414e29..61b95134637e5 100644 --- a/nixos/modules/module-list.nix +++ b/nixos/modules/module-list.nix @@ -794,6 +794,7 @@ ./services/misc/radarr.nix ./services/misc/readarr.nix ./services/misc/redmine.nix + ./services/misc/renovate.nix ./services/misc/ripple-data-api.nix ./services/misc/rippled.nix ./services/misc/rmfakecloud.nix diff --git a/nixos/modules/services/misc/renovate.nix b/nixos/modules/services/misc/renovate.nix new file mode 100644 index 0000000000000..25a719c91cbd8 --- /dev/null +++ b/nixos/modules/services/misc/renovate.nix @@ -0,0 +1,153 @@ +{ + config, + lib, + pkgs, + ... +}: +let + inherit (lib) + mkEnableOption + mkPackageOption + mkOption + types + mkIf + ; + json = pkgs.formats.json { }; + cfg = config.services.renovate; + generateValidatedConfig = + name: value: + pkgs.callPackage ( + { runCommand, jq }: + runCommand name + { + nativeBuildInputs = [ + jq + cfg.package + ]; + value = builtins.toJSON value; + passAsFile = [ "value" ]; + preferLocalBuild = true; + } + '' + jq . "$valuePath"> $out + renovate-config-validator $out + '' + ) { }; + generateConfig = if cfg.validateSettings then generateValidatedConfig else json.generate; +in +{ + meta.maintainers = with lib.maintainers; [ marie natsukium ]; + + options.services.renovate = { + enable = mkEnableOption "renovate"; + package = mkPackageOption pkgs "renovate" { }; + schedule = mkOption { + type = with types; nullOr str; + description = "How often to run renovate. See {manpage}`systemd.time(7)` for the format."; + example = "*:0/10"; + default = null; + }; + credentials = mkOption { + type = with types; attrsOf path; + description = '' + Allows configuring environment variable credentials for renovate, read from files. + This should always be used for passing confidential data to renovate. + ''; + example = { + RENOVATE_TOKEN = "/etc/renovate/token"; + }; + default = { }; + }; + runtimePackages = mkOption { + type = with types; listOf package; + description = "Packages available to renovate."; + default = [ ]; + }; + validateSettings = mkOption { + type = types.bool; + default = true; + description = "Weither to run renovate's config validator on the built configuration."; + }; + settings = mkOption { + type = json.type; + default = { }; + example = { + platform = "gitea"; + endpoint = "https://git.example.com"; + gitAuthor = "Renovate <renovate@example.com>"; + }; + description = '' + Renovate's global configuration. + If you want to pass secrets to renovate, please use {option}`services.renovate.credentials` for that. + ''; + }; + }; + + config = mkIf cfg.enable { + services.renovate.settings = { + cacheDir = "/var/cache/renovate"; + baseDir = "/var/lib/renovate"; + }; + + systemd.services.renovate = { + description = "Renovate dependency updater"; + documentation = [ "https://docs.renovatebot.com/" ]; + after = [ "network.target" ]; + startAt = lib.optional (cfg.schedule != null) cfg.schedule; + path = [ + config.systemd.package + pkgs.git + ] ++ cfg.runtimePackages; + + serviceConfig = { + Type = "oneshot"; + User = "renovate"; + Group = "renovate"; + DynamicUser = true; + LoadCredential = lib.mapAttrsToList (name: value: "SECRET-${name}:${value}") cfg.credentials; + RemainAfterExit = false; + Restart = "on-failure"; + CacheDirectory = "renovate"; + StateDirectory = "renovate"; + + # Hardening + CapabilityBoundingSet = [ "" ]; + DeviceAllow = [ "" ]; + LockPersonality = true; + PrivateDevices = true; + PrivateUsers = true; + ProcSubset = "pid"; + ProtectClock = true; + ProtectControlGroups = true; + ProtectHome = true; + ProtectHostname = true; + ProtectKernelLogs = true; + ProtectKernelModules = true; + ProtectKernelTunables = true; + ProtectProc = "invisible"; + RestrictAddressFamilies = [ + "AF_INET" + "AF_INET6" + ]; + RestrictNamespaces = true; + RestrictRealtime = true; + SystemCallArchitectures = "native"; + UMask = "0077"; + }; + + script = '' + ${lib.concatStringsSep "\n" ( + builtins.map (name: "export ${name}=$(systemd-creds cat 'SECRET-${name}')") ( + lib.attrNames cfg.credentials + ) + )} + exec ${lib.escapeShellArg (lib.getExe cfg.package)} + ''; + + environment = { + RENOVATE_CONFIG_FILE = generateConfig "renovate-config.json" cfg.settings; + HOME = "/var/lib/renovate"; + }; + }; + }; +} diff --git a/nixos/tests/all-tests.nix b/nixos/tests/all-tests.nix index 92238016af569..3052c1ddfe0da 100644 --- a/nixos/tests/all-tests.nix +++ b/nixos/tests/all-tests.nix @@ -803,6 +803,7 @@ in { redis = handleTest ./redis.nix {}; redlib = handleTest ./redlib.nix {}; redmine = handleTest ./redmine.nix {}; + renovate = handleTest ./renovate.nix {}; restartByActivationScript = handleTest ./restart-by-activation-script.nix {}; restic-rest-server = handleTest ./restic-rest-server.nix {}; restic = handleTest ./restic.nix {}; diff --git a/nixos/tests/renovate.nix b/nixos/tests/renovate.nix new file mode 100644 index 0000000000000..a30b5b3d60b9c --- /dev/null +++ b/nixos/tests/renovate.nix @@ -0,0 +1,69 @@ +import ./make-test-python.nix ( + { pkgs, ... }: + { + name = "renovate"; + meta.maintainers = with pkgs.lib.maintainers; [ marie natsukium ]; + + nodes.machine = + { config, ... }: + { + services.renovate = { + enable = true; + settings = { + platform = "gitea"; + endpoint = "http://localhost:3000"; + autodiscover = true; + gitAuthor = "Renovate <renovate@example.com>"; + }; + credentials = { + RENOVATE_TOKEN = "/etc/renovate-token"; + }; + }; + environment.systemPackages = [ + config.services.forgejo.package + pkgs.tea + pkgs.git + ]; + services.forgejo = { + enable = true; + settings.server.HTTP_PORT = 3000; + }; + }; + + testScript = '' + def gitea(command): + return machine.succeed(f"cd /var/lib/forgejo && sudo --user=forgejo GITEA_WORK_DIR=/var/lib/forgejo GITEA_CUSTOM=/var/lib/forgejo/custom gitea {command}") + + machine.wait_for_unit("forgejo.service") + machine.wait_for_open_port(3000) + + machine.systemctl("stop forgejo.service") + + gitea("admin user create --username meow --email meow@example.com --password meow") + + machine.systemctl("start forgejo.service") + machine.wait_for_unit("forgejo.service") + machine.wait_for_open_port(3000) + + accessToken = gitea("admin user generate-access-token --raw --username meow --scopes all | tr -d '\n'") + + machine.succeed(f"tea login add --name default --user meow --token '{accessToken}' --password meow --url http://localhost:3000") + machine.succeed("tea repo create --name kitty --init") + machine.succeed("git config --global user.name Meow") + machine.succeed("git config --global user.email meow@example.com") + machine.succeed(f"git clone http://meow:{accessToken}@localhost:3000/meow/kitty.git /tmp/kitty") + machine.succeed("echo '{ \"name\": \"meow\", \"version\": \"0.1.0\" }' > /tmp/kitty/package.json") + machine.succeed("git -C /tmp/kitty add /tmp/kitty/package.json") + machine.succeed("git -C /tmp/kitty commit -m 'add package.json'") + machine.succeed("git -C /tmp/kitty push origin") + + machine.succeed(f"echo '{accessToken}' > /etc/renovate-token") + machine.systemctl("start renovate.service") + + machine.succeed("tea pulls list --repo meow/kitty | grep 'Configure Renovate'") + machine.succeed("tea pulls merge --repo meow/kitty 1") + + machine.systemctl("start renovate.service") + ''; + } +) |