<commit_before>{ stdenv, makeWrapper, runCommandNoCC, lib, nixosTests, writeShellScript
, fetchFromGitHub, bundlerEnv, callPackage

, ruby, replace, gzip, gnutar, git, cacert, util-linux, gawk
, imagemagick, optipng, pngquant, libjpeg, jpegoptim, gifsicle, libpsl
, redis, postgresql, which, brotli, procps, rsync, nodePackages, v8

, plugins ? []
}:

let
  version = "2.7.4";

  src = fetchFromGitHub {
    owner = "discourse";
    repo = "discourse";
    rev = "v${version}";
    sha256 = "sha256-3cvrdWBXRM5F8qFEqbe8ru1U0wBqCkRxK7GAV0beJNk=";
  };

  runtimeDeps = [
    # For backups, themes and assets
    rubyEnv.wrappedRuby
    rsync
    gzip
    gnutar
    git
    brotli

    # Misc required system utils
    which
    procps       # For ps and kill
    util-linux   # For renice
    gawk

    # Image optimization
    imagemagick
    optipng
    pngquant
    libjpeg
    jpegoptim
    gifsicle
    nodePackages.svgo
  ];

  runtimeEnv = {
    HOME = "/run/discourse/home";
    RAILS_ENV = "production";
    UNICORN_LISTENER = "/run/discourse/sockets/unicorn.sock";
  };

  mkDiscoursePlugin =
    { name ? null
    , pname ? null
    , version ? null
    , meta ? null
    , bundlerEnvArgs ? {}
    , src
    , ...
    }@args:
    let
      rubyEnv = bundlerEnv (bundlerEnvArgs // {
        inherit name pname version ruby;
      });
    in
      stdenv.mkDerivation (builtins.removeAttrs args [ "bundlerEnvArgs" ] // {
        pluginName = if name != null then name else "${pname}-${version}";
        phases = [ "unpackPhase" "installPhase" ];
        installPhase = ''
          runHook preInstall
          mkdir -p $out
          cp -r * $out/
        '' + lib.optionalString (bundlerEnvArgs != {}) ''
          ln -sf ${rubyEnv}/lib/ruby/gems $out/gems
        '' + ''
          runHook postInstall
        '';
      });

  rake = runCommandNoCC "discourse-rake" {
    nativeBuildInputs = [ makeWrapper ];
  } ''
    mkdir -p $out/bin
    makeWrapper ${rubyEnv}/bin/rake $out/bin/discourse-rake \
        ${lib.concatStrings (lib.mapAttrsToList (name: value: "--set ${name} '${value}' ") runtimeEnv)} \
        --prefix PATH : ${lib.makeBinPath runtimeDeps} \
        --set RAKEOPT '-f ${discourse}/share/discourse/Rakefile' \
        --run 'cd ${discourse}/share/discourse'
  '';

  rubyEnv = bundlerEnv {
    name = "discourse-ruby-env-${version}";
    inherit version ruby;
    gemdir = ./rubyEnv;
    gemset =
      let
        gems = import ./rubyEnv/gemset.nix;
      in
        gems // {
          libv8-node =
            let
              noopScript = writeShellScript "noop" "exit 0";
              linkFiles = writeShellScript "link-files" ''
                cd ../..

                mkdir -p vendor/v8/out.gn/libv8/obj/
                ln -s "${v8}/lib/libv8.a" vendor/v8/out.gn/libv8/obj/libv8_monolith.a

                ln -s ${v8}/include vendor/v8/include

                mkdir -p ext/libv8-node
                echo '--- !ruby/object:Libv8::Node::Location::Vendor {}' >ext/libv8-node/.location.yml
              '';
            in gems.libv8-node // {
              dontBuild = false;
              postPatch = ''
                cp ${noopScript} libexec/build-libv8
                cp ${noopScript} libexec/build-monolith
                cp ${noopScript} libexec/download-node
                cp ${noopScript} libexec/extract-node
                cp ${linkFiles} libexec/inject-libv8
              '';
            };
          mini_suffix = gems.mini_suffix // {
            propagatedBuildInputs = [ libpsl ];
            dontBuild = false;
            # Use our libpsl instead of the vendored one, which isn't
            # available for aarch64. It has to be called
            # libpsl.x86_64.so or it isn't found.
            postPatch = ''
              cp $(readlink -f ${libpsl}/lib/libpsl.so) vendor/libpsl.x86_64.so
            '';
          };
        };

    groups = [
      "default" "assets" "development" "test"
    ];
  };

  assets = stdenv.mkDerivation {
    pname = "discourse-assets";
    inherit version src;

    nativeBuildInputs = [
      rubyEnv.wrappedRuby
      postgresql
      redis
      which
      brotli
      procps
      nodePackages.uglify-js
    ];

    patches = [
      # Use the Ruby API version in the plugin gem path, to match the
      # one constructed by bundlerEnv
      ./plugin_gem_api_version.patch
    ];

    # We have to set up an environment that is close enough to<commit_msg>discourse: Use `terser` when building assets<commit_after>{ stdenv, makeWrapper, runCommandNoCC, lib, nixosTests, writeShellScript
, fetchFromGitHub, bundlerEnv, callPackage

, ruby, replace, gzip, gnutar, git, cacert, util-linux, gawk
, imagemagick, optipng, pngquant, libjpeg, jpegoptim, gifsicle, libpsl
, redis, postgresql, which, brotli, procps, rsync, nodePackages, v8

, plugins ? []
}:

let
  version = "2.7.4";

  src = fetchFromGitHub {
    owner = "discourse";
    repo = "discourse";
    rev = "v${version}";
    sha256 = "sha256-3cvrdWBXRM5F8qFEqbe8ru1U0wBqCkRxK7GAV0beJNk=";
  };

  runtimeDeps = [
    # For backups, themes and assets
    rubyEnv.wrappedRuby
    rsync
    gzip
    gnutar
    git
    brotli

    # Misc required system utils
    which
    procps       # For ps and kill
    util-linux   # For renice
    gawk

    # Image optimization
    imagemagick
    optipng
    pngquant
    libjpeg
    jpegoptim
    gifsicle
    nodePackages.svgo
  ];

  runtimeEnv = {
    HOME = "/run/discourse/home";
    RAILS_ENV = "production";
    UNICORN_LISTENER = "/run/discourse/sockets/unicorn.sock";
  };

  mkDiscoursePlugin =
    { name ? null
    , pname ? null
    , version ? null
    , meta ? null
    , bundlerEnvArgs ? {}
    , src
    , ...
    }@args:
    let
      rubyEnv = bundlerEnv (bundlerEnvArgs // {
        inherit name pname version ruby;
      });
    in
      stdenv.mkDerivation (builtins.removeAttrs args [ "bundlerEnvArgs" ] // {
        pluginName = if name != null then name else "${pname}-${version}";
        phases = [ "unpackPhase" "installPhase" ];
        installPhase = ''
          runHook preInstall
          mkdir -p $out
          cp -r * $out/
        '' + lib.optionalString (bundlerEnvArgs != {}) ''
          ln -sf ${rubyEnv}/lib/ruby/gems $out/gems
        '' + ''
          runHook postInstall
        '';
      });

  rake = runCommandNoCC "discourse-rake" {
    nativeBuildInputs = [ makeWrapper ];
  } ''
    mkdir -p $out/bin
    makeWrapper ${rubyEnv}/bin/rake $out/bin/discourse-rake \
        ${lib.concatStrings (lib.mapAttrsToList (name: value: "--set ${name} '${value}' ") runtimeEnv)} \
        --prefix PATH : ${lib.makeBinPath runtimeDeps} \
        --set RAKEOPT '-f ${discourse}/share/discourse/Rakefile' \
        --run 'cd ${discourse}/share/discourse'
  '';

  rubyEnv = bundlerEnv {
    name = "discourse-ruby-env-${version}";
    inherit version ruby;
    gemdir = ./rubyEnv;
    gemset =
      let
        gems = import ./rubyEnv/gemset.nix;
      in
        gems // {
          libv8-node =
            let
              noopScript = writeShellScript "noop" "exit 0";
              linkFiles = writeShellScript "link-files" ''
                cd ../..

                mkdir -p vendor/v8/out.gn/libv8/obj/
                ln -s "${v8}/lib/libv8.a" vendor/v8/out.gn/libv8/obj/libv8_monolith.a

                ln -s ${v8}/include vendor/v8/include

                mkdir -p ext/libv8-node
                echo '--- !ruby/object:Libv8::Node::Location::Vendor {}' >ext/libv8-node/.location.yml
              '';
            in gems.libv8-node // {
              dontBuild = false;
              postPatch = ''
                cp ${noopScript} libexec/build-libv8
                cp ${noopScript} libexec/build-monolith
                cp ${noopScript} libexec/download-node
                cp ${noopScript} libexec/extract-node
                cp ${linkFiles} libexec/inject-libv8
              '';
            };
          mini_suffix = gems.mini_suffix // {
            propagatedBuildInputs = [ libpsl ];
            dontBuild = false;
            # Use our libpsl instead of the vendored one, which isn't
            # available for aarch64. It has to be called
            # libpsl.x86_64.so or it isn't found.
            postPatch = ''
              cp $(readlink -f ${libpsl}/lib/libpsl.so) vendor/libpsl.x86_64.so
            '';
          };
        };

    groups = [
      "default" "assets" "development" "test"
    ];
  };

  assets = stdenv.mkDerivation {
    pname = "discourse-assets";
    inherit version src;

    nativeBuildInputs = [
      rubyEnv.wrappedRuby
      postgresql
      redis
      which
      brotli
      procps
      nodePackages.uglify-js
      nodePackages.terser
    ];

    patches = [
      # Use the Ruby API version in the plugin gem path, to match the
      # one constructed by bundlerEnv
      ./plugin_gem_api_version.patch
    ];

    # We have to set up an environment that is close enough to
{'fraction_non_alphanumeric': 0.1165350828422106, 'fraction_numerical': 0.010007783831869232, 'mean_word_length': 1.8570520965692503, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3215020', 'n_tokens_mistral': 3071, 'n_tokens_neox': 2896, 'n_words': 651}