Unverified Commit 231c1145 authored by Martin Weinelt's avatar Martin Weinelt
Browse files

Merge remote-tracking branch 'origin/master' into staging-next

Conflicts:
- pkgs/development/python-modules/rflink/default.nix
parents c089dfed 968de5d5
Loading
Loading
Loading
Loading
+77 −0
Original line number Diff line number Diff line
@@ -15,6 +15,9 @@ let
    last
    genList
    elemAt
    all
    concatMap
    foldl'
    ;

  inherit (lib.strings)
@@ -190,6 +193,80 @@ in /* No rec! Add dependencies on this file at the top. */ {
    subpathInvalidReason value == null;


  /* Join subpath strings together using `/`, returning a normalised subpath string.

    Like `concatStringsSep "/"` but safer, specifically:

    - All elements must be valid subpath strings, see `lib.path.subpath.isValid`

    - The result gets normalised, see `lib.path.subpath.normalise`

    - The edge case of an empty list gets properly handled by returning the neutral subpath `"./."`

    Laws:

    - Associativity:

          subpath.join [ x (subpath.join [ y z ]) ] == subpath.join [ (subpath.join [ x y ]) z ]

    - Identity - `"./."` is the neutral element for normalised paths:

          subpath.join [ ] == "./."
          subpath.join [ (subpath.normalise p) "./." ] == subpath.normalise p
          subpath.join [ "./." (subpath.normalise p) ] == subpath.normalise p

    - Normalisation - the result is normalised according to `lib.path.subpath.normalise`:

          subpath.join ps == subpath.normalise (subpath.join ps)

    - For non-empty lists, the implementation is equivalent to normalising the result of `concatStringsSep "/"`.
      Note that the above laws can be derived from this one.

          ps != [] -> subpath.join ps == subpath.normalise (concatStringsSep "/" ps)

    Type:
      subpath.join :: [ String ] -> String

    Example:
      subpath.join [ "foo" "bar/baz" ]
      => "./foo/bar/baz"

      # normalise the result
      subpath.join [ "./foo" "." "bar//./baz/" ]
      => "./foo/bar/baz"

      # passing an empty list results in the current directory
      subpath.join [ ]
      => "./."

      # elements must be valid subpath strings
      subpath.join [ /foo ]
      => <error>
      subpath.join [ "" ]
      => <error>
      subpath.join [ "/foo" ]
      => <error>
      subpath.join [ "../foo" ]
      => <error>
  */
  subpath.join =
    # The list of subpaths to join together
    subpaths:
    # Fast in case all paths are valid
    if all isValid subpaths
    then joinRelPath (concatMap splitRelPath subpaths)
    else
      # Otherwise we take our time to gather more info for a better error message
      # Strictly go through each path, throwing on the first invalid one
      # Tracks the list index in the fold accumulator
      foldl' (i: path:
        if isValid path
        then i + 1
        else throw ''
          lib.path.subpath.join: Element at index ${toString i} is not a valid subpath string:
              ${subpathInvalidReason path}''
      ) 0 subpaths;

  /* Normalise a subpath. Throw an error if the subpath isn't valid, see
  `lib.path.subpath.isValid`

+30 −0
Original line number Diff line number Diff line
@@ -107,6 +107,36 @@ let
      expected = true;
    };

    # Test examples from the lib.path.subpath.join documentation
    testSubpathJoinExample1 = {
      expr = subpath.join [ "foo" "bar/baz" ];
      expected = "./foo/bar/baz";
    };
    testSubpathJoinExample2 = {
      expr = subpath.join [ "./foo" "." "bar//./baz/" ];
      expected = "./foo/bar/baz";
    };
    testSubpathJoinExample3 = {
      expr = subpath.join [ ];
      expected = "./.";
    };
    testSubpathJoinExample4 = {
      expr = (builtins.tryEval (subpath.join [ /foo ])).success;
      expected = false;
    };
    testSubpathJoinExample5 = {
      expr = (builtins.tryEval (subpath.join [ "" ])).success;
      expected = false;
    };
    testSubpathJoinExample6 = {
      expr = (builtins.tryEval (subpath.join [ "/foo" ])).success;
      expected = false;
    };
    testSubpathJoinExample7 = {
      expr = (builtins.tryEval (subpath.join [ "../foo" ])).success;
      expected = false;
    };

    # Test examples from the lib.path.subpath.normalise documentation
    testSubpathNormaliseExample1 = {
      expr = subpath.normalise "foo//bar";
+4 −0
Original line number Diff line number Diff line
@@ -71,6 +71,10 @@ In addition to numerous new and upgraded packages, this release has the followin

- [nimdow](https://github.com/avahe-kellenberger/nimdow), a window manager written in Nim, inspired by dwm.

- [woodpecker-agent](https://woodpecker-ci.org/), a simple CI engine with great extensibility. Available as [services.woodpecker-agent](#opt-services.woodpecker-agent.enable).

- [woodpecker-server](https://woodpecker-ci.org/), a simple CI engine with great extensibility. Available as [services.woodpecker-server](#opt-services.woodpecker-server.enable).

## Backward Incompatibilities {#sec-release-23.05-incompatibilities}

<!-- To avoid merge conflicts, consider adding your item at an arbitrary place in the list instead. -->
+2 −0
Original line number Diff line number Diff line
@@ -377,6 +377,8 @@
  ./services/continuous-integration/jenkins/default.nix
  ./services/continuous-integration/jenkins/job-builder.nix
  ./services/continuous-integration/jenkins/slave.nix
  ./services/continuous-integration/woodpecker/agent.nix
  ./services/continuous-integration/woodpecker/server.nix
  ./services/databases/aerospike.nix
  ./services/databases/cassandra.nix
  ./services/databases/clickhouse.nix
+99 −0
Original line number Diff line number Diff line
{ config
, lib
, pkgs
, ...
}:

let
  cfg = config.services.woodpecker-agent;
in
{
  meta.maintainers = [ lib.maintainers.janik ];

  options = {
    services.woodpecker-agent = {
      enable = lib.mkEnableOption (lib.mdDoc "the Woodpecker-Agent, Agents execute tasks generated by a Server, every install will need one server and at least one agent");
      package = lib.mkPackageOptionMD pkgs "woodpecker-agent" { };

      environment = lib.mkOption {
        default = { };
        type = lib.types.attrsOf lib.types.str;
        example = lib.literalExpression ''
          {
            WOODPECKER_SERVER = "localhost:9000";
            WOODPECKER_BACKEND = "docker";
            DOCKER_HOST = "unix:///run/podman/podman.sock";
          }
        '';
        description = lib.mdDoc "woodpecker-agent config envrionment variables, for other options read the [documentation](https://woodpecker-ci.org/docs/administration/agent-config)";
      };

      extraGroups = lib.mkOption {
        default = null;
        type = lib.types.nullOr (lib.types.listOf lib.types.str);
        example = [ "podman" ];
        description = lib.mdDoc ''
          Additional groups for the systemd service.
        '';
      };

      environmentFile = lib.mkOption {
        type = lib.types.nullOr lib.types.path;
        default = null;
        example = "/root/woodpecker-agent.env";
        description = lib.mdDoc ''
          File to load environment variables
          from. This is helpful for specifying secrets.
          Example content of environmentFile:
          ```
          WOODPECKER_AGENT_SECRET=your-shared-secret-goes-here
          ```
        '';
      };
    };
  };

  config = lib.mkIf cfg.enable {
    systemd.services = {
      woodpecker-agent = {
        description = "Woodpecker-Agent Service";
        wantedBy = [ "multi-user.target" ];
        after = [ "network-online.target" ];
        wants = [ "network-online.target" ];
        serviceConfig = {
          DynamicUser = true;
          SupplementaryGroups = lib.optionals (cfg.extraGroups != null) cfg.extraGroups;
          EnvironmentFile = lib.optional (cfg.environmentFile != null) cfg.environmentFile;
          ExecStart = "${cfg.package}/bin/woodpecker-agent";
          Restart = "on-failure";
          RestartSec = 15;
          CapabilityBoundingSet = "";
          # Security
          NoNewPrivileges = true;
          # Sandboxing
          ProtectSystem = "strict";
          PrivateTmp = true;
          PrivateDevices = true;
          PrivateUsers = true;
          ProtectHostname = true;
          ProtectClock = true;
          ProtectKernelTunables = true;
          ProtectKernelModules = true;
          ProtectKernelLogs = true;
          ProtectControlGroups = true;
          RestrictAddressFamilies = [ "AF_UNIX AF_INET AF_INET6" ];
          LockPersonality = true;
          MemoryDenyWriteExecute = true;
          RestrictRealtime = true;
          RestrictSUIDSGID = true;
          PrivateMounts = true;
          # System Call Filtering
          SystemCallArchitectures = "native";
          SystemCallFilter = "~@clock @privileged @cpu-emulation @debug @keyring @module @mount @obsolete @raw-io @reboot @setuid @swap";
        };
        inherit (cfg) environment;
      };
    };
  };
}
Loading