push sheeet
Some checks failed
Periodic Merges (6h) / master → staging-nixos (push) Failing after 12m50s
Periodic Merges (6h) / master → staging-next (push) Failing after 12m54s
Periodic Merges (24h) / merge-base(master,staging) → haskell-updates (push) Failing after 11m54s
Periodic Merges (6h) / staging-next → staging (push) Failing after 12m13s
Periodic Merges (24h) / staging-next-25.05 → staging-25.05 (push) Failing after 13m24s
Periodic Merges (24h) / release-25.05 → staging-next-25.05 (push) Failing after 14m28s

This commit is contained in:
Dark Steveneq
2025-10-09 14:15:47 +02:00
commit 646b892680
49168 changed files with 5897842 additions and 0 deletions

View File

@@ -0,0 +1,12 @@
diff --git a/app/models/global_setting.rb b/app/models/global_setting.rb
index 6e06e18039..b2bef31fe2 100644
--- a/app/models/global_setting.rb
+++ b/app/models/global_setting.rb
@@ -255,6 +255,7 @@ class GlobalSetting
domain: GlobalSetting.smtp_domain,
user_name: GlobalSetting.smtp_user_name,
password: GlobalSetting.smtp_password,
+ ca_file: "/etc/ssl/certs/ca-certificates.crt",
enable_starttls_auto: GlobalSetting.smtp_enable_start_tls,
open_timeout: GlobalSetting.smtp_open_timeout,
read_timeout: GlobalSetting.smtp_read_timeout,

View File

@@ -0,0 +1,48 @@
diff --git a/lib/tasks/admin.rake b/lib/tasks/admin.rake
index 37ef651f2b..b775129498 100644
--- a/lib/tasks/admin.rake
+++ b/lib/tasks/admin.rake
@@ -107,3 +107,43 @@ task "admin:create" => :environment do
end
end
+
+desc "Creates a forum administrator noninteractively"
+task "admin:create_noninteractively" => :environment do
+ email = ENV["ADMIN_EMAIL"]
+ existing_user = User.find_by_email(email)
+
+ # check if user account already exixts
+ if existing_user
+ admin = existing_user
+ else
+ # create new user
+ admin = User.new
+ end
+
+ admin.email = email
+ admin.name = ENV["ADMIN_NAME"]
+ admin.username = ENV["ADMIN_USERNAME"]
+
+ password = ENV["ADMIN_PASSWORD"]
+ unless admin.confirm_password?(password)
+ admin.password = password
+ puts "Admin password set!"
+ end
+
+ admin.active = true
+
+ # save/update user account
+ saved = admin.save
+ raise admin.errors.full_messages.join("\n") unless saved
+
+ puts "Account created successfully with username #{admin.username}" unless existing_user
+
+ # grant admin privileges
+ admin.grant_admin!
+ if admin.trust_level < 1
+ admin.change_trust_level!(1)
+ end
+ admin.email_tokens.update_all confirmed: true
+ admin.activate
+end

View File

@@ -0,0 +1,13 @@
diff --git a/lib/tasks/assets.rake b/lib/tasks/assets.rake
index 9608297789..5487490915 100644
--- a/lib/tasks/assets.rake
+++ b/lib/tasks/assets.rake
@@ -36,7 +36,7 @@ task "assets:precompile:build" do
if only_ember_precompile_build_remaining
exec "#{compile_command}"
elsif only_assets_precompile_remaining
- exec "#{compile_command} && SKIP_EMBER_CLI_COMPILE=1 bin/rake assets:precompile"
+ exec "#{compile_command} && SKIP_EMBER_CLI_COMPILE=1 bundle exec rake assets:precompile"
else
system compile_command, exception: true
EmberCli.clear_cache!

View File

@@ -0,0 +1,13 @@
diff --git a/lib/plugin/instance.rb b/lib/plugin/instance.rb
index 8482ff0210..826d111d65 100644
--- a/lib/plugin/instance.rb
+++ b/lib/plugin/instance.rb
@@ -455,7 +455,7 @@ class Plugin::Instance
end
def auto_generated_path
- File.dirname(path) << "/auto_generated"
+ "#{Rails.root}/public/assets/auto_generated_plugin_assets/#{name}"
end
def after_initialize(&block)

View File

@@ -0,0 +1,452 @@
{
stdenv,
pkgs,
makeWrapper,
runCommand,
lib,
writeShellScript,
fetchFromGitHub,
bundlerEnv,
callPackage,
nixosTests,
ruby_3_3,
gzip,
gnutar,
git,
cacert,
util-linux,
gawk,
net-tools,
imagemagick,
optipng,
pngquant,
libjpeg,
jpegoptim,
gifsicle,
jhead,
oxipng,
libpsl,
redis,
postgresql,
which,
brotli,
procps,
rsync,
icu,
pnpm_9,
svgo,
nodejs,
jq,
moreutils,
terser,
uglify-js,
plugins ? [ ],
}:
let
version = "3.4.7";
src = fetchFromGitHub {
owner = "discourse";
repo = "discourse";
rev = "v${version}";
sha256 = "sha256-vidv5aa2r1YOcnvkqrk7ttuIk1bN5Ct7kMANl8kpEm0=";
};
ruby = ruby_3_3;
runtimeDeps = [
# For backups, themes and assets
rubyEnv.wrappedRuby
rsync
gzip
gnutar
git
brotli
nodejs
# Misc required system utils
which
procps # For ps and kill
util-linux # For renice
gawk
net-tools # For hostname
# Image optimization
imagemagick
optipng
oxipng
pngquant
libjpeg
jpegoptim
gifsicle
svgo
jhead
];
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 ? { },
preserveGemsDir ? false,
src,
...
}@args:
let
rubyEnv = bundlerEnv (
bundlerEnvArgs
// {
inherit
name
pname
version
ruby
;
}
);
in
stdenv.mkDerivation (
removeAttrs args [ "bundlerEnvArgs" ]
// {
pluginName = if name != null then name else "${pname}-${version}";
dontConfigure = true;
dontBuild = true;
installPhase = ''
runHook preInstall
mkdir -p $out
cp -r * $out/
''
+ lib.optionalString (bundlerEnvArgs != { }) (
if preserveGemsDir then
''
cp -r ${rubyEnv}/lib/ruby/gems/* $out/gems/
''
else
''
if [[ -e $out/gems ]]; then
echo "Warning: The repo contains a 'gems' directory which will be removed!"
echo " If you need to preserve it, set 'preserveGemsDir = true'."
rm -r $out/gems
fi
ln -sf ${rubyEnv}/lib/ruby/gems $out/gems
''
+ ''
runHook postInstall
''
);
}
);
rake =
runCommand "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' \
--chdir '${discourse}/share/discourse'
'';
rubyEnv = bundlerEnv {
name = "discourse-ruby-env-${version}";
inherit version ruby;
gemdir = ./rubyEnv;
gemset =
let
gems = import ./rubyEnv/gemset.nix;
in
gems
// {
mini_racer = gems.mini_racer // {
buildInputs = [ icu ];
dontBuild = false;
NIX_LDFLAGS = "-licui18n";
};
libv8-node =
let
noopScript = writeShellScript "noop" "exit 0";
linkFiles = writeShellScript "link-files" ''
cd ../..
mkdir -p vendor/v8/${stdenv.hostPlatform.system}/libv8/obj/
ln -s "${nodejs.libv8}/lib/libv8.a" vendor/v8/${stdenv.hostPlatform.system}/libv8/obj/libv8_monolith.a
ln -s ${nodejs.libv8}/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 ${lib.getLib libpsl}/lib/libpsl.so) vendor/libpsl.x86_64.so
'';
};
};
groups = [
"default"
"assets"
"development"
"test"
];
};
assets = stdenv.mkDerivation {
pname = "discourse-assets";
inherit version src;
pnpmDeps = pnpm_9.fetchDeps {
pname = "discourse-assets";
inherit version src;
fetcherVersion = 1;
hash = "sha256-WyRBnuKCl5NJLtqy3HK/sJcrpMkh0PjbasGPNDV6+7Y=";
};
nativeBuildInputs = runtimeDeps ++ [
postgresql
redis
uglify-js
terser
jq
moreutils
nodejs
pnpm_9.configHook
];
outputs = [
"out"
"javascripts"
"node_modules"
];
patches = [
# Use the Ruby API version in the plugin gem path, to match the
# one constructed by bundlerEnv
./plugin_gem_api_version.patch
# Change the path to the auto generated plugin assets, which
# defaults to the plugin's directory and isn't writable at the
# time of asset generation
./auto_generated_path.patch
# Fix the rake command used to recursively execute itself in the
# assets precompilation task.
./assets_rake_command.patch
# Little does he know, so he decided there is no need to generate the
# theme-transpiler over and over again. Which at the same time allows the removal
# of javascript devDependencies from the runtime environment.
./prebuild-theme-transpiler.patch
];
env.RAILS_ENV = "production";
# We have to set up an environment that is close enough to
# production ready or the assets:precompile task refuses to
# run. This means that Redis and PostgreSQL has to be running and
# database migrations performed.
preBuild = ''
# Patch before running postinstall hook script
patchShebangs node_modules/
patchShebangs --build app/assets/javascripts
export SSL_CERT_FILE=${cacert}/etc/ssl/certs/ca-bundle.crt
redis-server >/dev/null &
initdb -A trust $NIX_BUILD_TOP/postgres >/dev/null
postgres -D $NIX_BUILD_TOP/postgres -k $NIX_BUILD_TOP >/dev/null &
export PGHOST=$NIX_BUILD_TOP
echo "Waiting for Redis and PostgreSQL to be ready.."
while ! redis-cli --scan >/dev/null || ! psql -l >/dev/null; do
sleep 0.1
done
psql -d postgres -tAc 'CREATE USER "discourse"'
psql -d postgres -tAc 'CREATE DATABASE "discourse" OWNER "discourse"'
psql 'discourse' -tAc "CREATE EXTENSION IF NOT EXISTS pg_trgm"
psql 'discourse' -tAc "CREATE EXTENSION IF NOT EXISTS hstore"
${lib.concatMapStringsSep "\n" (p: "ln -sf ${p} plugins/${p.pluginName or ""}") plugins}
bundle exec rake db:migrate >/dev/null
chmod -R +w tmp
'';
buildPhase = ''
runHook preBuild
bundle exec rake assets:precompile
runHook postBuild
'';
installPhase = ''
runHook preInstall
mv public/assets $out
mv node_modules $node_modules
rm -r app/assets/javascripts/plugins
mv app/assets/javascripts $javascripts
ln -sf /run/discourse/assets/javascripts/plugins $javascripts/plugins
runHook postInstall
'';
# The node_modules output by design has broken symlinks, as it refers to the source code.
# They are resolved in the primary discourse derivation.
dontCheckForBrokenSymlinks = true;
};
discourse = stdenv.mkDerivation {
pname = "discourse";
inherit version src;
buildInputs = [
rubyEnv
rubyEnv.wrappedRuby
rubyEnv.bundler
];
patches = [
# Load a separate NixOS site settings file
./nixos_defaults.patch
# Add a noninteractive admin creation task
./admin_create.patch
# Add the path to the CA cert bundle to make TLS work
./action_mailer_ca_cert.patch
# Log Unicorn messages to the journal and make request timeout
# configurable
./unicorn_logging_and_timeout.patch
# Use the Ruby API version in the plugin gem path, to match the
# one constructed by bundlerEnv
./plugin_gem_api_version.patch
# Change the path to the auto generated plugin assets, which
# defaults to the plugin's directory and isn't writable at the
# time of asset generation
./auto_generated_path.patch
# Make sure the notification email setting applies
./notification_email.patch
# Little does he know, so he decided there is no need to generate the
# theme-transpiler over and over again. Which at the same time allows the removal
# of javascript devDependencies from the runtime environment.
./prebuild-theme-transpiler.patch
];
postPatch = ''
# Always require lib-files and application.rb through their store
# path, not their relative state directory path. This gets rid of
# warnings and means we don't have to link back to lib from the
# state directory.
find config -type f -name "*.rb" -execdir \
sed -Ei "s,(\.\./)+(lib|app)/,$out/share/discourse/\2/," {} \;
find config -maxdepth 1 -type f -name "*.rb" -execdir \
sed -Ei "s,require_relative (\"|')([[:alnum:]].*)(\"|'),require_relative '$out/share/discourse/config/\2'," {} \;
'';
buildPhase = ''
runHook preBuild
mv config config.dist
mv public public.dist
runHook postBuild
'';
installPhase = ''
runHook preInstall
mkdir -p $out/share
cp -r . $out/share/discourse
rm -r $out/share/discourse/log
ln -sf /var/log/discourse $out/share/discourse/log
ln -sf /var/lib/discourse/tmp $out/share/discourse/tmp
ln -sf /run/discourse/config $out/share/discourse/config
ln -sf /run/discourse/public $out/share/discourse/public
ln -sf ${assets.node_modules} $out/share/discourse/node_modules
ln -sf ${assets} $out/share/discourse/public.dist/assets
rm -r $out/share/discourse/app/assets/javascripts
# This needs to be copied because it contains symlinks to node_modules
cp -r ${assets.javascripts} $out/share/discourse/app/assets/javascripts
${lib.concatMapStringsSep "\n" (
p: "ln -sf ${p} $out/share/discourse/plugins/${p.pluginName or ""}"
) plugins}
runHook postInstall
'';
passthru = {
inherit
rubyEnv
runtimeEnv
runtimeDeps
rake
mkDiscoursePlugin
assets
;
inherit (pkgs)
discourseAllPlugins
;
enabledPlugins = plugins;
plugins = callPackage ./plugins/all-plugins.nix { inherit mkDiscoursePlugin; };
ruby = rubyEnv.wrappedRuby;
tests = {
inherit (nixosTests)
discourse
discourseAllPlugins
;
};
};
meta = with lib; {
homepage = "https://www.discourse.org/";
platforms = platforms.linux;
maintainers = with maintainers; [ talyz ];
license = licenses.gpl2Plus;
description = "Open source discussion platform";
};
};
in
discourse

View File

@@ -0,0 +1,24 @@
To update discourse, do the following:
1. Switch to and work from the `master` branch and the directory this
file is in.
2. Run `./update.py print-diffs` and update the nginx settings and
backend settings accordingly. If you don't know how to, ask for
help - do not skip this step!
3. Run `./update.py update`.
4. Run `nix build -L -f ../../../../ discourse.tests` to make sure the
update works. Also test manually, if possible.
5. If the update works, commit it. If not, apply necessary fixes and
commit. No manual fixes that would be overwritten by the
`./update.py` script should be committed - the script should be
fixed instead.
6. Run `./update.py update-mail-receiver`. If there's an update, do
step 4 and 5 again.
7. Run `./update.py update-plugins`.
8. Run `nix build -L -f ../../../../ discourseAllPlugins.tests` to
make sure the plugins build and discourse starts with them. Also
test manually, if possible.
9. If the update works, commit it. If not, apply necessary fixes and
commit. No manual fixes that would be overwritten by the
`./update.py` script should be committed - the script should be
fixed instead.

View File

@@ -0,0 +1,13 @@
diff --git a/app/models/site_setting.rb b/app/models/site_setting.rb
index a6641f967a..a45353504a 100644
--- a/app/models/site_setting.rb
+++ b/app/models/site_setting.rb
@@ -21,6 +21,8 @@ class SiteSetting < ActiveRecord::Base
end
end
+ load_settings(File.join(Rails.root, 'config', 'nixos_site_settings.json'))
+
setup_deprecated_methods
client_settings << :available_locales

View File

@@ -0,0 +1,18 @@
diff --git a/db/fixtures/990_settings.rb b/db/fixtures/990_settings.rb
deleted file mode 100644
index 6f21e58813..0000000000
--- a/db/fixtures/990_settings.rb
+++ /dev/null
@@ -1,12 +0,0 @@
-# frozen_string_literal: true
-
-if SiteSetting.notification_email == SiteSetting.defaults[:notification_email]
- # don't crash for invalid hostname, which is possible in dev
- begin
- SiteSetting.notification_email = "noreply@#{Discourse.current_hostname}"
- rescue Discourse::InvalidParameters
- if Rails.env.production?
- STDERR.puts "WARNING: Discourse hostname: #{Discourse.current_hostname} is not a valid domain for emails!"
- end
- end
-end

View File

@@ -0,0 +1,13 @@
diff --git a/lib/plugin_gem.rb b/lib/plugin_gem.rb
index 49882b2cd9..96672df2ea 100644
--- a/lib/plugin_gem.rb
+++ b/lib/plugin_gem.rb
@@ -4,7 +4,7 @@ module PluginGem
def self.load(path, name, version, opts = nil)
opts ||= {}
- gems_path = File.dirname(path) + "/gems/#{RUBY_VERSION}"
+ gems_path = File.dirname(path) + "/gems/#{Gem.ruby_api_version}"
spec_path = gems_path + "/specifications"

View File

@@ -0,0 +1,4 @@
Run the nixpkgs/pkgs/servers/web-apps/discourse/update.py script to
update plugins! See the Plugins section of the Discourse chapter in
the NixOS manual (https://nixos.org/manual/nixos/unstable/index.html#module-services-discourse)
for more info.

View File

@@ -0,0 +1,27 @@
{ mkDiscoursePlugin, newScope, ... }@args:
let
callPackage = newScope args;
in
{
discourse-assign = callPackage ./discourse-assign { };
discourse-bbcode-color = callPackage ./discourse-bbcode-color { };
discourse-calendar = callPackage ./discourse-calendar { };
discourse-canned-replies = callPackage ./discourse-canned-replies { };
discourse-chat-integration = callPackage ./discourse-chat-integration { };
discourse-checklist = callPackage ./discourse-checklist { };
discourse-data-explorer = callPackage ./discourse-data-explorer { };
discourse-docs = callPackage ./discourse-docs { };
discourse-github = callPackage ./discourse-github { };
discourse-ldap-auth = callPackage ./discourse-ldap-auth { };
discourse-math = callPackage ./discourse-math { };
discourse-migratepassword = callPackage ./discourse-migratepassword { };
discourse-oauth2-basic = callPackage ./discourse-oauth2-basic { };
discourse-openid-connect = callPackage ./discourse-openid-connect { };
discourse-prometheus = callPackage ./discourse-prometheus { };
discourse-reactions = callPackage ./discourse-reactions { };
discourse-saved-searches = callPackage ./discourse-saved-searches { };
discourse-solved = callPackage ./discourse-solved { };
discourse-spoiler-alert = callPackage ./discourse-spoiler-alert { };
discourse-voting = callPackage ./discourse-voting { };
discourse-yearly-review = callPackage ./discourse-yearly-review { };
}

View File

@@ -0,0 +1,21 @@
{
lib,
mkDiscoursePlugin,
fetchFromGitHub,
}:
mkDiscoursePlugin {
name = "discourse-assign";
src = fetchFromGitHub {
owner = "discourse";
repo = "discourse-assign";
rev = "261a47d119d200a8d922d008ad3d1667df869435";
sha256 = "sha256-0OClWO70btM7EN7Vir1LIhCTeO5+2jtkP4RozoKzp+0=";
};
meta = with lib; {
homepage = "https://github.com/discourse/discourse-docs";
maintainers = with maintainers; [ dpausp ];
license = licenses.mit;
description = "Discourse Plugin for assigning users to a topic";
};
}

View File

@@ -0,0 +1,21 @@
{
lib,
mkDiscoursePlugin,
fetchFromGitHub,
}:
mkDiscoursePlugin {
name = "discourse-bbcode-color";
src = fetchFromGitHub {
owner = "discourse";
repo = "discourse-bbcode-color";
rev = "ecd4befeb4eae48aa0a37a88e5aca60e59730411";
sha256 = "sha256-enpeXc6pE9+5EdbMIFsnWd++ixlHBKFRxbXmvJYJftg=";
};
meta = with lib; {
homepage = "https://github.com/discourse/discourse-bbcode-color";
maintainers = with maintainers; [ ryantm ];
license = licenses.mit;
description = "Support BBCode color tags";
};
}

View File

@@ -0,0 +1,6 @@
# frozen_string_literal: true
source "https://rubygems.org"
# gem "rails"
gem "rrule", "0.4.4", require: false

View File

@@ -0,0 +1,35 @@
GEM
remote: https://rubygems.org/
specs:
activesupport (7.1.3.3)
base64
bigdecimal
concurrent-ruby (~> 1.0, >= 1.0.2)
connection_pool (>= 2.2.5)
drb
i18n (>= 1.6, < 2)
minitest (>= 5.1)
mutex_m
tzinfo (~> 2.0)
base64 (0.2.0)
bigdecimal (3.1.8)
concurrent-ruby (1.2.3)
connection_pool (2.4.1)
drb (2.2.1)
i18n (1.14.5)
concurrent-ruby (~> 1.0)
minitest (5.23.1)
mutex_m (0.2.0)
rrule (0.4.4)
activesupport (>= 2.3)
tzinfo (2.0.6)
concurrent-ruby (~> 1.0)
PLATFORMS
ruby
DEPENDENCIES
rrule (= 0.4.4)
BUNDLED WITH
2.5.9

View File

@@ -0,0 +1,22 @@
{
lib,
mkDiscoursePlugin,
fetchFromGitHub,
}:
mkDiscoursePlugin {
name = "discourse-calendar";
bundlerEnvArgs.gemdir = ./.;
src = fetchFromGitHub {
owner = "discourse";
repo = "discourse-calendar";
rev = "8d09cf8503b78f4c72b47a7319c0f4b9ad0247e7";
sha256 = "sha256-ES0/f/sv4Doao/MOdHYMwadRIVXb1I7FgSsl7790tio=";
};
meta = with lib; {
homepage = "https://github.com/discourse/discourse-calendar";
maintainers = with maintainers; [ ryantm ];
license = licenses.mit;
description = "Adds the ability to create a dynamic calendar in the first post of a topic";
};
}

View File

@@ -0,0 +1,126 @@
{
activesupport = {
dependencies = [
"base64"
"bigdecimal"
"concurrent-ruby"
"connection_pool"
"drb"
"i18n"
"minitest"
"mutex_m"
"tzinfo"
];
groups = [ "default" ];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "0z8kygxmz99krz9pwp947znkzf0jr64sml28df0vf1gzxlg7y57i";
type = "gem";
};
version = "7.1.3.3";
};
base64 = {
groups = [ "default" ];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "01qml0yilb9basf7is2614skjp8384h2pycfx86cr8023arfj98g";
type = "gem";
};
version = "0.2.0";
};
bigdecimal = {
groups = [ "default" ];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "1gi7zqgmqwi5lizggs1jhc3zlwaqayy9rx2ah80sxy24bbnng558";
type = "gem";
};
version = "3.1.8";
};
concurrent-ruby = {
groups = [ "default" ];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "1qh1b14jwbbj242klkyz5fc7npd4j0mvndz62gajhvl1l3wd7zc2";
type = "gem";
};
version = "1.2.3";
};
connection_pool = {
groups = [ "default" ];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "1x32mcpm2cl5492kd6lbjbaf17qsssmpx9kdyr7z1wcif2cwyh0g";
type = "gem";
};
version = "2.4.1";
};
drb = {
groups = [ "default" ];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "0h5kbj9hvg5hb3c7l425zpds0vb42phvln2knab8nmazg2zp5m79";
type = "gem";
};
version = "2.2.1";
};
i18n = {
dependencies = [ "concurrent-ruby" ];
groups = [ "default" ];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "1ffix518y7976qih9k1lgnc17i3v6yrlh0a3mckpxdb4wc2vrp16";
type = "gem";
};
version = "1.14.5";
};
minitest = {
groups = [ "default" ];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "1gkslxvkhh44s21rbjvka3zsvfxxrf5pcl6f75rv2vyrzzbgis7i";
type = "gem";
};
version = "5.23.1";
};
mutex_m = {
groups = [ "default" ];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "1ma093ayps1m92q845hmpk0dmadicvifkbf05rpq9pifhin0rvxn";
type = "gem";
};
version = "0.2.0";
};
rrule = {
dependencies = [ "activesupport" ];
groups = [ "default" ];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "04h3q0ws0wswqj3mwjyv44yx59d9ima9a820ay9w5bwnlb73syj2";
type = "gem";
};
version = "0.4.4";
};
tzinfo = {
dependencies = [ "concurrent-ruby" ];
groups = [ "default" ];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "16w2g84dzaf3z13gxyzlzbf748kylk5bdgg3n1ipvkvvqy685bwd";
type = "gem";
};
version = "2.0.6";
};
}

View File

@@ -0,0 +1,21 @@
{
lib,
mkDiscoursePlugin,
fetchFromGitHub,
}:
mkDiscoursePlugin {
name = "discourse-canned-replies";
src = fetchFromGitHub {
owner = "discourse";
repo = "discourse-canned-replies";
rev = "732598b6cdc86c74622bb15bfeaebb05611bbc25";
sha256 = "sha256-t0emNsPT8o0ralUedt33ufH0VLl4/12lVBBCnzfdRxE=";
};
meta = with lib; {
homepage = "https://github.com/discourse/discourse-canned-replies";
maintainers = with maintainers; [ talyz ];
license = licenses.gpl2Only;
description = "Adds support for inserting a canned reply into the composer window via a UI";
};
}

View File

@@ -0,0 +1,21 @@
{
lib,
mkDiscoursePlugin,
fetchFromGitHub,
}:
mkDiscoursePlugin {
name = "discourse-chat-integration";
src = fetchFromGitHub {
owner = "discourse";
repo = "discourse-chat-integration";
rev = "29ad813cd04812786780e1706cbc043810dea7d8";
sha256 = "sha256-5mGnHLlw3qIGi8et3WV1RXnrPB+bySi3wQryKTa5wNg=";
};
meta = with lib; {
homepage = "https://github.com/discourse/discourse-chat-integration";
maintainers = with maintainers; [ dpausp ];
license = licenses.mit;
description = "This plugin integrates Discourse with a number of external chatroom systems";
};
}

View File

@@ -0,0 +1,21 @@
{
lib,
mkDiscoursePlugin,
fetchFromGitHub,
}:
mkDiscoursePlugin {
name = "discourse-checklist";
src = fetchFromGitHub {
owner = "discourse";
repo = "discourse-checklist";
rev = "6fcf9fed5c3ae3baf9ddd1cca9cef4dc089996c1";
sha256 = "sha256-RIuoqZo7dW1DXbfbWhyyhCOGe4R5sLerzFW2TT0zO6U=";
};
meta = with lib; {
homepage = "https://github.com/discourse/discourse-checklist";
maintainers = with maintainers; [ ryantm ];
license = licenses.gpl2Only;
description = "Simple checklist rendering plugin for discourse";
};
}

View File

@@ -0,0 +1,21 @@
{
lib,
mkDiscoursePlugin,
fetchFromGitHub,
}:
mkDiscoursePlugin {
name = "discourse-data-explorer";
src = fetchFromGitHub {
owner = "discourse";
repo = "discourse-data-explorer";
rev = "2ba204a1de2638a7959e588b88f3b6c7fcf7a70f";
sha256 = "sha256-u8yGKANEyqm63/ZnJLe3u1nkNGZyX0wFUBIKU5GgjzY=";
};
meta = with lib; {
homepage = "https://github.com/discourse/discourse-data-explorer";
maintainers = with maintainers; [ ryantm ];
license = licenses.mit;
description = "SQL Queries for admins in Discourse";
};
}

View File

@@ -0,0 +1,21 @@
{
lib,
mkDiscoursePlugin,
fetchFromGitHub,
}:
mkDiscoursePlugin {
name = "discourse-docs";
src = fetchFromGitHub {
owner = "discourse";
repo = "discourse-docs";
rev = "4e42539cda9a54d7827bcdf51b6dfbcf56d24cc9";
sha256 = "sha256-sv9Q0qEQVncQw3QLiro5YfVcHJAG8sJ0GTjduCZ0iP4=";
};
meta = with lib; {
homepage = "https://github.com/discourse/discourse-docs";
maintainers = with maintainers; [ dpausp ];
license = licenses.mit;
description = "Find and filter knowledge base topics";
};
}

View File

@@ -0,0 +1,7 @@
# frozen_string_literal: true
source "https://rubygems.org"
# gem "rails"
gem "sawyer", "0.9.2"
gem "octokit", "5.6.1"

View File

@@ -0,0 +1,33 @@
GEM
remote: https://rubygems.org/
specs:
addressable (2.8.7)
public_suffix (>= 2.0.2, < 7.0)
faraday (2.12.3)
faraday-net_http (>= 2.0, < 3.5)
json
logger
faraday-net_http (3.4.0)
net-http (>= 0.5.0)
json (2.10.2)
logger (1.7.0)
net-http (0.6.0)
uri
octokit (5.6.1)
faraday (>= 1, < 3)
sawyer (~> 0.9)
public_suffix (6.0.1)
sawyer (0.9.2)
addressable (>= 2.3.5)
faraday (>= 0.17.3, < 3)
uri (1.0.3)
PLATFORMS
ruby
DEPENDENCIES
octokit (= 5.6.1)
sawyer (= 0.9.2)
BUNDLED WITH
2.5.22

View File

@@ -0,0 +1,23 @@
{
lib,
mkDiscoursePlugin,
fetchFromGitHub,
}:
mkDiscoursePlugin {
name = "discourse-github";
bundlerEnvArgs.gemdir = ./.;
src = fetchFromGitHub {
owner = "discourse";
repo = "discourse-github";
rev = "59e5fc5692959c6c564ab0e09de364ccfedd6702";
sha256 = "sha256-b+8eSw8Kbz2CZN16Rd7c8uyH5P1iYhOJmdXu1C5UclU=";
};
meta = with lib; {
homepage = "https://github.com/discourse/discourse-github";
maintainers = with maintainers; [ talyz ];
license = licenses.mit;
description = "Adds GitHub badges and linkback functionality";
};
}

View File

@@ -0,0 +1,118 @@
{
addressable = {
dependencies = [ "public_suffix" ];
groups = [ "default" ];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "0cl2qpvwiffym62z991ynks7imsm87qmgxf0yfsmlwzkgi9qcaa6";
type = "gem";
};
version = "2.8.7";
};
faraday = {
dependencies = [
"faraday-net_http"
"json"
"logger"
];
groups = [ "default" ];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "0dxalpc0ldvjjmd7z95na9lm99d2baz48sf9axk3a6x3pn50ibdi";
type = "gem";
};
version = "2.12.3";
};
faraday-net_http = {
dependencies = [ "net-http" ];
groups = [ "default" ];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "0jp5ci6g40d6i50bsywp35l97nc2fpi9a592r2cibwicdb6y9wd1";
type = "gem";
};
version = "3.4.0";
};
json = {
groups = [ "default" ];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "01lbdaizhkxmrw4y8j3wpvsryvnvzmg0pfs56c52laq2jgdfmq1l";
type = "gem";
};
version = "2.10.2";
};
logger = {
groups = [ "default" ];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "00q2zznygpbls8asz5knjvvj2brr3ghmqxgr83xnrdj4rk3xwvhr";
type = "gem";
};
version = "1.7.0";
};
net-http = {
dependencies = [ "uri" ];
groups = [ "default" ];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "1ysrwaabhf0sn24jrp0nnp51cdv0jf688mh5i6fsz63q2c6b48cn";
type = "gem";
};
version = "0.6.0";
};
octokit = {
dependencies = [
"faraday"
"sawyer"
];
groups = [ "default" ];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "15g4kyag6gmxxq6d03472h7srm3imlsks1wg6nac7hl3mb1b5vs8";
type = "gem";
};
version = "5.6.1";
};
public_suffix = {
groups = [ "default" ];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "0vqcw3iwby3yc6avs1vb3gfd0vcp2v7q310665dvxfswmcf4xm31";
type = "gem";
};
version = "6.0.1";
};
sawyer = {
dependencies = [
"addressable"
"faraday"
];
groups = [ "default" ];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "1jks1qjbmqm8f9kvwa81vqj39avaj9wdnzc531xm29a55bb74fps";
type = "gem";
};
version = "0.9.2";
};
uri = {
groups = [ "default" ];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "04bhfvc25b07jaiaf62yrach7khhr5jlr5bx6nygg8pf11329wp9";
type = "gem";
};
version = "1.0.3";
};
}

View File

@@ -0,0 +1,8 @@
# frozen_string_literal: true
source "https://rubygems.org"
# gem "rails"
gem 'pyu-ruby-sasl', '0.0.3.3', require: false
gem 'rubyntlm', '0.3.4', require: false
gem 'net-ldap', '0.18.0'

View File

@@ -0,0 +1,17 @@
GEM
remote: https://rubygems.org/
specs:
net-ldap (0.18.0)
pyu-ruby-sasl (0.0.3.3)
rubyntlm (0.3.4)
PLATFORMS
ruby
DEPENDENCIES
net-ldap (= 0.18.0)
pyu-ruby-sasl (= 0.0.3.3)
rubyntlm (= 0.3.4)
BUNDLED WITH
2.5.22

View File

@@ -0,0 +1,22 @@
{
lib,
mkDiscoursePlugin,
fetchFromGitHub,
}:
mkDiscoursePlugin {
name = "discourse-ldap-auth";
bundlerEnvArgs.gemdir = ./.;
src = fetchFromGitHub {
owner = "jonmbake";
repo = "discourse-ldap-auth";
rev = "fa1d661004ca99036ff628a9c4be12a81265d784";
sha256 = "sha256-2DYrYgC3H+e8USoo1MbJin1f5tshIUsQa6J7avnpvEc=";
};
meta = with lib; {
homepage = "https://github.com/jonmbake/discourse-ldap-auth";
maintainers = with maintainers; [ ryantm ];
license = licenses.mit;
description = "Discourse plugin to enable LDAP/Active Directory authentication";
};
}

View File

@@ -0,0 +1,32 @@
{
net-ldap = {
groups = [ "default" ];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "0xqcffn3c1564c4fizp10dzw2v5g2pabdzrcn25hq05bqhsckbar";
type = "gem";
};
version = "0.18.0";
};
pyu-ruby-sasl = {
groups = [ "default" ];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "1rcpjiz9lrvyb3rd8k8qni0v4ps08psympffyldmmnrqayyad0sn";
type = "gem";
};
version = "0.0.3.3";
};
rubyntlm = {
groups = [ "default" ];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "18d1lxhx62swggf4cqg76h7hp04f5801c8h07w08cm9xng2niqby";
type = "gem";
};
version = "0.3.4";
};
}

View File

@@ -0,0 +1,21 @@
{
lib,
mkDiscoursePlugin,
fetchFromGitHub,
}:
mkDiscoursePlugin {
name = "discourse-math";
src = fetchFromGitHub {
owner = "discourse";
repo = "discourse-math";
rev = "90a56a5b463546cba5017cf25168bae759bcbf77";
sha256 = "sha256-q8cNRIHYEkaE6QkdsHu4tPwSw3LnCNgKjbyESBXheE0=";
};
meta = with lib; {
homepage = "https://github.com/discourse/discourse-math";
maintainers = with maintainers; [ talyz ];
license = licenses.mit;
description = "Official MathJax support for Discourse";
};
}

View File

@@ -0,0 +1,9 @@
# frozen_string_literal: true
source "https://rubygems.org"
# gem "rails"
gem 'bcrypt', '3.1.13'
gem 'unix-crypt', '1.3.0'
gem 'ffi-compiler', '1.0.1', require: false
gem 'argon2', '2.2.0'

View File

@@ -0,0 +1,25 @@
GEM
remote: https://rubygems.org/
specs:
argon2 (2.2.0)
ffi (~> 1.15)
ffi-compiler (~> 1.0)
bcrypt (3.1.13)
ffi (1.17.0)
ffi-compiler (1.0.1)
ffi (>= 1.0.0)
rake
rake (13.2.1)
unix-crypt (1.3.0)
PLATFORMS
ruby
DEPENDENCIES
argon2 (= 2.2.0)
bcrypt (= 3.1.13)
ffi-compiler (= 1.0.1)
unix-crypt (= 1.3.0)
BUNDLED WITH
2.5.11

View File

@@ -0,0 +1,22 @@
{
lib,
mkDiscoursePlugin,
fetchFromGitHub,
}:
mkDiscoursePlugin {
name = "discourse-migratepassword";
bundlerEnvArgs.gemdir = ./.;
src = fetchFromGitHub {
owner = "communiteq";
repo = "discourse-migratepassword";
rev = "a732ae244cd4125561fd225a67bae95ef5f738d0";
sha256 = "sha256-EO+QnFTy3PgxZ92DZBm9sP8sFAny3ZpFw+faTX32j7Q=";
};
meta = with lib; {
homepage = "https://github.com/communiteq/discourse-migratepassword";
maintainers = with maintainers; [ ryantm ];
license = licenses.gpl2Only;
description = "Support migrated password hashes";
};
}

View File

@@ -0,0 +1,70 @@
{
argon2 = {
dependencies = [
"ffi"
"ffi-compiler"
];
groups = [ "default" ];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "1wdllcqlr81nzyf485ldv1p660xsi476p79ghbj7zsf3n9n86gwd";
type = "gem";
};
version = "2.2.0";
};
bcrypt = {
groups = [ "default" ];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "0ai0m15jg3n0b22mimk09ppnga316dc7dyvz06w8rrqh5gy1lslp";
type = "gem";
};
version = "3.1.13";
};
ffi = {
groups = [ "default" ];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "07139870npj59jnl8vmk39ja3gdk3fb5z9vc0lf32y2h891hwqsi";
type = "gem";
};
version = "1.17.0";
};
ffi-compiler = {
dependencies = [
"ffi"
"rake"
];
groups = [ "default" ];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "0c2caqm9wqnbidcb8dj4wd3s902z15qmgxplwyfyqbwa0ydki7q1";
type = "gem";
};
version = "1.0.1";
};
rake = {
groups = [ "default" ];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "17850wcwkgi30p7yqh60960ypn7yibacjjha0av78zaxwvd3ijs6";
type = "gem";
};
version = "13.2.1";
};
unix-crypt = {
groups = [ "default" ];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "1wflipsmmicmgvqilp9pml4x19b337kh6p6jgrzqrzpkq2z52gdq";
type = "gem";
};
version = "1.3.0";
};
}

View File

@@ -0,0 +1,7 @@
# frozen_string_literal: true
source 'https://rubygems.org'
group :development do
gem 'rubocop-discourse'
end

View File

@@ -0,0 +1,37 @@
GEM
remote: https://rubygems.org/
specs:
ast (2.4.2)
parallel (1.22.1)
parser (3.1.1.0)
ast (~> 2.4.1)
rainbow (3.1.1)
regexp_parser (2.2.1)
rexml (3.2.5)
rubocop (1.26.1)
parallel (~> 1.10)
parser (>= 3.1.0.0)
rainbow (>= 2.2.2, < 4.0)
regexp_parser (>= 1.8, < 3.0)
rexml
rubocop-ast (>= 1.16.0, < 2.0)
ruby-progressbar (~> 1.7)
unicode-display_width (>= 1.4.0, < 3.0)
rubocop-ast (1.16.0)
parser (>= 3.1.1.0)
rubocop-discourse (2.5.0)
rubocop (>= 1.1.0)
rubocop-rspec (>= 2.0.0)
rubocop-rspec (2.9.0)
rubocop (~> 1.19)
ruby-progressbar (1.11.0)
unicode-display_width (2.1.0)
PLATFORMS
ruby
DEPENDENCIES
rubocop-discourse
BUNDLED WITH
2.1.4

View File

@@ -0,0 +1,21 @@
{
lib,
mkDiscoursePlugin,
fetchFromGitHub,
}:
mkDiscoursePlugin rec {
name = "discourse-oauth2-basic";
bundlerEnvArgs.gemdir = ./.;
src = fetchFromGitHub {
owner = "discourse";
repo = name;
rev = "06ba5daa9aabd0487f2f30b944b6500f1f481308";
sha256 = "sha256-T08Q36k2hb9wVimKIa4O5mWcrr6VBTfHvhRJiLBiRPY=";
};
meta = with lib; {
homepage = "https://github.com/discourse/${name}";
license = licenses.mit;
description = "Basic OAuth2 plugin for use with Discourse";
};
}

View File

@@ -0,0 +1,172 @@
{
ast = {
groups = [
"default"
"development"
];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "04nc8x27hlzlrr5c2gn7mar4vdr0apw5xg22wp6m8dx3wqr04a0y";
type = "gem";
};
version = "2.4.2";
};
parallel = {
groups = [
"default"
"development"
];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "07vnk6bb54k4yc06xnwck7php50l09vvlw1ga8wdz0pia461zpzb";
type = "gem";
};
version = "1.22.1";
};
parser = {
dependencies = [ "ast" ];
groups = [
"default"
"development"
];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "0zaghgvva2q4jqbachg8jvpwgbg3w1jqr0d00m8rqciqznjgsw3c";
type = "gem";
};
version = "3.1.1.0";
};
rainbow = {
groups = [
"default"
"development"
];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "0smwg4mii0fm38pyb5fddbmrdpifwv22zv3d3px2xx497am93503";
type = "gem";
};
version = "3.1.1";
};
regexp_parser = {
groups = [
"default"
"development"
];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "155f6cr4rrfw5bs5xd3m5kfw32qhc5fsi4nk82rhif56rc6cs0wm";
type = "gem";
};
version = "2.2.1";
};
rexml = {
groups = [
"default"
"development"
];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "08ximcyfjy94pm1rhcx04ny1vx2sk0x4y185gzn86yfsbzwkng53";
type = "gem";
};
version = "3.2.5";
};
rubocop = {
dependencies = [
"parallel"
"parser"
"rainbow"
"regexp_parser"
"rexml"
"rubocop-ast"
"ruby-progressbar"
"unicode-display_width"
];
groups = [
"default"
"development"
];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "06105yrqajpm5l07fng1nbk55y9490hny542zclnan8hg841pjgl";
type = "gem";
};
version = "1.26.1";
};
rubocop-ast = {
dependencies = [ "parser" ];
groups = [
"default"
"development"
];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "1bd2z82ly7fix8415gvfiwzb6bjialz5rs3sr72kv1lk68rd23wv";
type = "gem";
};
version = "1.16.0";
};
rubocop-discourse = {
dependencies = [
"rubocop"
"rubocop-rspec"
];
groups = [ "development" ];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "01f4y7am9cq276zl8vsgv64w8wfmhpbzg7vzsifhgnnh92g6s04g";
type = "gem";
};
version = "2.5.0";
};
rubocop-rspec = {
dependencies = [ "rubocop" ];
groups = [
"default"
"development"
];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "051gq9pz49iv4gq34d3n089iaa6cb418n2fhin6gd6fpysbi3nf6";
type = "gem";
};
version = "2.9.0";
};
ruby-progressbar = {
groups = [
"default"
"development"
];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "02nmaw7yx9kl7rbaan5pl8x5nn0y4j5954mzrkzi9i3dhsrps4nc";
type = "gem";
};
version = "1.11.0";
};
unicode-display_width = {
groups = [
"default"
"development"
];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "0csjm9shhfik0ci9mgimb7hf3xgh7nx45rkd9rzgdz6vkwr8rzxn";
type = "gem";
};
version = "2.1.0";
};
}

View File

@@ -0,0 +1,7 @@
# frozen_string_literal: true
source 'https://rubygems.org'
group :development do
gem 'rubocop-discourse'
end

View File

@@ -0,0 +1,37 @@
GEM
remote: https://rubygems.org/
specs:
ast (2.4.1)
parallel (1.19.2)
parser (2.7.2.0)
ast (~> 2.4.1)
rainbow (3.0.0)
regexp_parser (1.8.1)
rexml (3.2.5)
rubocop (0.93.0)
parallel (~> 1.10)
parser (>= 2.7.1.5)
rainbow (>= 2.2.2, < 4.0)
regexp_parser (>= 1.8)
rexml
rubocop-ast (>= 0.6.0)
ruby-progressbar (~> 1.7)
unicode-display_width (>= 1.4.0, < 2.0)
rubocop-ast (0.7.1)
parser (>= 2.7.1.5)
rubocop-discourse (2.3.2)
rubocop (>= 0.69.0)
rubocop-rspec (>= 1.39.0)
rubocop-rspec (1.43.2)
rubocop (~> 0.87)
ruby-progressbar (1.10.1)
unicode-display_width (1.7.0)
PLATFORMS
ruby
DEPENDENCIES
rubocop-discourse
BUNDLED WITH
2.1.4

View File

@@ -0,0 +1,22 @@
{
lib,
mkDiscoursePlugin,
fetchFromGitHub,
}:
mkDiscoursePlugin {
name = "discourse-openid-connect";
bundlerEnvArgs.gemdir = ./.;
src = fetchFromGitHub {
owner = "discourse";
repo = "discourse-openid-connect";
rev = "e08efecc012a5ab8fa95084be93d4fd07ccebab9";
sha256 = "sha256-v4UWFDdOFON+nHkH490kBQ4sXX7Mrp7KVhN1x9HML7w=";
};
meta = with lib; {
homepage = "https://github.com/discourse/discourse-openid-connect";
maintainers = with maintainers; [ mkg20001 ];
license = licenses.mit;
description = "Discourse plugin to integrate Discourse with an openid-connect login provider";
};
}

View File

@@ -0,0 +1,172 @@
{
ast = {
groups = [
"default"
"development"
];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "1l3468czzjmxl93ap40hp7z94yxp4nbag0bxqs789bm30md90m2a";
type = "gem";
};
version = "2.4.1";
};
parallel = {
groups = [
"default"
"development"
];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "17b127xxmm2yqdz146qwbs57046kn0js1h8synv01dwqz2z1kp2l";
type = "gem";
};
version = "1.19.2";
};
parser = {
dependencies = [ "ast" ];
groups = [
"default"
"development"
];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "1f7gmm60yla325wlnd3qkxs59qm2y0aan8ljpg6k18rwzrrfil6z";
type = "gem";
};
version = "2.7.2.0";
};
rainbow = {
groups = [
"default"
"development"
];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "0bb2fpjspydr6x0s8pn1pqkzmxszvkfapv0p4627mywl7ky4zkhk";
type = "gem";
};
version = "3.0.0";
};
regexp_parser = {
groups = [
"default"
"development"
];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "0n9d14ppshnx71i3mi1pnm3hwhcbb6m6vsc0b0dqgsab8r2rs96n";
type = "gem";
};
version = "1.8.1";
};
rexml = {
groups = [
"default"
"development"
];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "08ximcyfjy94pm1rhcx04ny1vx2sk0x4y185gzn86yfsbzwkng53";
type = "gem";
};
version = "3.2.5";
};
rubocop = {
dependencies = [
"parallel"
"parser"
"rainbow"
"regexp_parser"
"rexml"
"rubocop-ast"
"ruby-progressbar"
"unicode-display_width"
];
groups = [
"default"
"development"
];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "1nrv7i81549addig09grw17qkab3l4319dcsf9y7psl7aa76ng3a";
type = "gem";
};
version = "0.93.0";
};
rubocop-ast = {
dependencies = [ "parser" ];
groups = [
"default"
"development"
];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "129hgz4swc8n0g01715v7y00k0h4mlzkxh63q7z27q7mjp54rl74";
type = "gem";
};
version = "0.7.1";
};
rubocop-discourse = {
dependencies = [
"rubocop"
"rubocop-rspec"
];
groups = [ "development" ];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "10l2wwnvd4xccgqsyhxrhc5bw10b7an4awl0v90fw5xf2qdjiflw";
type = "gem";
};
version = "2.3.2";
};
rubocop-rspec = {
dependencies = [ "rubocop" ];
groups = [
"default"
"development"
];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "1sc0bwdxzfr8byxzwvfyf22lwzqcaa6ca7wzxx31mk7vvy7r7dhl";
type = "gem";
};
version = "1.43.2";
};
ruby-progressbar = {
groups = [
"default"
"development"
];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "1k77i0d4wsn23ggdd2msrcwfy0i376cglfqypkk2q77r2l3408zf";
type = "gem";
};
version = "1.10.1";
};
unicode-display_width = {
groups = [
"default"
"development"
];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "06i3id27s60141x6fdnjn5rar1cywdwy64ilc59cz937303q3mna";
type = "gem";
};
version = "1.7.0";
};
}

View File

@@ -0,0 +1,6 @@
# frozen_string_literal: true
source "https://rubygems.org"
# gem "rails"
gem "prometheus_exporter", "2.2.0"

View File

@@ -0,0 +1,15 @@
GEM
remote: https://rubygems.org/
specs:
prometheus_exporter (2.2.0)
webrick
webrick (1.9.1)
PLATFORMS
ruby
DEPENDENCIES
prometheus_exporter (= 2.2.0)
BUNDLED WITH
2.5.22

View File

@@ -0,0 +1,30 @@
{
lib,
mkDiscoursePlugin,
fetchFromGitHub,
}:
mkDiscoursePlugin {
bundlerEnvArgs.gemdir = ./.;
name = "discourse-prometheus";
src = fetchFromGitHub {
owner = "discourse";
repo = "discourse-prometheus";
rev = "f46906e1d555f6838d74ea38d5037264cc1020b0";
sha256 = "sha256-czrxhH0L+vCZA8DKN6acW///iWJs9GIppEeaP2MOJBQ=";
};
patches = [
# The metrics collector tries to run git to get the commit id but fails
# because we don't run Discourse from a Git repository.
./no-git-version.patch
./spec-import-fix-abi-version.patch
];
meta = with lib; {
homepage = "https://github.com/discourse/discourse-prometheus";
maintainers = with maintainers; [ dpausp ];
license = licenses.mit;
description = "Official Discourse Plugin for Prometheus Monitoring";
};
}

View File

@@ -0,0 +1,23 @@
{
prometheus_exporter = {
dependencies = [ "webrick" ];
groups = [ "default" ];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "15vl8fw8vjnaj9g129dzrwk9nlrdqgffaj3rys4ba9ns2bqim9rq";
type = "gem";
};
version = "2.2.0";
};
webrick = {
groups = [ "default" ];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "12d9n8hll67j737ym2zw4v23cn4vxyfkb6vyv1rzpwv6y6a3qbdl";
type = "gem";
};
version = "1.9.1";
};
}

View File

@@ -0,0 +1,34 @@
diff --git a/lib/internal_metric/global.rb b/lib/internal_metric/global.rb
index 682571b..7bdd431 100644
--- a/lib/internal_metric/global.rb
+++ b/lib/internal_metric/global.rb
@@ -30,28 +30,7 @@ module DiscoursePrometheus::InternalMetric
@active_app_reqs = 0
@queued_app_reqs = 0
@fault_logged = {}
-
- begin
- @@version = nil
-
- out, error, status = Open3.capture3("git rev-parse HEAD")
-
- if status.success?
- @@version ||= out.chomp
- else
- raise error
- end
- rescue => e
- if defined?(::Discourse)
- Discourse.warn_exception(e, message: "Failed to calculate discourse_version_info metric")
- else
- STDERR.puts "Failed to calculate discourse_version_info metric: #{e}\n#{e.backtrace.join("\n")}"
- end
-
- @@retries ||= 10
- @@retries -= 1
- @@version = -1 if @@retries < 0
- end
+ @@version = -1
end
def collect

View File

@@ -0,0 +1,16 @@
diff --git a/bin/collector b/bin/collector
index 4bdce08178..5edc0a4aee 100755
--- a/bin/collector
+++ b/bin/collector
@@ -3,9 +3,11 @@
Process.setproctitle("discourse prometheus-collector")
+# We need the ABI version {MAJOR}.{MINOR}.0 here.
+abi_version = ENV['GEM_PATH'].split("/")[-1]
spec_file =
File.expand_path(
- "../../gems/#{RUBY_VERSION}/specifications/#{"prometheus_exporter-#{ENV["PROMETHEUS_EXPORTER_VERSION"]}"}.gemspec",
+ "../../gems/#{abi_version}/specifications/#{"prometheus_exporter-#{ENV["PROMETHEUS_EXPORTER_VERSION"]}"}.gemspec",
__FILE__,
)

View File

@@ -0,0 +1,21 @@
{
lib,
mkDiscoursePlugin,
fetchFromGitHub,
}:
mkDiscoursePlugin {
name = "discourse-reactions";
src = fetchFromGitHub {
owner = "discourse";
repo = "discourse-reactions";
rev = "f87583d9054421869ba0de16c24ad15e32bbebe7";
sha256 = "sha256-v2AkpSTF3VNgBUfvRMQ3BCw0nClWjcVTdKNn9yiByBM=";
};
meta = with lib; {
homepage = "https://github.com/discourse/discourse-reactions";
maintainers = with maintainers; [ bbenno ];
license = licenses.mit;
description = "Allows users to react to a post from a choice of emojis, rather than only the like heart";
};
}

View File

@@ -0,0 +1,21 @@
{
lib,
mkDiscoursePlugin,
fetchFromGitHub,
}:
mkDiscoursePlugin {
name = "discourse-saved-searches";
src = fetchFromGitHub {
owner = "discourse";
repo = "discourse-saved-searches";
rev = "b78aae086e95255b1a1e91a01e2d56b45b7aead2";
sha256 = "sha256-Wai+oZR+Pzjre6Th0kQDgvFOwfPRHlZkpKYYOUKNlx4=";
};
meta = with lib; {
homepage = "https://github.com/discourse/discourse-saved-searches";
maintainers = with maintainers; [ dpausp ];
license = licenses.mit;
description = "Allow users to save searches and be notified of new results";
};
}

View File

@@ -0,0 +1,21 @@
{
lib,
mkDiscoursePlugin,
fetchFromGitHub,
}:
mkDiscoursePlugin {
name = "discourse-solved";
src = fetchFromGitHub {
owner = "discourse";
repo = "discourse-solved";
rev = "e82c6ae1ca38ccebb34669148f8de93a3028906e";
sha256 = "sha256-KwpBCk4fjkZlSzgtc0OXvQupPd+aPb9nONyyALpEZhg=";
};
meta = with lib; {
homepage = "https://github.com/discourse/discourse-solved";
maintainers = with maintainers; [ talyz ];
license = licenses.mit;
description = "Allow accepted answers on topics";
};
}

View File

@@ -0,0 +1,21 @@
{
lib,
mkDiscoursePlugin,
fetchFromGitHub,
}:
mkDiscoursePlugin {
name = "discourse-spoiler-alert";
src = fetchFromGitHub {
owner = "discourse";
repo = "discourse-spoiler-alert";
rev = "42b77ec048b9b386a8b25a22bfec6472817da465";
sha256 = "sha256-BQeID+y9RvmcnuNsodOMXseVvre5QYxv+E/ul8bucUI=";
};
meta = with lib; {
homepage = "https://github.com/discourse/discourse-spoiler-alert";
maintainers = with maintainers; [ talyz ];
license = licenses.mit;
description = "Hide spoilers behind the spoiler-alert jQuery plugin";
};
}

View File

@@ -0,0 +1,21 @@
{
lib,
mkDiscoursePlugin,
fetchFromGitHub,
}:
mkDiscoursePlugin {
name = "discourse-voting";
src = fetchFromGitHub {
owner = "discourse";
repo = "discourse-topic-voting";
rev = "d779202749e56aaee2d548b538796fb5db1b9b7c";
sha256 = "sha256-8YF7W5SXhI7TGJNZkx5or7bxI0MKiDtx10TE2ekBMuM=";
};
meta = with lib; {
homepage = "https://github.com/discourse/discourse-voting";
maintainers = with maintainers; [ dpausp ];
license = licenses.gpl2Only;
description = "Adds the ability for voting on a topic within a specified category in Discourse";
};
}

View File

@@ -0,0 +1,21 @@
{
lib,
mkDiscoursePlugin,
fetchFromGitHub,
}:
mkDiscoursePlugin {
name = "discourse-yearly-review";
src = fetchFromGitHub {
owner = "discourse";
repo = "discourse-yearly-review";
rev = "439e0d78f1d8a0f387c0ec26f233a090ce82ef72";
sha256 = "sha256-DXA5P7XnItBjP4H1J/G1cGbFddSDZh0wjMZiJ5JA9s8=";
};
meta = with lib; {
homepage = "https://github.com/discourse/discourse-yearly-review";
maintainers = with maintainers; [ talyz ];
license = licenses.mit;
description = "Publishes an automated Year in Review topic";
};
}

View File

@@ -0,0 +1,23 @@
diff --git a/lib/discourse_js_processor.rb b/lib/discourse_js_processor.rb
index f1642386c5..5a672818da 100644
--- a/lib/discourse_js_processor.rb
+++ b/lib/discourse_js_processor.rb
@@ -54,7 +54,7 @@ class DiscourseJsProcessor
end
class Transpiler
- TRANSPILER_PATH = "tmp/theme-transpiler.js"
+ TRANSPILER_PATH = "app/assets/javascripts/theme-transpiler.js"
@mutex = Mutex.new
@ctx_init = Mutex.new
@@ -75,7 +75,9 @@ class DiscourseJsProcessor
end
def self.build_production_theme_transpiler
- File.write(TRANSPILER_PATH, build_theme_transpiler)
+ if (!Rails.env.production? or !File.file?(TRANSPILER_PATH))
+ File.write(TRANSPILER_PATH, build_theme_transpiler)
+ end
TRANSPILER_PATH
end

View File

@@ -0,0 +1,294 @@
# frozen_string_literal: true
source "https://rubygems.org"
# if there is a super emergency and rubygems is playing up, try
#source 'http://production.cf.rubygems.org'
gem "bootsnap", require: false, platform: :mri
gem "actionmailer", "~> 7.2.0"
gem "actionpack", "~> 7.2.0"
gem "actionview", "~> 7.2.0"
gem "activemodel", "~> 7.2.0"
gem "activerecord", "~> 7.2.0"
gem "activesupport", "~> 7.2.0"
gem "railties", "~> 7.2.0"
gem "sprockets-rails"
gem "json"
# TODO: At the moment Discourse does not work with Sprockets 4, we would need to correct internals
# We intend to drop sprockets rather than upgrade to 4.x
gem "sprockets", "~> 3.7.3"
# this will eventually be added to rails,
# allows us to precompile all our templates in the unicorn master
gem "actionview_precompiler", require: false
gem "discourse-seed-fu"
gem "mail"
gem "mini_mime"
gem "mini_suffix"
# config/initializers/006-mini_profiler.rb depends upon the RedisClient#call.
# Rework this when upgrading to redis client 5.0 and above.
gem "redis", "< 5.0"
# This is explicitly used by Sidekiq and is an optional dependency.
# We tell Sidekiq to use the namespace "sidekiq" which triggers this
# gem to be used. There is no explicit dependency in sidekiq cause
# redis namespace support is optional
# We already namespace stuff in DiscourseRedis, so we should consider
# just using a single implementation in core vs having 2 namespace implementations
gem "redis-namespace"
# NOTE: AM serializer gets a lot slower with recent updates
# we used an old branch which is the fastest one out there
# are long term goal here is to fork this gem so we have a
# better maintained living fork
gem "active_model_serializers", "~> 0.8.3"
gem "http_accept_language", require: false
gem "discourse-fonts", require: "discourse_fonts"
gem "message_bus"
gem "rails_multisite"
gem "fastimage"
gem "aws-sdk-s3", require: false
gem "aws-sdk-sns", require: false
gem "excon", require: false
gem "unf", require: false
gem "email_reply_trimmer"
gem "image_optim"
gem "multi_json"
gem "mustache"
gem "nokogiri"
gem "loofah"
gem "css_parser", require: false
gem "omniauth"
gem "omniauth-facebook"
gem "omniauth-twitter"
gem "omniauth-github"
gem "omniauth-oauth2", require: false
gem "omniauth-google-oauth2"
gem "oj"
gem "pg"
gem "mini_sql"
gem "pry-rails", require: false
gem "pry-byebug", require: false
gem "rtlcss", require: false
gem "messageformat-wrapper", require: false
gem "rake"
gem "thor", require: false
gem "diffy", require: false
gem "rinku"
gem "sidekiq"
gem "mini_scheduler"
gem "execjs", require: false
gem "mini_racer", "0.17.pre13"
gem "highline", require: false
gem "rack"
gem "rack-protection" # security
gem "cbor", require: false
gem "cose", require: false
gem "addressable"
gem "json_schemer"
gem "net-smtp", require: false
gem "net-imap", require: false
gem "net-pop", require: false
gem "digest", require: false
# Gems used only for assets and not required in production environments by default.
# Allow everywhere for now cause we are allowing asset debugging in production
group :assets do
gem "uglifier"
end
group :test do
gem "capybara", require: false
gem "webmock", require: false
gem "fakeweb", require: false
gem "simplecov", require: false
gem "selenium-webdriver", "~> 4.14", require: false
gem "selenium-devtools", require: false
gem "test-prof"
gem "rails-dom-testing", require: false
gem "minio_runner", require: false
end
group :test, :development do
gem "rspec"
gem "listen", require: false
gem "certified", require: false
gem "fabrication", require: false
gem "mocha", require: false
gem "rb-fsevent", require: RUBY_PLATFORM =~ /darwin/i ? "rb-fsevent" : false
gem "rspec-rails"
gem "shoulda-matchers", require: false
gem "rspec-html-matchers"
gem "pry-stack_explorer", require: false
gem "byebug", require: ENV["RM_INFO"].nil?, platform: :mri
gem "rubocop-discourse", require: false
gem "parallel_tests"
gem "rswag-specs"
gem "annotate"
gem "syntax_tree"
gem "syntax_tree-disable_ternary"
gem "rspec-multi-mock"
end
group :development do
gem "ruby-prof", require: false, platform: :mri
gem "bullet", require: !!ENV["BULLET"]
gem "better_errors", platform: :mri, require: !!ENV["BETTER_ERRORS"]
gem "binding_of_caller"
gem "yaml-lint"
gem "yard"
end
if ENV["ALLOW_DEV_POPULATE"] == "1"
gem "discourse_dev_assets"
gem "faker", "~> 2.16"
else
group :development, :test do
gem "discourse_dev_assets"
gem "faker", "~> 2.16"
end
end
# this is an optional gem, it provides a high performance replacement
# to String#blank? a method that is called quite frequently in current
# ActiveRecord, this may change in the future
gem "fast_blank", platform: :ruby
# this provides a very efficient lru cache
gem "lru_redux"
gem "htmlentities", require: false
# IMPORTANT: mini profiler monkey patches, so it better be required last
# If you want to amend mini profiler to do the monkey patches in the railties
# we are open to it. by deferring require to the initializer we can configure discourse installs without it
gem "rack-mini-profiler", require: ["enable_rails_patches"]
gem "unicorn", require: false, platform: :ruby
gem "puma", require: false
gem "rbtrace", require: false, platform: :mri
# required for feed importing and embedding
gem "ruby-readability", require: false
# rss gem is a bundled gem from Ruby 3 onwards
gem "rss", require: false
gem "stackprof", require: false, platform: :mri
gem "memory_profiler", require: false, platform: :mri
gem "cppjieba_rb", require: false
gem "lograge", require: false
gem "logstash-event", require: false
gem "logster"
# A fork of sassc with dart-sass support
gem "sassc-embedded"
gem "rotp", require: false
gem "rqrcode"
gem "rubyzip", require: false
gem "sshkey", require: false
gem "rchardet", require: false
gem "lz4-ruby", require: false, platform: :ruby
gem "sanitize"
if ENV["IMPORT"] == "1"
gem "mysql2"
gem "redcarpet"
# NOTE: in import mode the version of sqlite can matter a lot, so we stick it to a specific one
gem "sqlite3", "~> 1.3", ">= 1.3.13"
gem "ruby-bbcode-to-md", git: "https://github.com/nlalonde/ruby-bbcode-to-md"
gem "reverse_markdown"
gem "tiny_tds"
gem "csv"
end
group :generic_import, optional: true do
gem "sqlite3"
gem "redcarpet"
end
gem "web-push"
gem "colored2", require: false
gem "maxminddb"
gem "rails_failover", require: false
gem "faraday"
gem "faraday-retry"
# workaround for faraday-net_http, see
# https://github.com/ruby/net-imap/issues/16#issuecomment-803086765
gem "net-http"
# Workaround until Ruby ships with cgi version 0.3.6 or higher.
gem "cgi", ">= 0.3.6", require: false
gem "tzinfo-data"
gem "csv", require: false
# dependencies for the automation plugin
gem "iso8601"
gem "rrule"
group :migrations, optional: true do
gem "extralite-bundle", require: "extralite"
# auto-loading
gem "zeitwerk"
# databases
gem "trilogy"
# CLI
gem "ruby-progressbar"
# non-cryptographic hashing algorithm for generating placeholder IDs
gem "digest-xxhash"
end
gem "dry-initializer", "~> 3.1"
gem "parallel"

View File

@@ -0,0 +1,748 @@
GEM
remote: https://rubygems.org/
specs:
actionmailer (7.2.2.1)
actionpack (= 7.2.2.1)
actionview (= 7.2.2.1)
activejob (= 7.2.2.1)
activesupport (= 7.2.2.1)
mail (>= 2.8.0)
rails-dom-testing (~> 2.2)
actionpack (7.2.2.1)
actionview (= 7.2.2.1)
activesupport (= 7.2.2.1)
nokogiri (>= 1.8.5)
racc
rack (>= 2.2.4, < 3.2)
rack-session (>= 1.0.1)
rack-test (>= 0.6.3)
rails-dom-testing (~> 2.2)
rails-html-sanitizer (~> 1.6)
useragent (~> 0.16)
actionview (7.2.2.1)
activesupport (= 7.2.2.1)
builder (~> 3.1)
erubi (~> 1.11)
rails-dom-testing (~> 2.2)
rails-html-sanitizer (~> 1.6)
actionview_precompiler (0.4.0)
actionview (>= 6.0.a)
active_model_serializers (0.8.4)
activemodel (>= 3.0)
activejob (7.2.2.1)
activesupport (= 7.2.2.1)
globalid (>= 0.3.6)
activemodel (7.2.2.1)
activesupport (= 7.2.2.1)
activerecord (7.2.2.1)
activemodel (= 7.2.2.1)
activesupport (= 7.2.2.1)
timeout (>= 0.4.0)
activesupport (7.2.2.1)
base64
benchmark (>= 0.3)
bigdecimal
concurrent-ruby (~> 1.0, >= 1.3.1)
connection_pool (>= 2.2.5)
drb
i18n (>= 1.6, < 2)
logger (>= 1.4.2)
minitest (>= 5.1)
securerandom (>= 0.3)
tzinfo (~> 2.0, >= 2.0.5)
addressable (2.8.7)
public_suffix (>= 2.0.2, < 7.0)
annotate (3.2.0)
activerecord (>= 3.2, < 8.0)
rake (>= 10.4, < 14.0)
ast (2.4.2)
aws-eventstream (1.3.0)
aws-partitions (1.894.0)
aws-sdk-core (3.191.3)
aws-eventstream (~> 1, >= 1.3.0)
aws-partitions (~> 1, >= 1.651.0)
aws-sigv4 (~> 1.8)
jmespath (~> 1, >= 1.6.1)
aws-sdk-kms (1.77.0)
aws-sdk-core (~> 3, >= 3.191.0)
aws-sigv4 (~> 1.1)
aws-sdk-s3 (1.143.0)
aws-sdk-core (~> 3, >= 3.191.0)
aws-sdk-kms (~> 1)
aws-sigv4 (~> 1.8)
aws-sdk-sns (1.72.0)
aws-sdk-core (~> 3, >= 3.191.0)
aws-sigv4 (~> 1.1)
aws-sigv4 (1.8.0)
aws-eventstream (~> 1, >= 1.0.2)
base64 (0.2.0)
benchmark (0.4.0)
better_errors (2.10.1)
erubi (>= 1.0.0)
rack (>= 0.9.0)
rouge (>= 1.0.0)
bigdecimal (3.1.9)
binding_of_caller (1.0.1)
debug_inspector (>= 1.2.0)
bootsnap (1.18.4)
msgpack (~> 1.2)
builder (3.3.0)
bullet (8.0.0)
activesupport (>= 3.0.0)
uniform_notifier (~> 1.11)
byebug (11.1.3)
capybara (3.40.0)
addressable
matrix
mini_mime (>= 0.1.3)
nokogiri (~> 1.11)
rack (>= 1.6.0)
rack-test (>= 0.6.3)
regexp_parser (>= 1.5, < 3.0)
xpath (~> 3.2)
cbor (0.5.9.8)
certified (1.0.0)
cgi (0.4.1)
chunky_png (1.4.0)
coderay (1.1.3)
colored2 (4.0.3)
concurrent-ruby (1.3.5)
connection_pool (2.5.0)
cose (1.3.1)
cbor (~> 0.5.9)
openssl-signature_algorithm (~> 1.0)
cppjieba_rb (0.4.4)
crack (1.0.0)
bigdecimal
rexml
crass (1.0.6)
css_parser (1.21.0)
addressable
csv (3.3.2)
date (3.4.1)
debug_inspector (1.2.0)
diff-lcs (1.5.1)
diffy (3.4.3)
digest (3.2.0)
digest-xxhash (0.2.9)
discourse-fonts (0.0.18)
discourse-seed-fu (2.3.12)
activerecord (>= 3.1)
activesupport (>= 3.1)
discourse_dev_assets (0.0.4)
faker (~> 2.16)
literate_randomizer
docile (1.4.1)
drb (2.2.1)
dry-initializer (3.2.0)
email_reply_trimmer (0.2.0)
erubi (1.13.1)
excon (1.2.3)
execjs (2.10.0)
exifr (1.4.1)
extralite-bundle (2.8.2)
fabrication (2.31.0)
faker (2.23.0)
i18n (>= 1.8.11, < 2)
fakeweb (1.3.0)
faraday (2.12.2)
faraday-net_http (>= 2.0, < 3.5)
json
logger
faraday-net_http (3.4.0)
net-http (>= 0.5.0)
faraday-retry (2.2.1)
faraday (~> 2.0)
fast_blank (1.0.1)
fastimage (2.3.1)
ffi (1.17.1)
ffi (1.17.1-arm64-darwin)
ffi (1.17.1-x86_64-darwin)
fspath (3.1.2)
globalid (1.2.1)
activesupport (>= 6.1)
google-protobuf (4.29.3)
bigdecimal
rake (>= 13)
google-protobuf (4.29.3-arm64-darwin)
bigdecimal
rake (>= 13)
google-protobuf (4.29.3-x86_64-darwin)
bigdecimal
rake (>= 13)
guess_html_encoding (0.0.11)
hana (1.3.7)
hashdiff (1.1.2)
hashie (5.0.0)
highline (3.1.2)
reline
htmlentities (4.3.4)
http_accept_language (2.1.1)
i18n (1.14.7)
concurrent-ruby (~> 1.0)
image_optim (0.31.4)
exifr (~> 1.2, >= 1.2.2)
fspath (~> 3.0)
image_size (>= 1.5, < 4)
in_threads (~> 1.3)
progress (~> 3.0, >= 3.0.1)
image_size (3.4.0)
in_threads (1.6.0)
io-console (0.8.0)
irb (1.15.1)
pp (>= 0.6.0)
rdoc (>= 4.0.0)
reline (>= 0.4.2)
iso8601 (0.13.0)
jmespath (1.6.2)
json (2.9.1)
json-schema (5.1.1)
addressable (~> 2.8)
bigdecimal (~> 3.1)
json_schemer (2.4.0)
bigdecimal
hana (~> 1.3)
regexp_parser (~> 2.0)
simpleidn (~> 0.2)
jwt (2.10.1)
base64
kgio (2.11.4)
language_server-protocol (3.17.0.4)
libv8-node (22.7.0.4)
libv8-node (22.7.0.4-arm64-darwin)
libv8-node (22.7.0.4-x86_64-darwin)
listen (3.9.0)
rb-fsevent (~> 0.10, >= 0.10.3)
rb-inotify (~> 0.9, >= 0.9.10)
literate_randomizer (0.4.0)
logger (1.7.0)
lograge (0.14.0)
actionpack (>= 4)
activesupport (>= 4)
railties (>= 4)
request_store (~> 1.0)
logstash-event (1.2.02)
logster (2.20.0)
loofah (2.24.0)
crass (~> 1.0.2)
nokogiri (>= 1.12.0)
lru_redux (1.1.0)
lz4-ruby (0.3.3)
mail (2.8.1)
mini_mime (>= 0.1.1)
net-imap
net-pop
net-smtp
matrix (0.4.2)
maxminddb (0.1.22)
memory_profiler (1.1.0)
message_bus (4.3.8)
rack (>= 1.1.3)
messageformat-wrapper (1.1.0)
mini_racer (>= 0.6.3)
method_source (1.1.0)
mini_mime (1.1.5)
mini_portile2 (2.8.9)
mini_racer (0.17.0.pre13)
libv8-node (~> 22.7.0.4)
mini_scheduler (0.18.0)
sidekiq (>= 6.5, < 8.0)
mini_sql (1.6.0)
mini_suffix (0.3.3)
ffi (~> 1.9)
minio_runner (0.1.2)
minitest (5.25.4)
mocha (2.7.1)
ruby2_keywords (>= 0.0.5)
msgpack (1.7.5)
multi_json (1.15.0)
multi_xml (0.7.1)
bigdecimal (~> 3.1)
mustache (1.1.1)
net-http (0.6.0)
uri
net-imap (0.5.5)
date
net-protocol
net-pop (0.1.2)
net-protocol
net-protocol (0.2.2)
timeout
net-smtp (0.5.0)
net-protocol
nio4r (2.7.4)
nokogiri (1.18.2)
mini_portile2 (~> 2.8.2)
racc (~> 1.4)
nokogiri (1.18.2-arm64-darwin)
racc (~> 1.4)
nokogiri (1.18.2-x86_64-darwin)
racc (~> 1.4)
oauth (1.1.0)
oauth-tty (~> 1.0, >= 1.0.1)
snaky_hash (~> 2.0)
version_gem (~> 1.1)
oauth-tty (1.0.5)
version_gem (~> 1.1, >= 1.1.1)
oauth2 (1.4.11)
faraday (>= 0.17.3, < 3.0)
jwt (>= 1.0, < 3.0)
multi_json (~> 1.3)
multi_xml (~> 0.5)
rack (>= 1.2, < 4)
oj (3.16.9)
bigdecimal (>= 3.0)
ostruct (>= 0.2)
omniauth (1.9.2)
hashie (>= 3.4.6)
rack (>= 1.6.2, < 3)
omniauth-facebook (9.0.0)
omniauth-oauth2 (~> 1.2)
omniauth-github (1.4.0)
omniauth (~> 1.5)
omniauth-oauth2 (>= 1.4.0, < 2.0)
omniauth-google-oauth2 (0.8.2)
jwt (>= 2.0)
oauth2 (~> 1.1)
omniauth (~> 1.1)
omniauth-oauth2 (>= 1.6)
omniauth-oauth (1.2.1)
oauth
omniauth (>= 1.0, < 3)
rack (>= 1.6.2, < 4)
omniauth-oauth2 (1.7.3)
oauth2 (>= 1.4, < 3)
omniauth (>= 1.9, < 3)
omniauth-twitter (1.4.0)
omniauth-oauth (~> 1.1)
rack
openssl (3.3.0)
openssl-signature_algorithm (1.3.0)
openssl (> 2.0)
optimist (3.2.0)
ostruct (0.6.1)
parallel (1.26.3)
parallel_tests (4.9.0)
parallel
parser (3.3.7.0)
ast (~> 2.4.1)
racc
pg (1.5.9)
pp (0.6.2)
prettyprint
prettier_print (1.2.1)
prettyprint (0.2.0)
progress (3.6.0)
pry (0.14.2)
coderay (~> 1.1)
method_source (~> 1.0)
pry-byebug (3.10.1)
byebug (~> 11.0)
pry (>= 0.13, < 0.15)
pry-rails (0.3.11)
pry (>= 0.13.0)
pry-stack_explorer (0.6.1)
binding_of_caller (~> 1.0)
pry (~> 0.13)
psych (5.2.3)
date
stringio
public_suffix (6.0.1)
puma (6.6.0)
nio4r (~> 2.0)
racc (1.8.1)
rack (2.2.10)
rack-mini-profiler (3.3.1)
rack (>= 1.2.0)
rack-protection (3.2.0)
base64 (>= 0.1.0)
rack (~> 2.2, >= 2.2.4)
rack-session (1.0.2)
rack (< 3)
rack-test (2.2.0)
rack (>= 1.3)
rackup (1.0.1)
rack (< 3)
webrick
rails-dom-testing (2.2.0)
activesupport (>= 5.0.0)
minitest
nokogiri (>= 1.6)
rails-html-sanitizer (1.6.2)
loofah (~> 2.21)
nokogiri (>= 1.15.7, != 1.16.7, != 1.16.6, != 1.16.5, != 1.16.4, != 1.16.3, != 1.16.2, != 1.16.1, != 1.16.0.rc1, != 1.16.0)
rails_failover (2.2.0)
activerecord (>= 6.1, < 8.0)
concurrent-ruby
railties (>= 6.1, < 8.0)
rails_multisite (6.1.0)
activerecord (>= 6.0)
railties (>= 6.0)
railties (7.2.2.1)
actionpack (= 7.2.2.1)
activesupport (= 7.2.2.1)
irb (~> 1.13)
rackup (>= 1.0.0)
rake (>= 12.2)
thor (~> 1.0, >= 1.2.2)
zeitwerk (~> 2.6)
rainbow (3.1.1)
raindrops (0.20.1)
rake (13.2.1)
rb-fsevent (0.11.2)
rb-inotify (0.11.1)
ffi (~> 1.0)
rbtrace (0.5.1)
ffi (>= 1.0.6)
msgpack (>= 0.4.3)
optimist (>= 3.0.0)
rchardet (1.9.0)
rdoc (6.11.0)
psych (>= 4.0.0)
redcarpet (3.6.0)
redis (4.8.1)
redis-namespace (1.11.0)
redis (>= 4)
regexp_parser (2.10.0)
reline (0.6.0)
io-console (~> 0.5)
request_store (1.7.0)
rack (>= 1.4)
rexml (3.4.1)
rinku (2.0.6)
rotp (6.3.0)
rouge (4.5.1)
rqrcode (2.2.0)
chunky_png (~> 1.0)
rqrcode_core (~> 1.0)
rqrcode_core (1.2.0)
rrule (0.6.0)
activesupport (>= 2.3)
rspec (3.13.0)
rspec-core (~> 3.13.0)
rspec-expectations (~> 3.13.0)
rspec-mocks (~> 3.13.0)
rspec-core (3.13.2)
rspec-support (~> 3.13.0)
rspec-expectations (3.13.3)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.13.0)
rspec-html-matchers (0.10.0)
nokogiri (~> 1)
rspec (>= 3.0.0.a)
rspec-mocks (3.13.2)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.13.0)
rspec-multi-mock (0.3.1)
rspec (>= 3.7.0)
rspec-rails (7.1.0)
actionpack (>= 7.0)
activesupport (>= 7.0)
railties (>= 7.0)
rspec-core (~> 3.13)
rspec-expectations (~> 3.13)
rspec-mocks (~> 3.13)
rspec-support (~> 3.13)
rspec-support (3.13.2)
rss (0.3.1)
rexml
rswag-specs (2.16.0)
activesupport (>= 5.2, < 8.1)
json-schema (>= 2.2, < 6.0)
railties (>= 5.2, < 8.1)
rspec-core (>= 2.14)
rtlcss (0.2.1)
mini_racer (>= 0.6.3)
rubocop (1.71.1)
json (~> 2.3)
language_server-protocol (>= 3.17.0)
parallel (~> 1.10)
parser (>= 3.3.0.2)
rainbow (>= 2.2.2, < 4.0)
regexp_parser (>= 2.9.3, < 3.0)
rubocop-ast (>= 1.38.0, < 2.0)
ruby-progressbar (~> 1.7)
unicode-display_width (>= 2.4.0, < 4.0)
rubocop-ast (1.38.0)
parser (>= 3.3.1.0)
rubocop-capybara (2.21.0)
rubocop (~> 1.41)
rubocop-discourse (3.9.3)
activesupport (>= 6.1)
rubocop (>= 1.59.0)
rubocop-capybara (>= 2.0.0)
rubocop-factory_bot (>= 2.0.0)
rubocop-rails (>= 2.25.0)
rubocop-rspec (>= 3.0.1)
rubocop-rspec_rails (>= 2.30.0)
rubocop-factory_bot (2.26.1)
rubocop (~> 1.61)
rubocop-rails (2.29.1)
activesupport (>= 4.2.0)
rack (>= 1.1)
rubocop (>= 1.52.0, < 2.0)
rubocop-ast (>= 1.31.1, < 2.0)
rubocop-rspec (3.4.0)
rubocop (~> 1.61)
rubocop-rspec_rails (2.30.0)
rubocop (~> 1.61)
rubocop-rspec (~> 3, >= 3.0.1)
ruby-prof (1.7.1)
ruby-progressbar (1.13.0)
ruby-readability (0.7.2)
guess_html_encoding (>= 0.0.4)
nokogiri (>= 1.6.0)
ruby2_keywords (0.0.5)
rubyzip (2.4.1)
sanitize (7.0.0)
crass (~> 1.0.2)
nokogiri (>= 1.16.8)
sass-embedded (1.77.5)
google-protobuf (>= 3.25, < 5.0)
rake (>= 13)
sass-embedded (1.77.5-arm64-darwin)
google-protobuf (>= 3.25, < 5.0)
sass-embedded (1.77.5-x86_64-darwin)
google-protobuf (>= 3.25, < 5.0)
sassc-embedded (1.77.7)
sass-embedded (~> 1.77)
securerandom (0.4.1)
selenium-devtools (0.135.0)
selenium-webdriver (~> 4.2)
selenium-webdriver (4.31.0)
base64 (~> 0.2)
logger (~> 1.4)
rexml (~> 3.2, >= 3.2.5)
rubyzip (>= 1.2.2, < 3.0)
websocket (~> 1.0)
shoulda-matchers (6.4.0)
activesupport (>= 5.2.0)
sidekiq (6.5.12)
connection_pool (>= 2.2.5, < 3)
rack (~> 2.0)
redis (>= 4.5.0, < 5)
simplecov (0.22.0)
docile (~> 1.1)
simplecov-html (~> 0.11)
simplecov_json_formatter (~> 0.1)
simplecov-html (0.13.1)
simplecov_json_formatter (0.1.4)
simpleidn (0.2.3)
snaky_hash (2.0.1)
hashie
version_gem (~> 1.1, >= 1.1.1)
sprockets (3.7.5)
base64
concurrent-ruby (~> 1.0)
rack (> 1, < 3)
sprockets-rails (3.5.2)
actionpack (>= 6.1)
activesupport (>= 6.1)
sprockets (>= 3.0.0)
sqlite3 (2.5.0)
mini_portile2 (~> 2.8.0)
sqlite3 (2.5.0-arm64-darwin)
sqlite3 (2.5.0-x86_64-darwin)
sshkey (3.0.0)
stackprof (0.2.27)
stringio (3.1.2)
syntax_tree (6.2.0)
prettier_print (>= 1.2.0)
syntax_tree-disable_ternary (1.0.0)
test-prof (1.4.4)
thor (1.3.2)
timeout (0.4.3)
trilogy (2.9.0)
tzinfo (2.0.6)
concurrent-ruby (~> 1.0)
tzinfo-data (1.2025.1)
tzinfo (>= 1.0.0)
uglifier (4.2.1)
execjs (>= 0.3.0, < 3)
unf (0.2.0)
unicode-display_width (3.1.4)
unicode-emoji (~> 4.0, >= 4.0.4)
unicode-emoji (4.0.4)
unicorn (6.1.0)
kgio (~> 2.6)
raindrops (~> 0.7)
uniform_notifier (1.16.0)
uri (1.0.2)
useragent (0.16.11)
version_gem (1.1.4)
web-push (3.0.1)
jwt (~> 2.0)
openssl (~> 3.0)
webmock (3.24.0)
addressable (>= 2.8.0)
crack (>= 0.3.2)
hashdiff (>= 0.4.0, < 2.0.0)
webrick (1.9.1)
websocket (1.2.11)
xpath (3.2.0)
nokogiri (~> 1.8)
yaml-lint (0.1.2)
yard (0.9.37)
zeitwerk (2.7.1)
PLATFORMS
arm64-darwin-21
arm64-darwin-22
arm64-darwin-23
arm64-darwin-24
ruby
x86_64-darwin-22
x86_64-darwin-23
x86_64-darwin-24
DEPENDENCIES
actionmailer (~> 7.2.0)
actionpack (~> 7.2.0)
actionview (~> 7.2.0)
actionview_precompiler
active_model_serializers (~> 0.8.3)
activemodel (~> 7.2.0)
activerecord (~> 7.2.0)
activesupport (~> 7.2.0)
addressable
annotate
aws-sdk-s3
aws-sdk-sns
better_errors
binding_of_caller
bootsnap
bullet
byebug
capybara
cbor
certified
cgi (>= 0.3.6)
colored2
cose
cppjieba_rb
css_parser
csv
diffy
digest
digest-xxhash
discourse-fonts
discourse-seed-fu
discourse_dev_assets
dry-initializer (~> 3.1)
email_reply_trimmer
excon
execjs
extralite-bundle
fabrication
faker (~> 2.16)
fakeweb
faraday
faraday-retry
fast_blank
fastimage
highline
htmlentities
http_accept_language
image_optim
iso8601
json
json_schemer
listen
lograge
logstash-event
logster
loofah
lru_redux
lz4-ruby
mail
maxminddb
memory_profiler
message_bus
messageformat-wrapper
mini_mime
mini_racer (= 0.17.pre13)
mini_scheduler
mini_sql
mini_suffix
minio_runner
mocha
multi_json
mustache
net-http
net-imap
net-pop
net-smtp
nokogiri
oj
omniauth
omniauth-facebook
omniauth-github
omniauth-google-oauth2
omniauth-oauth2
omniauth-twitter
parallel
parallel_tests
pg
pry-byebug
pry-rails
pry-stack_explorer
puma
rack
rack-mini-profiler
rack-protection
rails-dom-testing
rails_failover
rails_multisite
railties (~> 7.2.0)
rake
rb-fsevent
rbtrace
rchardet
redcarpet
redis (< 5.0)
redis-namespace
rinku
rotp
rqrcode
rrule
rspec
rspec-html-matchers
rspec-multi-mock
rspec-rails
rss
rswag-specs
rtlcss
rubocop-discourse
ruby-prof
ruby-progressbar
ruby-readability
rubyzip
sanitize
sassc-embedded
selenium-devtools
selenium-webdriver (~> 4.14)
shoulda-matchers
sidekiq
simplecov
sprockets (~> 3.7.3)
sprockets-rails
sqlite3
sshkey
stackprof
syntax_tree
syntax_tree-disable_ternary
test-prof
thor
trilogy
tzinfo-data
uglifier
unf
unicorn
web-push
webmock
yaml-lint
yard
zeitwerk
BUNDLED WITH
2.6.9

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,25 @@
diff --git a/config/unicorn.conf.rb b/config/unicorn.conf.rb
index b8c549bc0f..a7d3592013 100644
--- a/config/unicorn.conf.rb
+++ b/config/unicorn.conf.rb
@@ -35,19 +35,7 @@ FileUtils.mkdir_p("#{discourse_path}/tmp/pids") if !File.exist?("#{discourse_pat
# feel free to point this anywhere accessible on the filesystem
pid(ENV["UNICORN_PID_PATH"] || "#{discourse_path}/tmp/pids/unicorn.pid")
-if ENV["RAILS_ENV"] == "production"
- # By default, the Unicorn logger will write to stderr.
- # Additionally, some applications/frameworks log to stderr or stdout,
- # so prevent them from going to /dev/null when daemonized here:
- stderr_path unicorn_stderr_path
- stdout_path unicorn_stdout_path
-
- # nuke workers after 30 seconds instead of 60 seconds (the default)
- timeout 30
-else
- # we want a longer timeout in dev cause first request can be really slow
- timeout(ENV["UNICORN_TIMEOUT"] && ENV["UNICORN_TIMEOUT"].to_i || 60)
-end
+timeout(ENV["UNICORN_TIMEOUT"] && ENV["UNICORN_TIMEOUT"].to_i || 60)
# important for Ruby 2.0
preload_app true

View File

@@ -0,0 +1,446 @@
#!/usr/bin/env nix-shell
#! nix-shell -i python3 -p "python3.withPackages (ps: with ps; [ requests click click-log packaging ])" bundix bundler nix-update nurl
from __future__ import annotations
import click
import click_log
import shutil
import tempfile
import re
import logging
import subprocess
import os
import stat
import json
import requests
import textwrap
from functools import total_ordering
from packaging.version import Version
from pathlib import Path
from typing import Union, Iterable
logger = logging.getLogger(__name__)
@total_ordering
class DiscourseVersion:
"""Represents a Discourse style version number and git tag.
This takes either a tag or version string as input and
extrapolates the other. Sorting is implemented to work as expected
in regard to A.B.C.betaD version numbers - 2.0.0.beta1 is
considered lower than 2.0.0.
"""
tag: str = ""
version: str = ""
split_version: Iterable[Union[None, int, str]] = []
def __init__(self, version: str):
"""Take either a tag or version number, calculate the other."""
if version.startswith('v'):
self.tag = version
self.version = version.lstrip('v')
else:
self.tag = 'v' + version
self.version = version
self._version = Version(self.version)
def __eq__(self, other: DiscourseVersion):
"""Versions are equal when their individual parts are."""
return self._version == other._version
def __gt__(self, other: DiscourseVersion):
"""Check if this version is greater than the other."""
return self._version > other._version
class DiscourseRepo:
version_regex = re.compile(r'^v\d+\.\d+\.\d+(\.beta\d+)?$')
_latest_commit_sha = None
def __init__(self, owner: str = 'discourse', repo: str = 'discourse'):
self.owner = owner
self.repo = repo
@property
def versions(self) -> Iterable[str]:
r = requests.get(f'https://api.github.com/repos/{self.owner}/{self.repo}/git/refs/tags').json()
tags = [x['ref'].replace('refs/tags/', '') for x in r]
# filter out versions not matching version_regex
versions = filter(self.version_regex.match, tags)
versions = [DiscourseVersion(x) for x in versions]
versions.sort(reverse=True)
return versions
@property
def latest_commit_sha(self) -> str:
if self._latest_commit_sha is None:
r = requests.get(f'https://api.github.com/repos/{self.owner}/{self.repo}/commits?per_page=1')
r.raise_for_status()
self._latest_commit_sha = r.json()[0]['sha']
return self._latest_commit_sha
def get_file(self, filepath, rev):
"""Return file contents at a given rev.
:param str filepath: the path to the file, relative to the repo root
:param str rev: the rev to fetch at :return:
"""
r = requests.get(f'https://raw.githubusercontent.com/{self.owner}/{self.repo}/{rev}/{filepath}')
r.raise_for_status()
return r.text
def _get_build_lock_hash():
nixpkgs_path = Path(__file__).parent / '../../../../'
output = subprocess.run(['nix-build', '-A', 'discourse'], text=True, cwd=nixpkgs_path, capture_output=True)
# The line is of the form " got: sha256-xxx"
lines = [i.strip() for i in output.stderr.splitlines()]
new_hash_lines = [i.strip("got:").strip() for i in lines if i.startswith("got:")]
if len(new_hash_lines) == 0:
if output.returncode != 0:
print("Error while fetching new hash with nix build")
print(output.stderr)
print("No hash change is needed")
return None
if len(new_hash_lines) > 1:
print(new_hash_lines)
raise Exception("Got an unexpected number of new hash lines:")
return new_hash_lines[0]
def _call_nix_update(pkg, version):
"""Call nix-update from nixpkgs root dir."""
nixpkgs_path = Path(__file__).parent / '../../../../'
return subprocess.check_output(['nix-update', pkg, '--version', version], cwd=nixpkgs_path)
def _nix_eval(expr: str):
nixpkgs_path = Path(__file__).parent / '../../../../'
try:
output = subprocess.check_output(['nix-instantiate', '--strict', '--json', '--eval', '-E', f'(with import {nixpkgs_path} {{}}; {expr})'], text=True)
except subprocess.CalledProcessError:
return None
return json.loads(output)
def _get_current_package_version(pkg: str):
return _nix_eval(f'{pkg}.version')
def _diff_file(filepath: str, old_version: DiscourseVersion, new_version: DiscourseVersion):
repo = DiscourseRepo()
current_dir = Path(__file__).parent
old = repo.get_file(filepath, old_version.tag)
new = repo.get_file(filepath, new_version.tag)
if old == new:
click.secho(f'{filepath} is unchanged', fg='green')
return
with tempfile.NamedTemporaryFile(mode='w') as o, tempfile.NamedTemporaryFile(mode='w') as n:
o.write(old), n.write(new)
width = shutil.get_terminal_size((80, 20)).columns
diff_proc = subprocess.run(
['diff', '--color=always', f'--width={width}', '-y', o.name, n.name],
stdout=subprocess.PIPE,
cwd=current_dir,
text=True
)
click.secho(f'Diff for {filepath} ({old_version.version} -> {new_version.version}):', fg='bright_blue', bold=True)
click.echo(diff_proc.stdout + '\n')
return
def _remove_platforms(rubyenv_dir: Path):
for platform in ['arm64-darwin-20', 'x86_64-darwin-18',
'x86_64-darwin-19', 'x86_64-darwin-20',
'x86_64-linux', 'aarch64-linux']:
with open(rubyenv_dir / 'Gemfile.lock', 'r') as f:
for line in f:
if platform in line:
subprocess.check_output(
['bundle', 'lock', '--remove-platform', platform], cwd=rubyenv_dir)
break
@click_log.simple_verbosity_option(logger)
@click.group()
def cli():
pass
@cli.command()
@click.argument('rev', default='latest')
@click.option('--reverse/--no-reverse', default=False, help='Print diffs from REV to current.')
def print_diffs(rev, reverse):
"""Print out diffs for files used as templates for the NixOS module.
The current package version found in the nixpkgs worktree the
script is run from will be used to download the "from" file and
REV used to download the "to" file for the diff, unless the
'--reverse' flag is specified.
REV should be the git rev to find changes in ('vX.Y.Z') or
'latest'; defaults to 'latest'.
"""
if rev == 'latest':
repo = DiscourseRepo()
rev = repo.versions[0].tag
old_version = DiscourseVersion(_get_current_package_version('discourse'))
new_version = DiscourseVersion(rev)
if reverse:
old_version, new_version = new_version, old_version
for f in ['config/nginx.sample.conf', 'config/discourse_defaults.conf']:
_diff_file(f, old_version, new_version)
@cli.command()
@click.argument('rev', default='latest')
def update(rev):
"""Update gem files and version.
REV: the git rev to update to ('vX.Y.Z[.betaA]') or
'latest'; defaults to 'latest'.
"""
repo = DiscourseRepo()
if rev == 'latest':
version = repo.versions[0]
else:
version = DiscourseVersion(rev)
logger.debug(f"Using rev {version.tag}")
logger.debug(f"Using version {version.version}")
rubyenv_dir = Path(__file__).parent / "rubyEnv"
for fn in ['Gemfile.lock', 'Gemfile']:
with open(rubyenv_dir / fn, 'w') as f:
f.write(repo.get_file(fn, version.tag))
# work around https://github.com/nix-community/bundix/issues/8
os.environ["BUNDLE_FORCE_RUBY_PLATFORM"] = "true"
subprocess.check_output(['bundle', 'lock'], cwd=rubyenv_dir)
_remove_platforms(rubyenv_dir)
subprocess.check_output(['bundix'], cwd=rubyenv_dir)
_call_nix_update('discourse', version.version)
old_pnpm_hash = _nix_eval('discourse.assets.pnpmDeps.outputHash')
new_pnpm_hash = _get_build_lock_hash()
if new_pnpm_hash is not None:
click.echo(f"Updating yarn lock hash: {old_pnpm_hash} -> {new_pnpm_hash}")
with open(Path(__file__).parent / "default.nix", 'r+') as f:
content = f.read()
content = content.replace(old_pnpm_hash, new_pnpm_hash)
f.seek(0)
f.write(content)
f.truncate()
@cli.command()
@click.argument('rev', default='latest')
def update_mail_receiver(rev):
"""Update discourse-mail-receiver.
REV: the git rev to update to ('vX.Y.Z') or 'latest'; defaults to
'latest'.
"""
repo = DiscourseRepo(repo="mail-receiver")
if rev == 'latest':
version = repo.versions[0]
else:
version = DiscourseVersion(rev)
_call_nix_update('discourse-mail-receiver', version.version)
@cli.command()
def update_plugins():
"""Update plugins to their latest revision."""
plugins = [
{'name': 'discourse-assign'},
{'name': 'discourse-bbcode-color'},
{'name': 'discourse-calendar'},
{'name': 'discourse-canned-replies'},
{'name': 'discourse-chat-integration'},
{'name': 'discourse-checklist'},
{'name': 'discourse-data-explorer'},
{'name': 'discourse-docs'},
{'name': 'discourse-github'},
{'name': 'discourse-ldap-auth', 'owner': 'jonmbake'},
{'name': 'discourse-math'},
{'name': 'discourse-migratepassword', 'owner': 'discoursehosting'},
{'name': 'discourse-openid-connect'},
{'name': 'discourse-prometheus'},
{'name': 'discourse-reactions'},
{'name': 'discourse-saved-searches'},
{'name': 'discourse-solved'},
{'name': 'discourse-spoiler-alert'},
{'name': 'discourse-voting', 'repo_name': "discourse-topic-voting"},
{'name': 'discourse-yearly-review'},
]
for plugin in plugins:
fetcher = plugin.get('fetcher') or "fetchFromGitHub"
owner = plugin.get('owner') or "discourse"
name = plugin.get('name')
repo_name = plugin.get('repo_name') or name
if fetcher == "fetchFromGitHub":
url = f"https://github.com/{owner}/{repo_name}"
else:
raise NotImplementedError(f"Missing URL pattern for {fetcher}")
repo = DiscourseRepo(owner=owner, repo=repo_name)
# implement the plugin pinning algorithm laid out here:
# https://meta.discourse.org/t/pinning-plugin-and-theme-versions-for-older-discourse-installs/156971
# this makes sure we don't upgrade plugins to revisions that
# are incompatible with the packaged Discourse version
repo_latest_commit = repo.latest_commit_sha
try:
compatibility_spec = repo.get_file('.discourse-compatibility', repo_latest_commit)
versions = [(DiscourseVersion(discourse_version), plugin_rev.strip(' '))
for [discourse_version, plugin_rev]
in [line.lstrip("< ").split(':')
for line
in compatibility_spec.splitlines() if line != '']]
discourse_version = DiscourseVersion(_get_current_package_version('discourse'))
versions = list(filter(lambda ver: ver[0] >= discourse_version, versions))
if versions == []:
rev = repo_latest_commit
else:
rev = versions[0][1]
print(rev)
except requests.exceptions.HTTPError:
rev = repo_latest_commit
filename = _nix_eval(f'builtins.unsafeGetAttrPos "src" discourse.plugins.{name}')
if filename is None:
filename = Path(__file__).parent / 'plugins' / name / 'default.nix'
filename.parent.mkdir()
has_ruby_deps = False
for line in repo.get_file('plugin.rb', rev).splitlines():
if 'gem ' in line:
has_ruby_deps = True
break
with open(filename, 'w') as f:
f.write(textwrap.dedent(f"""
{{ lib, mkDiscoursePlugin, fetchFromGitHub }}:
mkDiscoursePlugin {{
name = "{name}";"""[1:] + ("""
bundlerEnvArgs.gemdir = ./.;""" if has_ruby_deps else "") + f"""
src = {fetcher} {{
owner = "{owner}";
repo = "{repo_name}";
rev = "replace-with-git-rev";
sha256 = "replace-with-sha256";
}};
meta = with lib; {{
homepage = "";
maintainers = with maintainers; [ ];
license = licenses.mit; # change to the correct license!
description = "";
}};
}}"""))
all_plugins_filename = Path(__file__).parent / 'plugins' / 'all-plugins.nix'
with open(all_plugins_filename, 'r+') as f:
content = f.read()
pos = -1
while content[pos] != '}':
pos -= 1
content = content[:pos] + f' {name} = callPackage ./{name} {{}};' + os.linesep + content[pos:]
f.seek(0)
f.write(content)
f.truncate()
else:
filename = filename['file']
prev_commit_sha = _nix_eval(f'discourse.plugins.{name}.src.rev')
if prev_commit_sha == rev:
click.echo(f'Plugin {name} is already at the latest revision')
continue
prev_hash = _nix_eval(f'discourse.plugins.{name}.src.outputHash')
new_hash = subprocess.check_output([
"nurl",
"--fetcher", fetcher,
"--hash",
url,
rev,
], text=True).strip("\n")
click.echo(f"Update {name}, {prev_commit_sha} -> {rev} in {filename}")
with open(filename, 'r+') as f:
content = f.read()
content = content.replace(prev_commit_sha, rev)
content = content.replace(prev_hash, new_hash)
f.seek(0)
f.write(content)
f.truncate()
rubyenv_dir = Path(filename).parent
gemfile = rubyenv_dir / "Gemfile"
version_file_regex = re.compile(r'.*File\.expand_path\("\.\./(.*)", __FILE__\)')
gemfile_text = ''
plugin_file = repo.get_file('plugin.rb', rev)
plugin_file = plugin_file.replace(",\n", ", ") # fix split lines
for line in plugin_file.splitlines():
if 'gem ' in line:
line = ','.join(filter(lambda x: ":require_name" not in x, line.split(',')))
gemfile_text = gemfile_text + line + os.linesep
version_file_match = version_file_regex.match(line)
if version_file_match is not None:
filename = version_file_match.groups()[0]
content = repo.get_file(filename, rev)
with open(rubyenv_dir / filename, 'w') as f:
f.write(content)
if len(gemfile_text) > 0:
if os.path.isfile(gemfile):
os.remove(gemfile)
subprocess.check_output(['bundle', 'init'], cwd=rubyenv_dir)
os.chmod(gemfile, stat.S_IREAD | stat.S_IWRITE | stat.S_IRGRP | stat.S_IROTH)
with open(gemfile, 'a') as f:
f.write(gemfile_text)
subprocess.check_output(['bundle', 'lock', '--add-platform', 'ruby'], cwd=rubyenv_dir)
subprocess.check_output(['bundle', 'lock', '--update'], cwd=rubyenv_dir)
_remove_platforms(rubyenv_dir)
subprocess.check_output(['bundix'], cwd=rubyenv_dir)
if __name__ == '__main__':
cli()

View File

@@ -0,0 +1,35 @@
{
stdenv,
pkgs,
lib,
nodejs_20,
}:
let
nodejs = nodejs_20;
nodePackages = import ./node-packages.nix {
inherit pkgs nodejs;
inherit (stdenv.hostPlatform) system;
};
ethercalc = lib.head (lib.attrValues nodePackages);
combined = ethercalc.override {
meta = with lib; {
description = "Online collaborative spreadsheet";
license = with licenses; [
cpal10
artistic2
mit
asl20
cc0
mpl20
];
homepage = "https://github.com/audreyt/ethercalc";
maintainers = with maintainers; [ iblech ];
platforms = platforms.unix;
};
};
in
combined

View File

@@ -0,0 +1,16 @@
#!/usr/bin/env nix-shell
#! nix-shell -i bash -p nodePackages.node2nix
# Run this script not via `./generate.sh`, but via `$PWD/generate.sh`.
# Else `nix-shell` will not find this script.
set -euo pipefail
cd -- "$(dirname -- "$BASH_SOURCE[0]")"
node2nix \
--nodejs-14 \
--input node-packages.json \
--output node-packages-generated.nix \
--composition node-packages.nix \
--node-env ../../../development/node-packages/node-env.nix

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,3 @@
[
{ "whitebophir": "git+https://github.com/audreyt/ethercalc.git#b196277081d677be991d104e454a52d242ef0189" }
]

View File

@@ -0,0 +1,33 @@
# This file has been generated by node2nix 1.11.1. Do not edit!
{
pkgs ? import <nixpkgs> {
inherit system;
},
system ? builtins.currentSystem,
nodejs ? pkgs."nodejs_20",
}:
let
nodeEnv = import ../../../development/node-packages/node-env.nix {
inherit (pkgs)
stdenv
lib
runCommand
writeTextFile
writeShellScript
;
inherit pkgs nodejs;
libtool = if pkgs.stdenv.hostPlatform.isDarwin then pkgs.cctools or pkgs.darwin.cctools else null;
};
in
import ./node-packages-generated.nix {
inherit (pkgs)
fetchurl
nix-gitignore
stdenv
lib
fetchgit
;
inherit nodeEnv;
}

View File

@@ -0,0 +1,59 @@
{
stdenvNoCC,
lib,
fetchFromGitHub,
nixosTests,
php,
writeText,
}:
stdenvNoCC.mkDerivation rec {
pname = "FreshRSS";
version = "1.27.1";
src = fetchFromGitHub {
owner = "FreshRSS";
repo = "FreshRSS";
rev = version;
hash = "sha256-EpszwgYzobRA7LohtJJtgTefFAEmCXvcP3ilfsu+obo=";
};
postPatch = ''
patchShebangs cli/*.php app/actualize_script.php
'';
# THIRDPARTY_EXTENSIONS_PATH can only be set by config, but should be read from an env-var.
overrideConfig = writeText "constants.local.php" ''
<?php
$thirdpartyExtensionsPath = getenv('THIRDPARTY_EXTENSIONS_PATH');
if (is_string($thirdpartyExtensionsPath) && $thirdpartyExtensionsPath !== "") {
define('THIRDPARTY_EXTENSIONS_PATH', $thirdpartyExtensionsPath . '/extensions');
}
'';
buildInputs = [ php ];
# There's nothing to build.
dontBuild = true;
installPhase = ''
runHook preInstall
mkdir -p $out
cp -vr * $out/
cp $overrideConfig $out/constants.local.php
runHook postInstall
'';
passthru.tests = {
inherit (nixosTests) freshrss;
};
meta = with lib; {
description = "FreshRSS is a free, self-hostable RSS aggregator";
homepage = "https://www.freshrss.org/";
license = licenses.agpl3Plus;
maintainers = with maintainers; [
stunkymonkey
];
};
}

View File

@@ -0,0 +1,140 @@
{
config,
lib,
fetchFromGitHub,
fetchFromGitLab,
callPackage,
}:
let
buildFreshRssExtension = (callPackage ./freshrss-utils.nix { }).buildFreshRssExtension;
official_extensions_version = "unstable-2024-04-27";
official_extensions_src = fetchFromGitHub {
owner = "FreshRSS";
repo = "Extensions";
rev = "71de129744ba37fd4cf363b78445f5345bc6d0b7";
hash = "sha256-A+hOjbGNfhwTOAMeo08MUdqfWxxetzLz865oQQDsQlg=";
};
baseExtensions =
_self:
lib.mapAttrs (_n: lib.recurseIntoAttrs) {
auto-ttl = buildFreshRssExtension rec {
FreshRssExtUniqueId = "AutoTTL";
pname = "auto-ttl";
version = "0.5.0";
src = fetchFromGitHub {
owner = "mgnsk";
repo = "FreshRSS-AutoTTL";
rev = "v${version}";
hash = "sha256-OiTiLZ2BjQD1W/BD8EkUt7WB2wOjL6GMGJ+APT4YpwE=";
};
meta = {
description = "FreshRSS extension for automatic feed refresh TTL based on the average frequency of entries";
homepage = "https://github.com/mgnsk/FreshRSS-AutoTTL";
license = lib.licenses.agpl3Only;
maintainers = [ lib.maintainers.stunkymonkey ];
};
};
demo = buildFreshRssExtension {
FreshRssExtUniqueId = "Demo";
pname = "demo";
version = "unstable-2023-12-22";
src = fetchFromGitHub {
owner = "FreshRSS";
repo = "xExtension-Demo";
rev = "8d60f71a2f0411f5fbbb1f88a57791cee0848f35";
hash = "sha256-5fe8TjefSiGMaeZkurxSJjX8qEEa1ArhJxDztp7ZNZc=";
};
meta = {
description = "FreshRSS Extension for the demo version";
homepage = "https://github.com/FreshRSS/xExtension-Demo";
license = lib.licenses.agpl3Only;
maintainers = [ lib.maintainers.stunkymonkey ];
};
};
reading-time = buildFreshRssExtension {
FreshRssExtUniqueId = "ReadingTime";
pname = "reading-time";
version = "1.5";
src = fetchFromGitLab {
domain = "framagit.org";
owner = "Lapineige";
repo = "FreshRSS_Extension-ReadingTime";
rev = "fb6e9e944ef6c5299fa56ffddbe04c41e5a34ebf";
hash = "sha256-C5cRfaphx4Qz2xg2z+v5qRji8WVSIpvzMbethTdSqsk=";
};
meta = {
description = "FreshRSS extension adding a reading time estimation next to each article";
homepage = "https://framagit.org/Lapineige/FreshRSS_Extension-ReadingTime";
license = lib.licenses.agpl3Only;
maintainers = [ lib.maintainers.stunkymonkey ];
};
};
reddit-image = buildFreshRssExtension rec {
FreshRssExtUniqueId = "RedditImage";
pname = "reddit-image";
version = "1.2.0";
src = fetchFromGitHub {
owner = "aledeg";
repo = "xExtension-RedditImage";
rev = "v${version}";
hash = "sha256-H/uxt441ygLL0RoUdtTn9Q6Q/Ois8RHlhF8eLpTza4Q=";
};
meta = {
description = "FreshRSS extension to process Reddit feeds";
homepage = "https://github.com/aledeg/xExtension-RedditImage";
license = lib.licenses.agpl3Only;
maintainers = [ lib.maintainers.stunkymonkey ];
};
};
title-wrap = buildFreshRssExtension {
FreshRssExtUniqueId = "TitleWrap";
pname = "title-wrap";
version = official_extensions_version;
src = official_extensions_src;
sourceRoot = "${official_extensions_src.name}/xExtension-TitleWrap";
meta = {
description = "FreshRSS extension instead of truncating the title is wrapped";
homepage = "https://github.com/FreshRSS/Extensions/tree/master/xExtension-TitleWrap";
license = lib.licenses.agpl3Only;
maintainers = [ lib.maintainers.stunkymonkey ];
};
};
youtube = buildFreshRssExtension {
FreshRssExtUniqueId = "YouTube";
pname = "youtube";
version = official_extensions_version;
src = official_extensions_src;
sourceRoot = "${official_extensions_src.name}/xExtension-YouTube";
meta = {
description = "FreshRSS extension allows you to directly watch YouTube/PeerTube videos from within subscribed channel feeds";
homepage = "https://github.com/FreshRSS/Extensions/tree/master/xExtension-YouTube";
license = lib.licenses.agpl3Only;
maintainers = [ lib.maintainers.stunkymonkey ];
};
};
};
# add possibility to define aliases
aliases = super: {
# example: RedditImage = super.reddit-image;
};
# overlays will be applied left to right, overrides should come after aliases.
overlays = lib.optionals config.allowAliases [
(_self: super: lib.recursiveUpdate super (aliases super))
];
toFix = lib.foldl' (lib.flip lib.extends) baseExtensions overlays;
in
(lib.fix toFix)
// {
inherit buildFreshRssExtension;
}

View File

@@ -0,0 +1,57 @@
{ stdenv, unzip }:
let
buildFreshRssExtension =
args@{
pname,
version,
src,
FreshRssExtUniqueId,
configurePhase ? ''
runHook preConfigure
runHook postConfigure
'',
buildPhase ? ''
runHook preBuild
runHook postBuild
'',
dontPatchELF ? true,
dontStrip ? true,
passthru ? { },
sourceRoot ? "source",
...
}:
stdenv.mkDerivation (
(removeAttrs args [ "FreshRssExtUniqueId" ])
// {
pname = "freshrss-extension-${pname}";
inherit
version
src
configurePhase
buildPhase
dontPatchELF
dontStrip
sourceRoot
;
installPrefix = "share/freshrss/extensions/xExtension-${FreshRssExtUniqueId}";
installPhase = ''
runHook preInstall
mkdir -p "$out/$installPrefix"
find . -mindepth 1 -maxdepth 1 | xargs -d'\n' mv -t "$out/$installPrefix/"
runHook postInstall
'';
passthru = passthru // {
inherit FreshRssExtUniqueId;
};
}
);
in
{
inherit buildFreshRssExtension;
}

View File

@@ -0,0 +1,8 @@
{
"serverVersion": "0.19.13",
"uiVersion": "0.19.13",
"serverHash": "sha256-EKZZsJ8B111z+5SC79arMQaPfhQBNX4uYXyRtU8yAJM=",
"serverCargoHash": "sha256-sMPLxuG3leCVHqTK4MD5F3RxbO7u6om/vb0opquoa3I=",
"uiHash": "sha256-SU/JS3LdSm4gEfwG9JXPH0WPzmT/8hiSEpuJdXpaywc=",
"uiPNPMDepsHash": "sha256-tuarUG1uKx6Q1O+rF6DHyK8MEseF9lKk34qtRWWScAg="
}

View File

@@ -0,0 +1,79 @@
{
lib,
stdenv,
rustPlatform,
fetchFromGitHub,
openssl,
libpq,
libiconv,
protobuf,
rustfmt,
nixosTests,
}:
let
pinData = lib.importJSON ./pin.json;
version = pinData.serverVersion;
in
rustPlatform.buildRustPackage rec {
inherit version;
pname = "lemmy-server";
src = fetchFromGitHub {
owner = "LemmyNet";
repo = "lemmy";
rev = version;
hash = pinData.serverHash;
fetchSubmodules = true;
};
preConfigure = ''
echo 'pub const VERSION: &str = "${version}";' > crates/utils/src/version.rs
'';
cargoHash = pinData.serverCargoHash;
buildInputs = [
libpq
]
++ lib.optionals stdenv.hostPlatform.isDarwin [
libiconv
];
# Using OPENSSL_NO_VENDOR is not an option on darwin
# As of version 0.10.35 rust-openssl looks for openssl on darwin
# with a hardcoded path to /usr/lib/libssl.x.x.x.dylib
# https://github.com/sfackler/rust-openssl/blob/master/openssl-sys/build/find_normal.rs#L115
OPENSSL_LIB_DIR = "${lib.getLib openssl}/lib";
OPENSSL_INCLUDE_DIR = "${openssl.dev}/include";
PROTOC = "${protobuf}/bin/protoc";
PROTOC_INCLUDE = "${protobuf}/include";
nativeBuildInputs = [
protobuf
rustfmt
];
checkFlags = [
# test requires database access
"--skip=session_middleware::tests::test_session_auth"
# tests require network access
"--skip=scheduled_tasks::tests::test_nodeinfo_mastodon_social"
"--skip=scheduled_tasks::tests::test_nodeinfo_lemmy_ml"
];
passthru.updateScript = ./update.py;
passthru.tests.lemmy-server = nixosTests.lemmy;
meta = with lib; {
description = "🐀 Building a federated alternative to reddit in rust";
homepage = "https://join-lemmy.org/";
license = licenses.agpl3Only;
maintainers = with maintainers; [
happysalada
billewanick
georgyo
];
mainProgram = "lemmy_server";
};
}

View File

@@ -0,0 +1,97 @@
{
lib,
stdenvNoCC,
libsass,
nodejs,
pnpm_9,
fetchFromGitHub,
nixosTests,
vips,
}:
let
pinData = lib.importJSON ./pin.json;
in
stdenvNoCC.mkDerivation (finalAttrs: {
pname = "lemmy-ui";
version = pinData.uiVersion;
src =
with finalAttrs;
fetchFromGitHub {
owner = "LemmyNet";
repo = pname;
rev = version;
fetchSubmodules = true;
hash = pinData.uiHash;
};
nativeBuildInputs = [
nodejs
pnpm_9.configHook
];
buildInputs = [
libsass
vips
];
extraBuildInputs = [ libsass ];
pnpmDeps = pnpm_9.fetchDeps {
inherit (finalAttrs) pname version src;
fetcherVersion = 1;
hash = pinData.uiPNPMDepsHash;
};
buildPhase = ''
runHook preBuild
pnpm build:prod
runHook postBuild
'';
# installPhase = ''
# runHook preInstall
# mkdir -p $out/{bin,lib/${finalAttrs.pname}}
# mv {dist,node_modules} $out/lib/${finalAttrs.pname}
# runHook postInstall
# '';
preInstall = ''
mkdir $out
cp -R ./dist $out
cp -R ./node_modules $out
'';
preFixup = ''
find $out -name libvips-cpp.so.42 -print0 | while read -d $'\0' libvips; do
echo replacing libvips at $libvips
rm $libvips
ln -s ${lib.getLib vips}/lib/libvips-cpp.so.42 $libvips
done
'';
distPhase = "true";
passthru.updateScript = ./update.py;
passthru.tests.lemmy-ui = nixosTests.lemmy;
passthru.commit_sha = finalAttrs.src.rev;
meta = with lib; {
description = "Building a federated alternative to reddit in rust";
homepage = "https://join-lemmy.org/";
license = licenses.agpl3Only;
maintainers = with maintainers; [
happysalada
billewanick
georgyo
];
inherit (nodejs.meta) platforms;
};
})

View File

@@ -0,0 +1,155 @@
#! /usr/bin/env nix-shell
#! nix-shell -i python3 -p python3 python3.pkgs.semver nix-prefetch-github
from urllib.request import Request, urlopen
import dataclasses
import subprocess
import os.path
import semver
from typing import (
Optional,
Dict,
List,
)
import json
import os
SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
NIXPKGS = os.path.abspath(os.path.join(SCRIPT_DIR, "../../../../"))
OWNER = "LemmyNet"
UI_REPO = "lemmy-ui"
SERVER_REPO = "lemmy"
@dataclasses.dataclass
class Pin:
serverVersion: str
uiVersion: str
serverHash: str = ""
serverCargoHash: str = ""
uiHash: str = ""
uiPNPMDepsHash: str = ""
filename: Optional[str] = None
def write(self) -> None:
if not self.filename:
raise ValueError("No filename set")
with open(self.filename, "w") as fd:
pin = dataclasses.asdict(self)
del pin["filename"]
json.dump(pin, fd, indent=2)
fd.write("\n")
def github_get(path: str) -> Dict:
"""Send a GET request to GitHub, optionally adding GITHUB_TOKEN auth header"""
url = f"https://api.github.com/{path.lstrip('/')}"
print(f"Retrieving {url}")
req = Request(url)
if "GITHUB_TOKEN" in os.environ:
req.add_header("authorization", f"Bearer {os.environ['GITHUB_TOKEN']}")
with urlopen(req) as resp:
return json.loads(resp.read())
def get_latest_release(owner: str, repo: str) -> str:
return github_get(f"/repos/{owner}/{repo}/releases/latest")["tag_name"]
def prefetch_github(owner: str, repo: str, rev: str) -> str:
"""Prefetch GitHub rev and return SRI hash"""
print(f"Prefetching {owner}/{repo}({rev})")
proc = subprocess.run(
["nix-prefetch-github", owner, repo, "--rev", rev, "--fetch-submodules"],
check=True,
stdout=subprocess.PIPE,
)
return json.loads(proc.stdout)["hash"]
def get_latest_tag(owner: str, repo: str, prerelease: bool = False) -> str:
"""Get the latest tag from a GitHub Repo"""
tags: List[str] = []
# As the GitHub API doesn't have any notion of "latest" for tags we need to
# collect all of them and sort so we can figure out the latest one.
i = 0
while i <= 100: # Prevent infinite looping
i += 1
resp = github_get(f"/repos/{owner}/{repo}/tags?page={i}")
if not resp:
break
# Filter out unparseable tags
for tag in resp:
try:
parsed = semver.Version.parse(tag["name"])
if (
semver.Version.parse(tag["name"])
and not prerelease
and parsed.prerelease
): # Filter out release candidates
continue
except ValueError:
continue
else:
tags.append(tag["name"])
# Sort and return latest
return sorted(tags, key=lambda name: semver.Version.parse(name))[-1]
def get_fod_hash(attr: str) -> str:
"""
Get fixed output hash for attribute.
This depends on a fixed output derivation with an empty hash.
"""
print(f"Getting fixed output hash for {attr}")
proc = subprocess.run(["nix-build", NIXPKGS, "-A", attr], stderr=subprocess.PIPE)
if proc.returncode != 1:
raise ValueError("Expected nix-build to fail")
# Iterate list in reverse order so we get the "got:" line early
for line in proc.stderr.decode().split("\n")[::-1]:
cols = line.split()
if cols and cols[0] == "got:":
return cols[1]
raise ValueError("No fixed output hash found")
def make_server_pin(pin: Pin, attr: str) -> None:
pin.serverHash = prefetch_github(OWNER, SERVER_REPO, pin.serverVersion)
pin.write()
pin.serverCargoHash = get_fod_hash(attr)
pin.write()
def make_ui_pin(pin: Pin, attr: str) -> None:
pin.uiHash = prefetch_github(OWNER, UI_REPO, pin.uiVersion)
pin.write()
pin.uiPNPMDepsHash = get_fod_hash(attr)
pin.write()
if __name__ == "__main__":
# Get server version
server_version = get_latest_tag(OWNER, SERVER_REPO)
# Get UI version (not always the same as lemmy-server)
ui_version = get_latest_tag(OWNER, UI_REPO)
pin = Pin(server_version, ui_version, filename=os.path.join(SCRIPT_DIR, "pin.json"))
make_server_pin(pin, "lemmy-server")
make_ui_pin(pin, "lemmy-ui")

View File

@@ -0,0 +1,146 @@
{
lib,
stdenv,
fetchurl,
writeText,
plugins ? [ ],
nixosTests,
}:
let
version = "5.0.2";
versionParts = lib.take 2 (lib.splitVersion version);
# 4.2 -> 402, 3.11 -> 311
stableVersion = lib.removePrefix "0" (
lib.concatMapStrings (
p:
if (lib.toInt p) < 10 then
(lib.concatStrings [
"0"
p
])
else
p
) versionParts
);
# Reference: https://docs.moodle.org/dev/Plugin_types
pluginDirs = {
mod = "mod";
antivirus = "lib/antivirus";
assignsubmission = "mod/assign/submission";
assignfeedback = "mod/assign/feedback";
booktool = "mod/book/tool";
customfield = "customfield/field";
datafield = "mod/data/field";
datapreset = "mod/data/preset";
ltisource = "mod/lti/source";
fileconverter = "files/converter";
ltiservice = "mod/lti/service";
mlbackend = "lib/mlbackend";
forumreport = "mod/forum/report";
quiz = "mod/quiz/report";
quizaccess = "mod/quiz/accessrule";
scormreport = "mod/scorm/report";
workshopform = "mod/workshop/form";
workshopallocation = "mod/workshop/allocation";
workshopeval = "mod/workshop/eval";
block = "blocks";
qtype = "question/type";
qbehaviour = "question/behaviour";
qformat = "question/format";
filter = "filter";
editor = "lib/editor";
atto = "lib/editor/atto/plugins";
tinymce = "lib/editor/tinymce/plugins";
enrol = "enrol";
auth = "auth";
tool = "admin/tool";
logstore = "admin/tool/log/store";
availability = "availability/condition";
calendartype = "calendar/type";
message = "message/output";
format = "course/format";
dataformat = "dataformat";
profilefield = "user/profile/field";
report = "report";
# coursereport = "course/report"; # Moved to /report
gradeexport = "grade/export";
gradeimport = "grade/import";
gradereport = "grade/report";
gradingform = "grade/grading/form";
mnetservice = "mnet/service";
webservice = "webservice";
repository = "repository";
portfolio = "portfolio";
search = "search/engine";
media = "media/player";
plagiarism = "plagiarism";
cachestore = "cache/stores";
cachelock = "cache/locks";
theme = "theme";
local = "local";
# assignment = "mod/assignment/type"; # Deprecated
# report = "admin/report"; # Moved to /report
contenttype = "contentbank/contenttype";
h5plib = "h5p/h5plib";
qbank = "question/bank";
};
in
stdenv.mkDerivation rec {
pname = "moodle";
inherit version;
src = fetchurl {
url = "https://download.moodle.org/download.php/direct/stable${stableVersion}/${pname}-${version}.tgz";
hash = "sha256-p9kXrUnsFNHJ3k5EwSYO/iXNlN1AanOGln1TQSFiCUI=";
};
phpConfig = writeText "config.php" ''
<?php
return require(getenv('MOODLE_CONFIG'));
?>
'';
installPhase = ''
runHook preInstall
mkdir -p $out/share/moodle
cp -r . $out/share/moodle
cp ${phpConfig} $out/share/moodle/config.php
${lib.concatStringsSep "\n" (
map (
p:
let
dir =
if (lib.hasAttr p.pluginType pluginDirs) then
pluginDirs.${p.pluginType}
else
throw "unknown moodle plugin type";
# we have to copy it, because the plugins have refrences to .. inside
in
''
mkdir -p $out/share/moodle/${dir}/${p.name}
cp -r ${p}/* $out/share/moodle/${dir}/${p.name}/
''
) plugins
)}
runHook postInstall
'';
passthru.tests = {
inherit (nixosTests) moodle;
};
meta = with lib; {
description = "Free and open-source learning management system (LMS) written in PHP";
license = licenses.gpl3Plus;
homepage = "https://moodle.org/";
maintainers = with maintainers; [ freezeboy ];
platforms = platforms.all;
};
}

View File

@@ -0,0 +1,38 @@
{ stdenv, unzip, ... }:
let
buildMoodlePlugin =
a@{
name,
src,
pluginType,
configurePhase ? ":",
buildPhase ? ":",
buildInputs ? [ ],
nativeBuildInputs ? [ ],
...
}:
stdenv.mkDerivation (
a
// {
name = name;
inherit pluginType;
inherit configurePhase buildPhase buildInputs;
nativeBuildInputs = [ unzip ] ++ nativeBuildInputs;
installPhase = ''
runHook preInstall
mkdir -p "$out"
mv * $out/
runHook postInstall
'';
}
);
in
{
inherit buildMoodlePlugin;
}

View File

@@ -0,0 +1,103 @@
{
stdenv,
lib,
fetchFromGitHub,
fetchYarnDeps,
makeWrapper,
nix-update-script,
prefetch-yarn-deps,
fixup-yarn-lock,
nodejs,
yarn,
nixosTests,
}:
stdenv.mkDerivation rec {
pname = "outline";
version = "0.87.4";
src = fetchFromGitHub {
owner = "outline";
repo = "outline";
rev = "v${version}";
hash = "sha256-gsQPDbKTzsXV8y8/xMxmhJM6pI+zDkx/r1Zk83ixb7k=";
};
nativeBuildInputs = [
makeWrapper
prefetch-yarn-deps
fixup-yarn-lock
];
buildInputs = [
yarn
nodejs
];
yarnOfflineCache = fetchYarnDeps {
yarnLock = "${src}/yarn.lock";
hash = "sha256-/bWDFIGElBc1lMODKTxmSkal9c4L1iTPd521/DVYyxo=";
};
configurePhase = ''
export HOME=$(mktemp -d)/yarn_home
'';
buildPhase = ''
runHook preBuild
export NODE_OPTIONS=--openssl-legacy-provider
yarn config --offline set yarn-offline-mirror $yarnOfflineCache
fixup-yarn-lock yarn.lock
yarn install --offline \
--frozen-lockfile \
--ignore-engines --ignore-scripts
patchShebangs node_modules/
# apply upstream patches with `patch-package`
yarn run postinstall
yarn build
runHook postBuild
'';
installPhase = ''
runHook preInstall
mkdir -p $out/bin $out/share/outline
mv build server public node_modules $out/share/outline/
node_modules=$out/share/outline/node_modules
build=$out/share/outline/build
server=$out/share/outline/server
makeWrapper ${nodejs}/bin/node $out/bin/outline-server \
--add-flags $build/server/index.js \
--set NODE_ENV production \
--set NODE_PATH $node_modules \
--prefix PATH : ${lib.makeBinPath [ nodejs ]} # required to run migrations
runHook postInstall
'';
passthru = {
tests = {
basic-functionality = nixosTests.outline;
};
updateScript = nix-update-script { };
# alias for nix-update to be able to find and update this attribute
offlineCache = yarnOfflineCache;
};
meta = with lib; {
description = "Fastest wiki and knowledge base for growing teams. Beautiful, feature rich, and markdown compatible";
homepage = "https://www.getoutline.com/";
changelog = "https://github.com/outline/outline/releases";
license = licenses.bsl11;
maintainers = with maintainers; [
cab404
yrd
];
teams = [ teams.cyberus ];
platforms = platforms.linux;
};
}

View File

@@ -0,0 +1,50 @@
{
lib,
buildNpmPackage,
vips,
pkg-config,
prisma,
src,
version,
nixosTests,
}:
buildNpmPackage {
pname = "pingvin-share-backend";
inherit version;
src = "${src}/backend";
npmInstallFlags = [ "--build-from-source" ];
installPhase = ''
cp -r . $out
ln -s $out/node_modules/.bin $out/bin
'';
preBuild = ''
prisma generate
'';
buildInputs = [ vips ];
nativeBuildInputs = [
pkg-config
prisma
];
npmDepsHash = "sha256-bc2suSGa7YTonIhUxEtNzdIUeUBubwJ6upW2tydVCnU=";
makeCacheWritable = true;
npmFlags = [ "--legacy-peer-deps" ];
passthru.tests = {
pingvin-share = nixosTests.pingvin-share;
};
meta = with lib; {
description = "Backend of pingvin-share, a self-hosted file sharing platform";
homepage = "https://github.com/stonith404/pingvin-share";
downloadPage = "https://github.com/stonith404/pingvin-share/releases";
changelog = "https://github.com/stonith404/pingvin-share/releases/tag/v${version}";
license = licenses.bsd2;
maintainers = with maintainers; [ ratcornu ];
};
}

View File

@@ -0,0 +1,21 @@
{
callPackage,
fetchFromGitHub,
recurseIntoAttrs,
}:
let
version = "1.13.0";
src = fetchFromGitHub {
owner = "stonith404";
repo = "pingvin-share";
rev = "v${version}";
hash = "sha256-FWc0Yo2Phh8ee5izHj0ol1pwLSVJgIqyeaJo1o4drsM=";
};
in
recurseIntoAttrs {
backend = callPackage ./backend.nix { inherit src version; };
frontend = callPackage ./frontend.nix { inherit src version; };
}

View File

@@ -0,0 +1,42 @@
{
lib,
buildNpmPackage,
vips,
pkg-config,
src,
version,
nixosTests,
}:
buildNpmPackage {
pname = "pingvin-share-frontend";
inherit version;
src = "${src}/frontend";
npmInstallFlags = [ "--build-from-source" ];
installPhase = ''
cp -r . $out
ln -s $out/node_modules/.bin $out/bin
'';
buildInputs = [ vips ];
nativeBuildInputs = [ pkg-config ];
npmDepsHash = "sha256-ykq98Bd67TY/t8JYraii7XnCIoSLk454decdHpQGorw=";
makeCacheWritable = true;
npmFlags = [ "--legacy-peer-deps" ];
passthru.tests = {
pingvin-share = nixosTests.pingvin-share;
};
meta = with lib; {
description = "Frontend of pingvin-share, a self-hosted file sharing platform";
homepage = "https://github.com/stonith404/pingvin-share";
downloadPage = "https://github.com/stonith404/pingvin-share/releases";
changelog = "https://github.com/stonith404/pingvin-share/releases/tag/v${version}";
license = licenses.bsd2;
maintainers = with maintainers; [ ratcornu ];
};
}

View File

@@ -0,0 +1,66 @@
commit f89ce378d3b405d69635da28dfd57adced23aa17
Author: kuflierl <41301536+kuflierl@users.noreply.github.com>
Date: Mon Sep 15 20:14:08 2025 +0200
server: replace pillow-avif-plugin, pyheif, heif-image-plugin with pillow-heif
diff --git a/requirements.txt b/requirements.txt
index ffe18f0c..16a72750 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,12 +1,10 @@
alembic>=0.8.5
certifi>=2017.11.5
coloredlogs==5.0
-heif-image-plugin==0.3.2
numpy>=1.8.2
-pillow-avif-plugin~=1.1.0
-pillow>=4.3.0
+pillow>=11.2.1
+pillow-heif>=1.0.0
psycopg2-binary>=2.6.1
-pyheif==0.6.1
pynacl>=1.2.1
pyRFC3339>=1.0
pytz>=2018.3
diff --git a/szurubooru/func/image_hash.py b/szurubooru/func/image_hash.py
index 76d5a846..b89541eb 100644
--- a/szurubooru/func/image_hash.py
+++ b/szurubooru/func/image_hash.py
@@ -4,13 +4,13 @@ from datetime import datetime
from io import BytesIO
from typing import Any, Callable, List, Optional, Set, Tuple
-import HeifImagePlugin
+from pillow_heif import register_heif_opener
import numpy as np
-import pillow_avif
from PIL import Image
from szurubooru import config, errors
+register_heif_opener()
logger = logging.getLogger(__name__)
# Math based on paper from H. Chi Wong, Marshall Bern and David Goldberg
diff --git a/szurubooru/func/images.py b/szurubooru/func/images.py
index e135d182..f4b5aa5b 100644
--- a/szurubooru/func/images.py
+++ b/szurubooru/func/images.py
@@ -7,14 +7,14 @@ import subprocess
from io import BytesIO
from typing import List
-import HeifImagePlugin
-import pillow_avif
+from pillow_heif import register_heif_opener
from PIL import Image as PILImage
from szurubooru import errors
from szurubooru.func import mime, util
logger = logging.getLogger(__name__)
+register_heif_opener()
def convert_heif_to_png(content: bytes) -> bytes:

View File

@@ -0,0 +1,36 @@
{
src,
version,
lib,
buildNpmPackage,
}:
buildNpmPackage {
pname = "szurubooru-client";
inherit version;
src = "${src}/client";
npmDepsHash = "sha256-HtcitZl2idgVleB6c0KCTSNLxh7hP8/G/RGdMaQG3iI=";
makeCacheWritable = true;
npmBuildFlags = [
"--gzip"
];
installPhase = ''
runHook preInstall
mkdir $out
mv ./public/* $out
runHook postInstall
'';
meta = with lib; {
description = "Client of szurubooru, an image board engine for small and medium communities";
homepage = "https://github.com/rr-/szurubooru";
license = licenses.gpl3;
maintainers = with maintainers; [ ratcornu ];
};
}

View File

@@ -0,0 +1,20 @@
{
callPackage,
fetchFromGitHub,
recurseIntoAttrs,
}:
let
version = "2.5-unstable-2025-07-19";
src = fetchFromGitHub {
owner = "rr-";
repo = "szurubooru";
rev = "5a0f8867f3af1556d82c1ad7e29977903300c2dd";
hash = "sha256-ihocmBS4h23bb4ZRhHEXvnHiNfRMPdUe94B5K9bi2E4=";
};
in
recurseIntoAttrs {
client = callPackage ./client.nix { inherit src version; };
server = callPackage ./server.nix { inherit src version; };
}

View File

@@ -0,0 +1,84 @@
{
src,
version,
lib,
nixosTests,
fetchPypi,
python3,
}:
let
overrides = [
(self: super: {
alembic = super.alembic.overridePythonAttrs (oldAttrs: rec {
version = "1.14.1";
src = fetchPypi {
pname = "alembic";
inherit version;
sha256 = "sha256-SW6IgkWlOt8UmPyrMXE6Rpxlg2+N524BOZqhw+kN0hM=";
};
doCheck = false;
});
sqlalchemy = super.sqlalchemy.overridePythonAttrs (oldAttrs: rec {
version = "1.3.23";
src = fetchPypi {
pname = "SQLAlchemy";
inherit version;
sha256 = "sha256-b8ozZyV4Zm9lfBMVUsTviXnBYG5JT3jNUZl0LfsmkYs=";
};
doCheck = false;
});
})
];
python = python3.override {
self = python;
packageOverrides = lib.composeManyExtensions overrides;
};
in
python.pkgs.buildPythonApplication {
pname = "szurubooru-server";
inherit version;
pyproject = true;
src = "${src}/server";
patches = [
./001-server-pillow-heif.patch
];
nativeBuildInputs = with python.pkgs; [ setuptools ];
propagatedBuildInputs = with python.pkgs; [
alembic
certifi
coloredlogs
legacy-cgi
numpy
pillow
pillow-heif
psycopg2-binary
pynacl
pyrfc3339
pytz
pyyaml
sqlalchemy
yt-dlp
];
postInstall = ''
mkdir $out/bin
install -m0755 $src/szuru-admin $out/bin/szuru-admin
'';
passthru.tests.szurubooru = nixosTests.szurubooru;
meta = with lib; {
description = "Server of szurubooru, an image board engine for small and medium communities";
homepage = "https://github.com/rr-/szurubooru";
license = licenses.gpl3;
maintainers = with maintainers; [ ratcornu ];
};
}

View File

@@ -0,0 +1,12 @@
{ callPackage }:
builtins.mapAttrs (_: callPackage ./generic.nix) rec {
wordpress = wordpress_6_8;
wordpress_6_7 = {
version = "6.7.2";
hash = "sha256-z9nIPPqd2gNRiY6ptz9YmVyBeZSlQkvhh3f4PohqPPY=";
};
wordpress_6_8 = {
version = "6.8.3";
hash = "sha256-kto0yZYOZNElhlLB73PFF/fkasbf0t/HVDbThVr0aww=";
};
}

View File

@@ -0,0 +1,57 @@
{
lib,
version,
hash,
stdenv,
fetchurl,
nixosTests,
writeScript,
}:
stdenv.mkDerivation rec {
pname = "wordpress";
inherit version;
src = fetchurl {
url = "https://wordpress.org/${pname}-${version}.tar.gz";
inherit hash;
};
installPhase = ''
runHook preInstall
# remove non-essential plugins and themes
rm -r wp-content/{plugins,themes}
mkdir wp-content/plugins
cat << EOF > wp-content/plugins/index.php
<?php
// Silence is golden.
EOF
cp -a wp-content/{plugins,themes}
mkdir -p $out/share/wordpress
cp -r . $out/share/wordpress
runHook postInstall
'';
passthru.tests = {
inherit (nixosTests) wordpress;
};
passthru.updateScript = writeScript "update.sh" ''
#!/usr/bin/env nix-shell
#!nix-shell -i bash -p common-updater-scripts jq
set -eu -o pipefail
version=$(curl --globoff "https://api.wordpress.org/core/version-check/1.7/" | jq -r '.offers[0].version')
update-source-version wordpress $version --file=./pkgs/servers/web-apps/wordpress/default.nix
'';
meta = with lib; {
homepage = "https://wordpress.org";
description = "Open source software you can use to create a beautiful website, blog, or app";
license = [ licenses.gpl2Plus ];
maintainers = [ maintainers.basvandijk ];
platforms = platforms.all;
};
}

View File

@@ -0,0 +1,48 @@
= Adding plugin, theme or language =
To extend the wordpressPackages set, add a new line to the corresponding json
file with the codename of the package:
- `wordpress-languages.json` for language packs
- `wordpress-themes.json` for themes
- `wordpress-plugins.json` for plugins
The codename is the last part in the url of the plugin or theme page, for
example `cookie-notice` in in the url
`https://wordpress.org/plugins/cookie-notice/` or `twentytwenty` in
`https://wordpress.org/themes/twentytwenty/`.
In case of language packages, the name consists of country and language codes.
For example `de_DE` for country code `de` (Germany) and language `DE` (German).
For available translations and language codes see [upstream translation repository](https://translate.wordpress.org).
To regenerate the nixpkgs wordpressPackages set, run:
```
./generate.sh
```
After that you can commit and submit the changes.
= Usage with the Wordpress module =
The plugins will be available in the namespace `wordpressPackages.plugins`.
Using it together with the Wordpress module could look like this:
```nix
{
services.wordpress = {
sites."blog.${config.networking.domain}" = {
plugins = with pkgs.wordpressPackages.plugins; [
anti-spam-bee
code-syntax-block
cookie-notice
lightbox-with-photoswipe
wp-gdpr-compliance
];
};
};
}
```
The same scheme applies to `themes` and `languages`.

View File

@@ -0,0 +1,207 @@
# Source: https://git.helsinki.tools/helsinki-systems/wp4nix/-/blob/master/default.nix
# Licensed under: MIT
# Slightly modified
{
lib,
newScope,
plugins,
themes,
languages,
callPackage,
}:
let
packages =
self:
let
generatedJson = {
inherit plugins themes languages;
};
sourceJson = {
plugins = builtins.fromJSON (builtins.readFile ./wordpress-plugins.json);
themes = builtins.fromJSON (builtins.readFile ./wordpress-themes.json);
languages = builtins.fromJSON (builtins.readFile ./wordpress-languages.json);
};
in
{
# Create a generic WordPress package. Most arguments are just passed
# to `mkDerivation`. The version is automatically filtered for weird characters.
mkWordpressDerivation = self.callPackage (
{
stdenvNoCC,
lib,
filterWPString,
gettext,
wp-cli,
}:
{
type,
pname,
version,
license,
...
}@args:
assert lib.any (x: x == type) [
"plugin"
"theme"
"language"
];
stdenvNoCC.mkDerivation (
{
pname = "wordpress-${type}-${pname}";
version = filterWPString version;
dontConfigure = true;
dontBuild = true;
installPhase = ''
runHook preInstall
cp -R ./. $out
runHook postInstall
'';
passthru = {
wpName = pname;
};
meta = {
license = lib.licenses.${license};
}
// (args.passthru or { });
}
// lib.optionalAttrs (type == "language") {
nativeBuildInputs = [
gettext
wp-cli
];
dontBuild = false;
buildPhase = ''
runHook preBuild
find -name '*.po' -print0 | while IFS= read -d "" -r po; do
msgfmt -o $(basename "$po" .po).mo "$po"
done
wp i18n make-json .
rm *.po
runHook postBuild
'';
}
// removeAttrs args [
"type"
"pname"
"version"
"passthru"
]
)
) { };
# Create a derivation from the official wordpress.org packages.
# This takes the type, the pname and the data generated from the go tool.
mkOfficialWordpressDerivation = self.callPackage (
{ mkWordpressDerivation, fetchWordpress }:
{
type,
pname,
data,
license,
}:
mkWordpressDerivation {
inherit type pname license;
version = data.version;
src = fetchWordpress type data;
}
) { };
# Filter out all characters that might occur in a version string but that that are not allowed
# in store paths.
filterWPString =
builtins.replaceStrings
[
" "
","
"/"
"&"
";"
''"''
"'"
"$"
":"
"("
")"
"["
"]"
"{"
"}"
"|"
"*"
"\t"
]
[
"_"
"."
"."
""
""
""
""
""
""
""
""
""
""
""
""
"-"
""
""
];
# Fetch a package from the official wordpress.org SVN.
# The data supplied is the data straight from the go tool.
fetchWordpress = self.callPackage (
{ fetchsvn }:
type: data:
fetchsvn {
inherit (data) rev sha256;
url =
if type == "plugin" || type == "theme" then
"https://" + type + "s.svn.wordpress.org/" + data.path
else if type == "language" then
"https://i18n.svn.wordpress.org/core/" + data.version + "/" + data.path
else if type == "pluginLanguage" then
"https://i18n.svn.wordpress.org/plugins/" + data.path
else if type == "themeLanguage" then
"https://i18n.svn.wordpress.org/themes/" + data.path
else
throw "fetchWordpress: invalid package type ${type}";
}
) { };
}
// lib.mapAttrs (
type: pkgs:
lib.recurseIntoAttrs (
lib.makeExtensible (
_:
lib.mapAttrs (
pname: data:
self.mkOfficialWordpressDerivation {
type = lib.removeSuffix "s" type;
inherit pname data;
license = sourceJson.${type}.${pname};
}
) pkgs
)
)
) generatedJson;
in
# This creates an extensible scope.
lib.recursiveUpdate ((lib.makeExtensible (_: (lib.makeScope newScope packages))).extend (
selfWP: superWP: { }
)) (callPackage ./thirdparty.nix { })

View File

@@ -0,0 +1,23 @@
#!/usr/bin/env nix-shell
#!nix-shell -i bash -p wp4nix jq
set -e
set -u
set -o pipefail
set -x
cd $(dirname "$0")
nixFlags="--option experimental-features nix-command eval --raw --impure --expr"
export NIX_PATH=nixpkgs=../../../../..
export WP_VERSION=$(nix $nixFlags '(import <nixpkgs> {}).wordpress.version')
PLUGINS=`cat wordpress-plugins.json | jq -r 'keys|.[]' | sed -z 's/\n/,/g;s/,$/\n/'`
THEMES=`cat wordpress-themes.json | jq -r 'keys|.[]' | sed -z 's/\n/,/g;s/,$/\n/'`
LANGUAGES=`cat wordpress-languages.json | jq -r 'keys|.[]' | sed -z 's/\n/,/g;s/,$/\n/'`
wp4nix -p $PLUGINS -pl en
wp4nix -t $THEMES -tl en
wp4nix -l $LANGUAGES
rm *.log themeLanguages.json pluginLanguages.json

View File

@@ -0,0 +1,26 @@
{
"de_DE": {
"path": "de_DE",
"rev": "1551261",
"sha256": "0d4kxfzvpyp9p4kl7mfhvm2pilh27rbvsd3hv3p0y8hl33r96avb",
"version": "6.6"
},
"fr_FR": {
"path": "fr_FR",
"rev": "1566738",
"sha256": "1x4sxs40fal6qlbj9x8f0wwbji20729l25axcxx62rd98y47llg5",
"version": "6.6"
},
"ro_RO": {
"path": "ro_RO",
"rev": "1551215",
"sha256": "00i2grjcr7n2bqknff39ar7maz7gk7d17dqrl2p9smlhkj6m1bbp",
"version": "6.6"
},
"ru_RU": {
"path": "ru_RU",
"rev": "1551262",
"sha256": "0d5bdq99h9g6pcs3fw7czb4w4p60cjiizxqlbzan4p1g9056mmbl",
"version": "6.6"
}
}

View File

@@ -0,0 +1,260 @@
{
"add-widget-after-content": {
"path": "add-widget-after-content/tags/2.5.2",
"rev": "3172493",
"sha256": "0mw51q59wlr0y43la9fchimsp41gzgcapn7f9fdzvr42d3kwm3la",
"version": "2.5.2"
},
"akismet": {
"path": "akismet/tags/5.3.7",
"rev": "3272824",
"sha256": "0vpvzp0hf9b5ga4snlbh3k6z4vqwzxgzhgz61n62g0qgxkgk0qv1",
"version": "5.3.7"
},
"antispam-bee": {
"path": "antispam-bee/tags/2.11.7",
"rev": "3186018",
"sha256": "1scq6mqbalqvjb82cl55w9i8mzqr60rw4r7yfrln9plxi9bpmzgb",
"version": "2.11.7"
},
"async-javascript": {
"path": "async-javascript/tags/2.21.08.31",
"rev": "2929532",
"sha256": "0v9lrbxcgk6diz927q36nx45nbl6hm8bdig9lc0gj42i183y3g61",
"version": "2.21.08.31"
},
"breeze": {
"path": "breeze/tags/2.2.9",
"rev": "3270307",
"sha256": "19n5zrdswj4mi23355a13k4j194119nw70g95c0irxy78lv74zhm",
"version": "2.2.9"
},
"co-authors-plus": {
"path": "co-authors-plus/tags/3.6.5",
"rev": "3273514",
"sha256": "1jmcimc58psxlkk3pl57l5270f7w26vsx23j3mdlxh455vj5iavf",
"version": "3.6.5"
},
"code-syntax-block": {
"path": "code-syntax-block/tags/3.2.1",
"rev": "3083143",
"sha256": "0hcvix71g2nh2yws0j3rll2dk3ybf39i04m7qz9yrnva6s17g6l6",
"version": "3.2.1"
},
"cookie-notice": {
"path": "cookie-notice/tags/2.5.6",
"rev": "3262965",
"sha256": "1h7avy7mni4cfvh672vnk6n4npz57mpgm8xssp089hn8vqj2d1zx",
"version": "2.5.6"
},
"disable-xml-rpc": {
"path": "disable-xml-rpc/tags/1.0.1",
"rev": "2954460",
"sha256": "03vay6j7ac44pg55hlm02lglm3ggmjxdq95dhh0cmavbiafimhqq",
"version": "1.0.1"
},
"embed-extended": {
"path": "embed-extended/tags/1.4.0",
"rev": "2982701",
"sha256": "1qfxy9rp6ipp6r6m70vr30clbm2akssra4jbk8fss3qiz85rmfxa",
"version": "1.4.0"
},
"gutenberg": {
"path": "gutenberg/tags/20.6.0",
"rev": "3266305",
"sha256": "09sjm22lg5n07pi53xbaf47719zlp1nb7cmhkxd6pwdz3sik7xcx",
"version": "20.6.0"
},
"hcaptcha-for-forms-and-more": {
"path": "hcaptcha-for-forms-and-more/tags/4.12.0",
"rev": "3265103",
"sha256": "0b8blf03g8vaw1i22rl3swknyqwq28bv8fmk2fd6a64phrsbdpvj",
"version": "4.12.0"
},
"hello-dolly": {
"path": "hello-dolly/tags/1.7.2",
"rev": "2807593",
"sha256": "0zzbzdkzpgc65djn3694li82zc2q25q3zzv0kqjr7zwqmnrli0jp",
"version": "1.7.2"
},
"hkdev-maintenance-mode": {
"path": "hkdev-maintenance-mode/tags/3.1.3",
"rev": "3252095",
"sha256": "1znf09ld180qkfzyxigm5xhzqvfrlvx4g4j0f66a9fny4kpfk9jq",
"version": "3.1.3"
},
"jetpack": {
"path": "jetpack/tags/14.5",
"rev": "3265712",
"sha256": "0bibdqlv88hhk6xdlaq62264slqf0nild9mqzkbglzl2zybpfyjx",
"version": "14.5"
},
"jetpack-lite": {
"path": "jetpack-lite/tags/3.0.3",
"rev": "1895157",
"sha256": "04wq8cnhzgzrhm5pjwicsnavc46n6wdmb6xf8gz4wwl1di2hl471",
"version": "3.0.3"
},
"lightbox-photoswipe": {
"path": "lightbox-photoswipe/tags/5.6.1",
"rev": "3213779",
"sha256": "1p6w9bcb8irq38zsr2m14lnaq4hdjqvrcw7dr0603p00wnr9hc3k",
"version": "5.6.1"
},
"login-lockdown": {
"path": "login-lockdown/tags/2.11",
"rev": "3274659",
"sha256": "0hs8mv7w0fxad05fj5v5867azy4zd5x05918jq362f6qj18ci8xm",
"version": "2.11"
},
"mailpoet": {
"path": "mailpoet/tags/5.10.1",
"rev": "3273602",
"sha256": "0kzvc7841v5zl10vvsqmywm1i4smic4vvb3kl03a905j2flsjwm3",
"version": "5.10.1"
},
"merge-minify-refresh": {
"path": "merge-minify-refresh/trunk",
"rev": "3126978",
"sha256": "1xrr7ddriagd8hh6f0n9bkfqsc32rvzb9prbrh1r1k6qr84z0pi6",
"version": "2.12"
},
"opengraph": {
"path": "opengraph/tags/2.0.2",
"rev": "3246616",
"sha256": "1jphg0w6mm021kxypgz7hh04hyw7v7g95gdm35mq34z39h29hkbp",
"version": "2.0.2"
},
"simple-login-captcha": {
"path": "simple-login-captcha/tags/1.3.6",
"rev": "3272733",
"sha256": "1p0lhhqn9bca900bdbp5lnzq8mj16s3bic039ndrqzhj1wd87fy1",
"version": "1.3.6"
},
"simple-mastodon-verification": {
"path": "simple-mastodon-verification/tags/2.0.3",
"rev": "3169544",
"sha256": "12gh5ih4rkbdcrzdjml9rrlipbp2ymwhwxvr8y7lawmrflsas3r5",
"version": "2.0.3"
},
"so-clean-up-wp-seo": {
"path": "so-clean-up-wp-seo/tags/4.0.2",
"rev": "3114751",
"sha256": "1kqgmmaw99b164v554siygrxa3z7lxqhn0bwg7s01cm5fdg6i3dl",
"version": "4.0.2"
},
"sqlite-database-integration": {
"path": "sqlite-database-integration/tags/2.2.3",
"rev": "3322285",
"sha256": "1fggp3qpcdjk6a92wlv41kqmvnhs7dg1pb1ahan9n9wyja48acn8",
"version": "2.2.3"
},
"static-mail-sender-configurator": {
"path": "static-mail-sender-configurator/tags/0.10.0",
"rev": "2941521",
"sha256": "1mrwgqp1ril54xqr8k2gwgjcsbf4xv3671v15xawapwz730h2c4r",
"version": "0.10.0"
},
"surge": {
"path": "surge/tags/1.1.0",
"rev": "3146952",
"sha256": "16p75r1qcr4m1gajgw3bmpk3pvkpmrz3sh6pvi775hgs594f4vhc",
"version": "1.1.0"
},
"tc-custom-javascript": {
"path": "tc-custom-javascript/tags/1.2.3",
"rev": "2870386",
"sha256": "0lcprrnf25p6a12mf5hkfnl6r470n35pgfdl9nizjh4q43qzdcam",
"version": "1.2.3"
},
"webp-converter-for-media": {
"path": "webp-converter-for-media/tags/6.2.1",
"rev": "3265172",
"sha256": "13affcpq23s3gjsd7mja86j3a7vgv4kyaca77gxjsp1nbiba9nk5",
"version": "6.2.1"
},
"webp-express": {
"path": "webp-express/tags/0.25.9",
"rev": "3066149",
"sha256": "1rcd6qxpq569w8hk01h2k807n9qwvz2qv4g33n7spzsxpgqiicgh",
"version": "0.25.9"
},
"wordpress-seo": {
"path": "wordpress-seo/tags/24.9",
"rev": "3273107",
"sha256": "04b541yryi1xjkrj9ydr2yy7dasc1557f32asq6mppbyn2ia54xq",
"version": "24.9"
},
"worker": {
"path": "worker/tags/4.9.20",
"rev": "3087053",
"sha256": "0krm85iyk25s2fy7z16z0k9cjvhw31y5w6wfjbsl7cfz0q3ld6j5",
"version": "4.9.20"
},
"wp-change-email-sender": {
"path": "wp-change-email-sender/tags/3.0",
"rev": "3163024",
"sha256": "12r17xxwrnci5v18x71y44289z5dvvrj8xr3sfl1ipvlrvzggbfh",
"version": "3.0"
},
"wp-fail2ban": {
"path": "wp-fail2ban/tags/5.4.0.1",
"rev": "3230788",
"sha256": "1lzm42lx810h1fpn9qfi9az4ssmxsysx6lpcpfs6y815a4ik0dc4",
"version": "5.4.0.1"
},
"wp-fail2ban-addon-contact-form-7": {
"path": "wp-fail2ban-addon-contact-form-7/tags/2.0.0",
"rev": "3150733",
"sha256": "0xixgpkibyp9diwnfdr5pyyf3z1ll9wkps5cdhpqcikaapdpj45f",
"version": "2.0.0"
},
"wp-fastest-cache": {
"path": "wp-fastest-cache/tags/1.3.6",
"rev": "3271461",
"sha256": "1m06zrpq8iya8pkra99ajkv74lqqfgwdv74ywjnf23h57cli609a",
"version": "1.3.6"
},
"wp-gdpr-compliance": {
"path": "wp-gdpr-compliance/tags/2.0.22",
"rev": "2865556",
"sha256": "0zgn3pg2zhqqv89rl6pqwd3p3hvspsnn47iab7xw0d79nby0nh7c",
"version": "2.0.22"
},
"wp-import-export-lite": {
"path": "wp-import-export-lite/trunk",
"rev": "3274100",
"sha256": "1s7hqsh5xvwd84349a2rkxv3bqi7y86m5q6x0y7qgm889m3d2hli",
"version": "3.9.28"
},
"wp-mail-smtp": {
"path": "wp-mail-smtp/tags/4.4.0",
"rev": "3251178",
"sha256": "0rg9rdd675zrc9x1vxb552v10gk0jk2lq6pkbd4kbcmh851r55zb",
"version": "4.4.0"
},
"wp-statistics": {
"path": "wp-statistics/tags/14.13.1",
"rev": "3268590",
"sha256": "0xr04pa8f24lril2svd0g7hd4hgw6nvcv3ys5wvn32byjd8pxx2c",
"version": "14.13.1"
},
"wp-swiper": {
"path": "wp-swiper/trunk",
"rev": "3220490",
"sha256": "091rl79z5y9qvvdlcfx9czfrrji0ifipkg7l02n91331fi02ij07",
"version": "1.2.17"
},
"wp-user-avatars": {
"path": "wp-user-avatars/trunk",
"rev": "2540784",
"sha256": "1g21nl6xs9zyq0ainjwa06wl90975l8f9rj0fa20zkmw17w2mdgl",
"version": "1.4.1"
},
"wpforms-lite": {
"path": "wpforms-lite/tags/1.9.4.2",
"rev": "3254748",
"sha256": "087iw17maiv84cmyv0lmpr8fafijr3m7xw36jdwbd3kfi57rwmsz",
"version": "1.9.4.2"
}
}

View File

@@ -0,0 +1,44 @@
{
"twentynineteen": {
"path": "twentynineteen/3.1",
"rev": "267655",
"sha256": "0w6vq93s54j8c02613h9hmjjzs15aasazbi96c6k0ns8395dzl2i",
"version": "3.1"
},
"twentytwenty": {
"path": "twentytwenty/2.9",
"rev": "267656",
"sha256": "1hkbsy5w5qzbvlsaj16zwnmq0hzhnlqb6ikjyg0fliyddlxnjyi0",
"version": "2.9"
},
"twentytwentyfive": {
"path": "twentytwentyfive/1.2",
"rev": "267661",
"sha256": "1sm5ifdgnxgmg0pkaik98hnqmcfmjk552994a0gd4mpp137d3f1n",
"version": "1.2"
},
"twentytwentyfour": {
"path": "twentytwentyfour/1.3",
"rev": "248600",
"sha256": "12zfb83s1zgbs3r8an17hdwzn7s01hfwhxd5ak5x6106cy61nshq",
"version": "1.3"
},
"twentytwentyone": {
"path": "twentytwentyone/2.5",
"rev": "267659",
"sha256": "06jb3wx0mwfkv0yb1vi2prx9i13xw2lr3xb7qkv5vlc7dc08rb5r",
"version": "2.5"
},
"twentytwentythree": {
"path": "twentytwentythree/1.6",
"rev": "248602",
"sha256": "0q8qz75a2yaf4lqj84w4hfcizjj7fvgbq0rinag4abk7ivdys537",
"version": "1.6"
},
"twentytwentytwo": {
"path": "twentytwentytwo/2.0",
"rev": "267660",
"sha256": "0b34rz0jpxzc0bc9plml0n4c54rlgzq9r7f9wx092yf0jiz9fr12",
"version": "2.0"
}
}

View File

@@ -0,0 +1,53 @@
{
fetchzip,
stdenv,
lib,
}:
{
plugins.civicrm = stdenv.mkDerivation rec {
pname = "civicrm";
version = "6.2.0";
src = fetchzip {
inherit version;
name = pname;
url = "https://download.civicrm.org/${pname}-${version}-wordpress.zip";
hash = "sha256-Bx1rixRbqJsiMrIIkzTGeqLIc5raiNoUVTsoxZ6q9uU=";
};
installPhase = ''
runHook preInstall
cp -r ./ -T $out
runHook postInstall
'';
meta.license = lib.licenses.agpl3Only;
};
themes = {
geist = stdenv.mkDerivation rec {
pname = "geist";
version = "2.0.3";
src = fetchzip {
inherit version;
name = pname;
url = "https://github.com/christophery/geist/archive/refs/tags/${version}.zip";
hash = "sha256-c85oRhqu5E5IJlpgqKJRQITur1W7x40obOvHZbPevzU=";
};
meta.license = lib.licenses.gpl2Only;
};
proton = stdenv.mkDerivation rec {
pname = "proton";
version = "1.0.1";
src = fetchzip {
inherit version;
name = pname;
url = "https://github.com/christophery/proton/archive/refs/tags/${version}.zip";
hash = "sha256-JgKyLJ3dRqh1uwlsNuffCOM7LPBigGkLVFqftjFAiP4=";
};
installPhase = ''
runHook preInstall
mkdir -p $out
cp -r ./* $out/
runHook postInstall
'';
meta.license = lib.licenses.mit;
};
};
}

View File

@@ -0,0 +1,6 @@
{
"de_DE": "gpl2Plus",
"fr_FR": "gpl2Plus",
"ro_RO": "gpl2Plus",
"ru_RU": "gpl2Plus"
}

View File

@@ -0,0 +1,45 @@
{
"add-widget-after-content": "gpl3Plus"
, "akismet": "gpl2Plus"
, "antispam-bee": "gpl2Plus"
, "async-javascript": "gpl2Plus"
, "breeze": "gpl2Plus"
, "code-syntax-block": "gpl2Plus"
, "cookie-notice": "mit"
, "co-authors-plus": "gpl2Plus"
, "disable-xml-rpc": "gpl2Plus"
, "embed-extended": "gpl2Plus"
, "gutenberg": "gpl2Plus"
, "hcaptcha-for-forms-and-more": "gpl2Only"
, "hello-dolly": "gpl2Plus"
, "hkdev-maintenance-mode": "gpl2Plus"
, "jetpack": "gpl2Plus"
, "jetpack-lite": "gpl2Only"
, "lightbox-photoswipe": "gpl2Only"
, "login-lockdown": "gpl2Plus"
, "mailpoet": "gpl3Only"
, "merge-minify-refresh": "gpl2Plus"
, "opengraph": "asl20"
, "simple-login-captcha": "gpl2Plus"
, "simple-mastodon-verification": "gpl2Plus"
, "so-clean-up-wp-seo": "gpl3Plus"
, "sqlite-database-integration": "gpl2Plus"
, "static-mail-sender-configurator": "mit"
, "surge": "gpl3Only"
, "tc-custom-javascript": "gpl2Plus"
, "webp-converter-for-media": "gpl2Plus"
, "webp-express": "gpl3Only"
, "wordpress-seo": "gpl3Only"
, "worker": "gpl3Plus"
, "wp-change-email-sender": "gpl2Plus"
, "wp-fail2ban": "gpl3Plus"
, "wp-fail2ban-addon-contact-form-7": "gpl3Plus"
, "wp-fastest-cache": "gpl2Plus"
, "wp-gdpr-compliance": "gpl2Plus"
, "wp-import-export-lite": "gpl3Plus"
, "wp-mail-smtp": "gpl3Plus"
, "wp-statistics": "gpl3Only"
, "wp-swiper": "gpl2Plus"
, "wp-user-avatars": "gpl2Plus"
, "wpforms-lite": "gpl2Plus"
}

View File

@@ -0,0 +1,9 @@
{
"twentynineteen": "gpl2Plus",
"twentytwenty": "gpl2Plus",
"twentytwentyone": "gpl2Plus",
"twentytwentytwo": "gpl2Plus",
"twentytwentythree": "gpl2Plus",
"twentytwentyfour": "gpl2Plus",
"twentytwentyfive": "gpl2Plus"
}