Unverified Commit 77f77a04 authored by Tristan Ross's avatar Tristan Ross Committed by GitHub
Browse files

mattermost: 9.11.11 -> 10.5.2; use formats.json; squash systemd-tmpfiles warning (#376838)

parents 9e9486ba 423caa2d
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@
- The Mattermost module ({option}`services.mattermost`) and packages (`mattermost` and `mmctl`) have been substantially updated:
  - {option}`services.mattermost.preferNixConfig` now defaults to true if you advance {option}`system.stateVersion` to 25.05. This means that if you have {option}`services.mattermost.mutableConfig` set, NixOS will override your settings to those that you define in the module. It is recommended to leave this at the default, even if you used a mutable config before, because it will ensure that your Mattermost data directories are correct. If you moved your data directories, you may want to review the module changes before upgrading.
  - Mattermost telemetry reporting is now disabled by default, though security update notifications are enabled. Look at {option}`services.mattermost.telemetry` for options to control this behavior.
  - `pkgs.mattermost` has been updated from 9.11 to 10.5 to track the latest extended support release, since 9.11 will become end-of-life during the lifetime of NixOS 25.05.
  - `pkgs.mattermostLatest` is now an option to track the latest (non-prerelease) Mattermost release. We test upgrade migrations from ESR releases (`pkgs.mattermost`) to `pkgs.mattermostLatest`.
  - The Mattermost frontend is now built from source and can be overridden.
    - Note that the Mattermost derivation containing both the webapp and server is now wrapped to allow them to be built independently, so overrides to both webapp and server look like `mattermost.overrideAttrs (prev: { webapp = prev.webapp.override { ... }; server = prev.server.override { ... }; })` now.
+57 −43
Original line number Diff line number Diff line
@@ -147,15 +147,15 @@ let
    else
      throw "Invalid database driver: ${cfg.database.driver}";

  mattermostPluginDerivations =
    with pkgs;
    map (
  mattermostPluginDerivations = map (
    plugin:
      stdenv.mkDerivation {
        name = "mattermost-plugin";
    pkgs.stdenvNoCC.mkDerivation {
      name = "${cfg.package.name}-plugin";
      installPhase = ''
        runHook preInstall
        mkdir -p $out/share
          cp ${plugin} $out/share/plugin.tar.gz
        ln -sf ${plugin} $out/share/plugin.tar.gz
        runHook postInstall
      '';
      dontUnpack = true;
      dontPatch = true;
@@ -166,15 +166,15 @@ let
  ) cfg.plugins;

  mattermostPlugins =
    with pkgs;
    if mattermostPluginDerivations == [ ] then
      null
    else
      stdenv.mkDerivation {
      pkgs.stdenvNoCC.mkDerivation {
        name = "${cfg.package.name}-plugins";
        nativeBuildInputs = [ autoPatchelfHook ] ++ mattermostPluginDerivations;
        nativeBuildInputs = [ pkgs.autoPatchelfHook ] ++ mattermostPluginDerivations;
        buildInputs = [ cfg.package ];
        installPhase = ''
          runHook preInstall
          mkdir -p $out
          plugins=(${
            escapeShellArgs (map (plugin: "${plugin}/share/plugin.tar.gz") mattermostPluginDerivations)
@@ -187,6 +187,7 @@ let
            GZIP_OPT=-9 tar -C "$hash" -cvzf "$out/$hash.tar.gz" .
            rm -rf "$hash"
          done
          runHook postInstall
        '';

        dontUnpack = true;
@@ -254,8 +255,8 @@ let
      }
  );

  mattermostConfJSON = pkgs.writeText "mattermost-config.json" (builtins.toJSON mattermostConf);

  format = pkgs.formats.json { };
  finalConfig = format.generate "mattermost-config.json" mattermostConf;
in
{
  imports = [
@@ -454,9 +455,9 @@ in
          the options specified in services.mattermost will be generated
          but won't be overwritten on changes or rebuilds.

          If this option is disabled, changes in the system console won't
          be possible (default). If an config.json is present, it will be
          overwritten!
          If this option is disabled, persistent changes in the system
          console won't be possible (the default). If a config.json is
          present, it will be overwritten at service start!
        '';
      };

@@ -480,7 +481,20 @@ in
        description = ''
          Plugins to add to the configuration. Overrides any installed if non-null.
          This is a list of paths to .tar.gz files or derivations evaluating to
          .tar.gz files.
          .tar.gz files. You can use `mattermost.buildPlugin` to build plugins;
          see the NixOS documentation for more details.
        '';
      };

      pluginsBundle = mkOption {
        type = with types; nullOr package;
        default = mattermostPlugins;
        defaultText = ''
          All entries in {config}`services.mattermost.plugins`, repacked
        '';
        description = ''
          Derivation building to a directory of plugin tarballs.
          This overrides {option}`services.mattermost.plugins` if provided.
        '';
      };

@@ -508,7 +522,8 @@ in
        type = with types; attrsOf (either int str);
        default = { };
        description = ''
          Extra environment variables to export to the Mattermost process, in the systemd unit.
          Extra environment variables to export to the Mattermost process
          from the systemd unit configuration.
        '';
        example = {
          MM_SERVICESETTINGS_SITEURL = "http://example.com";
@@ -524,11 +539,11 @@ in
          for mattermost (see [the Mattermost documentation](https://docs.mattermost.com/configure/configuration-settings.html#environment-variables)).

          Settings defined in the environment file will overwrite settings
          set via nix or via the {option}`services.mattermost.extraConfig`
          set via Nix or via the {option}`services.mattermost.extraConfig`
          option.

          Useful for setting config options without their value ending up in the
          (world-readable) nix store, e.g. for a database password.
          (world-readable) Nix store, e.g. for a database password.
        '';
      };

@@ -639,13 +654,13 @@ in
            if cfg.database.driver == "postgres" then
              {
                sslmode = "disable";
                connect_timeout = 30;
                connect_timeout = 60;
              }
            else if cfg.database.driver == "mysql" then
              {
                charset = "utf8mb4,utf8";
                writeTimeout = "30s";
                readTimeout = "30s";
                writeTimeout = "60s";
                readTimeout = "60s";
              }
            else
              throw "Invalid database driver ${cfg.database.driver}";
@@ -653,13 +668,13 @@ in
            if config.mattermost.database.driver == "postgres" then
              {
                sslmode = "disable";
                connect_timeout = 30;
                connect_timeout = 60;
              }
            else if config.mattermost.database.driver == "mysql" then
              {
                charset = "utf8mb4,utf8";
                writeTimeout = "30s";
                readTimeout = "30s";
                writeTimeout = "60s";
                readTimeout = "60s";
              }
            else
              throw "Invalid database driver";
@@ -687,7 +702,7 @@ in
      };

      settings = mkOption {
        type = types.attrs;
        inherit (format) type;
        default = { };
        description = ''
          Additional configuration options as Nix attribute set in config.json schema.
@@ -786,7 +801,7 @@ in
          "d= ${tempDir} 0750 ${cfg.user} ${cfg.group} - -"

          # Ensure that pluginDir is a directory, as it could be a symlink on prior versions.
          "r- ${pluginDir} - - - - -"
          # Don't remove or clean it out since it should be persistent, as this is where plugins are unpacked.
          "d= ${pluginDir} 0750 ${cfg.user} ${cfg.group} - -"

          # Ensure that the plugin directories exist.
@@ -801,15 +816,14 @@ in
          "L+ ${cfg.dataDir}/client - - - - ${cfg.package}/client"
        ]
        ++ (
          if mattermostPlugins == null then
            # Create the plugin tarball directory if it's a symlink.
          if cfg.pluginsBundle == null then
            # Create the plugin tarball directory to allow plugin uploads.
            [
              "r- ${cfg.dataDir}/plugins - - - - -"
              "d= ${cfg.dataDir}/plugins 0750 ${cfg.user} ${cfg.group} - -"
            ]
          else
            # Symlink the plugin tarball directory, removing anything existing.
            [ "L+ ${cfg.dataDir}/plugins - - - - ${mattermostPlugins}" ]
            # Symlink the plugin tarball directory, removing anything existing, since it's managed by Nix.
            [ "L+ ${cfg.dataDir}/plugins - - - - ${cfg.pluginsBundle}" ]
        );

      systemd.services.mattermost = rec {
@@ -836,7 +850,7 @@ in
            configDir=${escapeShellArg cfg.configDir}
            logDir=${escapeShellArg cfg.logDir}
            package=${escapeShellArg cfg.package}
            nixConfig=${escapeShellArg mattermostConfJSON}
            nixConfig=${escapeShellArg finalConfig}
          ''
          + optionalString (versionAtLeast config.system.stateVersion "25.05") ''
            # Migrate configs in the pre-25.05 directory structure.
+134 −79
Original line number Diff line number Diff line
@@ -33,7 +33,7 @@ import ../make-test-python.nix (
              );
            };

            system.stateVersion = lib.mkDefault "25.05";
            system.stateVersion = lib.mkDefault (lib.versions.majorMinor lib.version);

            services.mattermost = lib.recursiveUpdate {
              enable = true;
@@ -63,7 +63,7 @@ import ../make-test-python.nix (
            # Upgrade to the latest Mattermost.
            specialisation.latest.configuration = {
              services.mattermost.package = lib.mkForce pkgs.mattermostLatest;
              system.stateVersion = lib.mkVMOverride "25.05";
              system.stateVersion = lib.mkVMOverride (lib.versions.majorMinor lib.version);
            };
          }
        )
@@ -90,22 +90,16 @@ import ../make-test-python.nix (
    name = "mattermost";

    nodes = rec {
      postgresMutable =
        makeMattermost
          {
      postgresMutable = makeMattermost {
        mutableConfig = true;
        preferNixConfig = false;
        settings.SupportSettings.HelpLink = "https://search.nixos.org";
          }
      } { };
      postgresMostlyMutable =
        makeMattermost
          {
            # Last version to support the "old" config layout.
            system.stateVersion = lib.mkForce "24.11";

            # First version to support the "new" config layout.
            specialisation.upgrade.configuration.system.stateVersion = lib.mkVMOverride "25.05";
          };
      postgresMostlyMutable = makeMattermost {
            mutableConfig = true;
            preferNixConfig = true;
            plugins = with pkgs; [
              # Build the demo plugin.
              (mattermost.buildPlugin {
@@ -140,7 +134,16 @@ import ../make-test-python.nix (
                };
              })
            ];
      } { };
          }
          {
            # Last version to support the "old" config layout.
            system.stateVersion = lib.mkForce "24.11";

            # Supports the "new" config layout.
            specialisation.upgrade.configuration.system.stateVersion = lib.mkVMOverride (
              lib.versions.majorMinor lib.version
            );
          };
      postgresImmutable = makeMattermost {
        package = pkgs.mattermost.overrideAttrs (prev: {
          webapp = prev.webapp.overrideAttrs (prevWebapp: {
@@ -343,9 +346,14 @@ import ../make-test-python.nix (
        '';
      in
      ''
        import sys
        import shlex
        import threading
        import queue

        def wait_mattermost_up(node, site_name="${siteName}"):
          print(f"wait_mattermost_up({node.name!r}, site_name={site_name!r})", file=sys.stderr)
          node.wait_for_unit("multi-user.target")
          node.systemctl("start mattermost.service")
          node.wait_for_unit("mattermost.service")
          node.wait_for_open_port(8065)
@@ -353,20 +361,25 @@ import ../make-test-python.nix (
          node.succeed(f"curl {shlex.quote('${url}')}/index.html | grep {shlex.quote(site_name)}")

        def restart_mattermost(node, site_name="${siteName}"):
          print(f"restart_mattermost({node.name!r}, site_name={site_name!r})", file=sys.stderr)
          node.systemctl("restart mattermost.service")
          wait_mattermost_up(node, site_name)

        def expect_config(node, mattermost_version, *configs):
          print(f"expect_config({node.name!r}, {mattermost_version!r}, *{configs!r})", file=sys.stderr)
          for config in configs:
            node.succeed(f"${expectConfig} {shlex.quote(config)} {shlex.quote(mattermost_version)}")

        def expect_plugins(node, jq_or_code):
          print(f"expect_plugins({node.name!r}, {jq_or_code!r})", file=sys.stderr)
          node.succeed(f"${expectPlugins} {shlex.quote(str(jq_or_code))}")

        def ensure_post(node, fail_if_not_found=False):
          print(f"ensure_post({node.name!r}, fail_if_not_found={fail_if_not_found!r})", file=sys.stderr)
          node.succeed(f"${ensurePost} {shlex.quote('${url}')} {1 if fail_if_not_found else 0}")

        def set_config(node, *configs, nixos_version='25.05'):
        def set_config(node, *configs, nixos_version='${lib.versions.majorMinor lib.version}'):
          print(f"set_config({node.name!r}, *{configs!r}, nixos_version={nixos_version!r})", file=sys.stderr)
          for config in configs:
            args = [shlex.quote("${setConfig}")]
            args.append(shlex.quote(config))
@@ -374,8 +387,13 @@ import ../make-test-python.nix (
              args.append(shlex.quote(str(nixos_version)))
            node.succeed(' '.join(args))

        def run_mattermost_tests(mutableToplevel: str, mutable,
                                 mostlyMutableToplevel: str, mostlyMutable,
        def switch_to_specialisation(node, toplevel: str, specialisation: str):
          print(f"switch_to_specialisation({node.name!r}, {toplevel!r}, {specialisation!r})", file=sys.stderr)
          node.succeed(f"{toplevel}/specialisation/{specialisation}/bin/switch-to-configuration switch || true")

        def run_mattermost_tests(shutdown_queue: queue.Queue,
                                 mutableToplevel: str, mutable,
                                 mostlyMutableToplevel: str, mostlyMutablePlugins: str, mostlyMutable,
                                 immutableToplevel: str, immutable,
                                 environmentFileToplevel: str, environmentFile):
          esr, latest = '${pkgs.mattermost.version}', '${pkgs.mattermostLatest.version}'
@@ -391,8 +409,7 @@ import ../make-test-python.nix (
          set_config(
            mutable,
            '.SupportSettings.AboutLink = "https://mattermost.com"',
            '.SupportSettings.HelpLink = "https://nixos.org/nixos/manual"',
            nixos_version='24.11' # Default 'mutable' config is an old version
            '.SupportSettings.HelpLink = "https://nixos.org/nixos/manual"'
          )
          ensure_post(mutable)
          restart_mattermost(mutable)
@@ -401,23 +418,14 @@ import ../make-test-python.nix (
          expect_config(mutable, esr, '.AboutLink == "https://mattermost.com" and .HelpLink == "https://nixos.org/nixos/manual"')
          ensure_post(mutable, fail_if_not_found=True)

          # Switch to the newer config
          mutable.succeed(f"{mutableToplevel}/specialisation/upgrade/bin/switch-to-configuration switch")
          wait_mattermost_up(mutable)

          # AboutLink and HelpLink should be changed, still, and the post should still exist
          expect_config(mutable, esr, '.AboutLink == "https://mattermost.com" and .HelpLink == "https://nixos.org/nixos/manual"')
          ensure_post(mutable, fail_if_not_found=True)

          # Switch to the latest Mattermost version
          mutable.succeed(f"{mutableToplevel}/specialisation/latest/bin/switch-to-configuration switch")
          switch_to_specialisation(mutable, mutableToplevel, "latest")
          wait_mattermost_up(mutable)

          # AboutLink and HelpLink should be changed, still, and the post should still exist
          expect_config(mutable, latest, '.AboutLink == "https://mattermost.com" and .HelpLink == "https://nixos.org/nixos/manual"')
          ensure_post(mutable, fail_if_not_found=True)

          mutable.shutdown()
          shutdown_queue.put(mutable)

          ## Mostly mutable node tests ##
          mostlyMutable.start()
@@ -434,13 +442,40 @@ import ../make-test-python.nix (
            mostlyMutable,
            '.SupportSettings.AboutLink = "https://mattermost.com"',
            '.SupportSettings.HelpLink = "https://nixos.org/nixos/manual"',
            nixos_version='24.11' # Default 'mostlyMutable' config is an old version
          )
          ensure_post(mostlyMutable)
          restart_mattermost(mostlyMutable)

          # HelpLink should be changed but AboutLink should not, and the post should exist
          expect_config(mostlyMutable, esr, '.AboutLink == "https://nixos.org" and .HelpLink == "https://nixos.org/nixos/manual"')
          ensure_post(mostlyMutable, fail_if_not_found=True)

          # Switch to the newer config and make sure the plugins directory is replaced with a directory,
          # since it could have been a symlink on previous versions.
          mostlyMutable.systemctl("stop mattermost.service")
          mostlyMutable.succeed(f"[ ! -L /var/lib/mattermost/data/plugins ] && rm -rf /var/lib/mattermost/data/plugins && ln -s {mostlyMutablePlugins} /var/lib/mattermost/data/plugins || true")
          mostlyMutable.succeed('[ -L /var/lib/mattermost/data/plugins ] && [ -d /var/lib/mattermost/data/plugins ]')
          switch_to_specialisation(mostlyMutable, mostlyMutableToplevel, "upgrade")
          wait_mattermost_up(mostlyMutable)
          mostlyMutable.succeed('[ ! -L /var/lib/mattermost/data/plugins ] && [ -d /var/lib/mattermost/data/plugins ]')

          # HelpLink should be changed, still, and the post should still exist
          expect_config(mostlyMutable, esr, '.AboutLink == "https://nixos.org" and .HelpLink == "https://nixos.org/nixos/manual"')
          ensure_post(mostlyMutable, fail_if_not_found=True)

          # Edit the config and make a post
          set_config(
            mostlyMutable,
            '.SupportSettings.AboutLink = "https://mattermost.com/foo"',
            '.SupportSettings.HelpLink = "https://nixos.org/nixos/manual/bar"',
            '.PluginSettings.PluginStates."com.mattermost.plugin-todo".Enable = true'
          )
          ensure_post(mostlyMutable)
          restart_mattermost(mostlyMutable)

          # AboutLink should be overridden by NixOS configuration; HelpLink should be what we set above
          expect_config(mostlyMutable, esr, '.AboutLink == "https://nixos.org" and .HelpLink == "https://nixos.org/nixos/manual"')
          expect_config(mostlyMutable, esr, '.AboutLink == "https://nixos.org" and .HelpLink == "https://nixos.org/nixos/manual/bar"')

          # Single plugin that's now enabled.
          expect_plugins(mostlyMutable, 'length == 1')
@@ -449,14 +484,14 @@ import ../make-test-python.nix (
          ensure_post(mostlyMutable, fail_if_not_found=True)

          # Switch to the latest Mattermost version
          mostlyMutable.succeed(f"{mostlyMutableToplevel}/specialisation/latest/bin/switch-to-configuration switch")
          switch_to_specialisation(mostlyMutable, mostlyMutableToplevel, "latest")
          wait_mattermost_up(mostlyMutable)

          # AboutLink should be overridden and the post should still exist
          expect_config(mostlyMutable, latest, '.AboutLink == "https://nixos.org" and .HelpLink == "https://nixos.org/nixos/manual"')
          expect_config(mostlyMutable, latest, '.AboutLink == "https://nixos.org" and .HelpLink == "https://nixos.org/nixos/manual/bar"')
          ensure_post(mostlyMutable, fail_if_not_found=True)

          mostlyMutable.shutdown()
          shutdown_queue.put(mostlyMutable)

          ## Immutable node tests ##
          immutable.start()
@@ -484,14 +519,14 @@ import ../make-test-python.nix (
          ensure_post(immutable, fail_if_not_found=True)

          # Switch to the latest Mattermost version
          immutable.succeed(f"{immutableToplevel}/specialisation/latest/bin/switch-to-configuration switch")
          switch_to_specialisation(immutable, immutableToplevel, "latest")
          wait_mattermost_up(immutable)

          # AboutLink and HelpLink should be changed, still, and the post should still exist
          expect_config(immutable, latest, '.AboutLink == "https://nixos.org" and .HelpLink == "https://search.nixos.org"')
          ensure_post(immutable, fail_if_not_found=True)

          immutable.shutdown()
          shutdown_queue.put(immutable)

          ## Environment File node tests ##
          environmentFile.start()
@@ -503,36 +538,56 @@ import ../make-test-python.nix (
          ensure_post(environmentFile, fail_if_not_found=True)

          # Switch to the latest Mattermost version
          environmentFile.succeed(f"{environmentFileToplevel}/specialisation/latest/bin/switch-to-configuration switch")
          switch_to_specialisation(environmentFile, environmentFileToplevel, "latest")
          wait_mattermost_up(environmentFile)

          # AboutLink should be changed still, and the post should still exist
          expect_config(environmentFile, latest, '.AboutLink == "https://nixos.org"')
          ensure_post(environmentFile, fail_if_not_found=True)

          environmentFile.shutdown()
          shutdown_queue.put(environmentFile)

        # Run shutdowns asynchronously so we can pipeline them.
        shutdown_queue: queue.Queue = queue.Queue()
        def shutdown_worker():
          while True:
            node = shutdown_queue.get()
            print(f"Shutting down node {node.name!r} asynchronously", file=sys.stderr)
            node.shutdown()
            shutdown_queue.task_done()
        threading.Thread(target=shutdown_worker, daemon=True).start()

        ${pkgs.lib.optionalString pkgs.stdenv.isx86_64 ''
          # Only run the MySQL tests on x86_64 so we don't have to debug MySQL ARM issues.
          run_mattermost_tests(
            shutdown_queue,
            "${nodes.mysqlMutable.system.build.toplevel}",
            mysqlMutable,
            "${nodes.mysqlMostlyMutable.system.build.toplevel}",
            "${nodes.mysqlMostlyMutable.services.mattermost.pluginsBundle}",
            mysqlMostlyMutable,
            "${nodes.mysqlImmutable.system.build.toplevel}",
            mysqlImmutable,
            "${nodes.mysqlEnvironmentFile.system.build.toplevel}",
            mysqlEnvironmentFile
          )
        ''}

        run_mattermost_tests(
          shutdown_queue,
          "${nodes.postgresMutable.system.build.toplevel}",
          postgresMutable,
          "${nodes.postgresMostlyMutable.system.build.toplevel}",
          "${nodes.postgresMostlyMutable.services.mattermost.pluginsBundle}",
          postgresMostlyMutable,
          "${nodes.postgresImmutable.system.build.toplevel}",
          postgresImmutable,
          "${nodes.postgresEnvironmentFile.system.build.toplevel}",
          postgresEnvironmentFile
        )

        # Drain the queue
        shutdown_queue.join()
      '';
  }
)
+9 −6
Original line number Diff line number Diff line
@@ -18,11 +18,14 @@
    # the version regex here as well.
    #
    # Ensure you also check ../mattermostLatest/package.nix.
    regex = "^v(9\\.11\\.[0-9]+)$";
    version = "9.11.11";
    srcHash = "sha256-ugFGb85Oolg9pXeNi2JFKWQ4eebmdr/O3xIGbKGFSvQ=";
    vendorHash = "sha256-h/hcdVImU3wFp7BGHS/TxYBEWGv9v06y8etaz9OrHTA=";
    npmDepsHash = "sha256-Kk0Bbx/Rs5xpwSpgpm9BSMMEMKmO6kgKgyv/oDIAZ7w=";
    regex = "^v(10\\.5\\.[0-9]+)$";
    version = "10.5.2";
    srcHash = "sha256-wC8tkplOntZpucCe2QPmnlrecwcqkzyEiTni8lO0p1I=";
    vendorHash = "sha256-7jghoXFKA+WZ/ywOT0wWDMTfqAcBqp5gswOvpB7weL0=";
    npmDepsHash = "sha256-tIeuDUZbqgqooDm5TRfViiTT5OIyN0BPwvJdI+wf7p0=";
    lockfileOverlay = ''
      unlock(.; "@floating-ui/react"; "channels/node_modules/@floating-ui/react")
    '';
  },
}:

@@ -80,7 +83,7 @@ let
          tests.mattermostWithTests = withTests;
        };
    in
    finalPassthru.withTests;
    finalPassthru.withoutTests;
in
buildMattermost rec {
  pname = "mattermost";
+4 −0
Original line number Diff line number Diff line
@@ -146,6 +146,10 @@ mattermost.overrideAttrs (
      ++ optionals (!stdenv.hostPlatform.isx86_64) [
        # aarch64: invalid operating system or processor architecture
        "TestCanIUpgradeToE0"

        # aarch64: thumbnail previews are nondeterministic
        "TestUploadFiles/multipart_Happy_image_thumbnail"
        "TestUploadFiles/simple_Happy_image_thumbnail"
      ];

    preCheck = ''