Merge pull request #48189 from aanderse/redmine

redmine: refactor, cleanup, bug fix, and add functionality
This commit is contained in:
Michael Raskin 2018-10-11 15:32:43 +00:00 committed by GitHub
commit a29603344a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 394 additions and 91 deletions

View File

@ -5,7 +5,7 @@ with lib;
let
cfg = config.services.redmine;
bundle = "${pkgs.redmine}/share/redmine/bin/bundle";
bundle = "${cfg.package}/share/redmine/bin/bundle";
databaseYml = pkgs.writeText "database.yml" ''
production:
@ -15,6 +15,7 @@ let
port: ${toString cfg.database.port}
username: ${cfg.database.user}
password: #dbpass#
${optionalString (cfg.database.socket != null) "socket: ${cfg.database.socket}"}
'';
configurationYml = pkgs.writeText "configuration.yml" ''
@ -29,6 +30,19 @@ let
${cfg.extraConfig}
'';
unpackTheme = unpack "theme";
unpackPlugin = unpack "plugin";
unpack = id: (name: source:
pkgs.stdenv.mkDerivation {
name = "redmine-${id}-${name}";
buildInputs = [ pkgs.unzip ];
buildCommand = ''
mkdir -p $out
cd $out
unpackFile ${source}
'';
});
in
{
@ -40,6 +54,14 @@ in
description = "Enable the Redmine service.";
};
package = mkOption {
type = types.package;
default = pkgs.redmine;
defaultText = "pkgs.redmine";
description = "Which Redmine package to use.";
example = "pkgs.redmine.override { ruby = pkgs.ruby_2_3; }";
};
user = mkOption {
type = types.str;
default = "redmine";
@ -52,6 +74,12 @@ in
description = "Group under which Redmine is ran.";
};
port = mkOption {
type = types.int;
default = 3000;
description = "Port on which Redmine is ran.";
};
stateDir = mkOption {
type = types.str;
default = "/var/lib/redmine";
@ -66,6 +94,41 @@ in
See https://guides.rubyonrails.org/action_mailer_basics.html#action-mailer-configuration
'';
example = literalExample ''
email_delivery:
delivery_method: smtp
smtp_settings:
address: mail.example.com
port: 25
'';
};
themes = mkOption {
type = types.attrsOf types.path;
default = {};
description = "Set of themes.";
example = literalExample ''
{
dkuk-redmine_alex_skin = builtins.fetchurl {
url = https://bitbucket.org/dkuk/redmine_alex_skin/get/1842ef675ef3.zip;
sha256 = "0hrin9lzyi50k4w2bd2b30vrf1i4fi1c0gyas5801wn8i7kpm9yl";
};
}
'';
};
plugins = mkOption {
type = types.attrsOf types.path;
default = {};
description = "Set of plugins.";
example = literalExample ''
{
redmine_env_auth = builtins.fetchurl {
url = https://github.com/Intera/redmine_env_auth/archive/0.6.zip;
sha256 = "0yyr1yjd8gvvh832wdc8m3xfnhhxzk2pk3gm2psg5w9jdvd6skak";
};
}
'';
};
database = {
@ -78,7 +141,7 @@ in
host = mkOption {
type = types.str;
default = "127.0.0.1";
default = (if cfg.database.socket != null then "localhost" else "127.0.0.1");
description = "Database host address.";
};
@ -119,6 +182,13 @@ in
<option>database.user</option>.
'';
};
socket = mkOption {
type = types.nullOr types.path;
default = null;
example = "/run/mysqld/mysqld.sock";
description = "Path to the unix socket file to use for authentication.";
};
};
};
};
@ -126,17 +196,20 @@ in
config = mkIf cfg.enable {
assertions = [
{ assertion = cfg.database.passwordFile != null || cfg.database.password != "";
message = "either services.redmine.database.passwordFile or services.redmine.database.password must be set";
{ assertion = cfg.database.passwordFile != null || cfg.database.password != "" || cfg.database.socket != null;
message = "one of services.redmine.database.socket, services.redmine.database.passwordFile, or services.redmine.database.password must be set";
}
{ assertion = cfg.database.socket != null -> (cfg.database.type == "mysql2");
message = "Socket authentication is only available for the mysql2 database type";
}
];
environment.systemPackages = [ pkgs.redmine ];
environment.systemPackages = [ cfg.package ];
systemd.services.redmine = {
after = [ "network.target" (if cfg.database.type == "mysql2" then "mysql.service" else "postgresql.service") ];
wantedBy = [ "multi-user.target" ];
environment.HOME = "${pkgs.redmine}/share/redmine";
environment.HOME = "${cfg.package}/share/redmine";
environment.RAILS_ENV = "production";
environment.RAILS_CACHE = "${cfg.stateDir}/cache";
environment.REDMINE_LANG = "en";
@ -151,43 +224,80 @@ in
subversion
];
preStart = ''
# start with a fresh config directory every time
rm -rf ${cfg.stateDir}/config
cp -r ${pkgs.redmine}/share/redmine/config.dist ${cfg.stateDir}/config
# ensure cache directory exists for db:migrate command
mkdir -p "${cfg.stateDir}/cache"
# create the basic state directory layout pkgs.redmine expects
mkdir -p /run/redmine
# create the basic directory layout the redmine package expects
mkdir -p /run/redmine/public
for i in config files log plugins tmp; do
mkdir -p ${cfg.stateDir}/$i
ln -fs ${cfg.stateDir}/$i /run/redmine/$i
mkdir -p "${cfg.stateDir}/$i"
ln -fs "${cfg.stateDir}/$i" /run/redmine/
done
# ensure cache directory exists for db:migrate command
mkdir -p ${cfg.stateDir}/cache
for i in plugin_assets themes; do
mkdir -p "${cfg.stateDir}/public/$i"
ln -fs "${cfg.stateDir}/public/$i" /run/redmine/public/
done
# start with a fresh config directory
# the config directory is copied instead of linked as some mutable data is stored in there
rm -rf "${cfg.stateDir}/config/"*
cp -r ${cfg.package}/share/redmine/config.dist/* "${cfg.stateDir}/config/"
# link in the application configuration
ln -fs ${configurationYml} ${cfg.stateDir}/config/configuration.yml
ln -fs ${configurationYml} "${cfg.stateDir}/config/configuration.yml"
chmod -R ug+rwX,o-rwx+x ${cfg.stateDir}/
# handle database.passwordFile
# link in all user specified themes
rm -rf "${cfg.stateDir}/public/themes/"*
for theme in ${concatStringsSep " " (mapAttrsToList unpackTheme cfg.themes)}; do
ln -fs $theme/* "${cfg.stateDir}/public/themes"
done
# link in redmine provided themes
ln -sf ${cfg.package}/share/redmine/public/themes.dist/* "${cfg.stateDir}/public/themes/"
# link in all user specified plugins
rm -rf "${cfg.stateDir}/plugins/"*
for plugin in ${concatStringsSep " " (mapAttrsToList unpackPlugin cfg.plugins)}; do
ln -fs $plugin/* "${cfg.stateDir}/plugins/''${plugin##*-redmine-plugin-}"
done
# ensure correct permissions for most files
chmod -R ug+rwX,o-rwx+x "${cfg.stateDir}/"
# handle database.passwordFile & permissions
DBPASS=$(head -n1 ${cfg.database.passwordFile})
cp -f ${databaseYml} ${cfg.stateDir}/config/database.yml
sed -e "s,#dbpass#,$DBPASS,g" -i ${cfg.stateDir}/config/database.yml
chmod 440 ${cfg.stateDir}/config/database.yml
cp -f ${databaseYml} "${cfg.stateDir}/config/database.yml"
sed -e "s,#dbpass#,$DBPASS,g" -i "${cfg.stateDir}/config/database.yml"
chmod 440 "${cfg.stateDir}/config/database.yml"
# generate a secret token if required
if ! test -e "${cfg.stateDir}/config/initializers/secret_token.rb"; then
${bundle} exec rake generate_secret_token
chmod 440 ${cfg.stateDir}/config/initializers/secret_token.rb
chmod 440 "${cfg.stateDir}/config/initializers/secret_token.rb"
fi
# ensure everything is owned by ${cfg.user}
chown -R ${cfg.user}:${cfg.group} ${cfg.stateDir}
${bundle} exec rake db:migrate
${bundle} exec rake redmine:load_default_data
# ensure everything is owned by ${cfg.user}
chown -R ${cfg.user}:${cfg.group} "${cfg.stateDir}"
# execute redmine required commands prior to starting the application
# NOTE: su required in case using mysql socket authentication
/run/wrappers/bin/su -s ${pkgs.bash}/bin/bash -m -l redmine -c '${bundle} exec rake db:migrate'
/run/wrappers/bin/su -s ${pkgs.bash}/bin/bash -m -l redmine -c '${bundle} exec rake redmine:load_default_data'
# log files don't exist until after first command has been executed
# correct ownership of files generated by calling exec rake ...
chown -R ${cfg.user}:${cfg.group} "${cfg.stateDir}/log"
'';
serviceConfig = {
@ -196,13 +306,13 @@ in
User = cfg.user;
Group = cfg.group;
TimeoutSec = "300";
WorkingDirectory = "${pkgs.redmine}/share/redmine";
ExecStart="${bundle} exec rails server webrick -e production -P ${cfg.stateDir}/redmine.pid";
WorkingDirectory = "${cfg.package}/share/redmine";
ExecStart="${bundle} exec rails server webrick -e production -p ${toString cfg.port} -P '${cfg.stateDir}/redmine.pid'";
};
};
users.extraUsers = optionalAttrs (cfg.user == "redmine") (singleton
users.users = optionalAttrs (cfg.user == "redmine") (singleton
{ name = "redmine";
group = cfg.group;
home = cfg.stateDir;
@ -210,7 +320,7 @@ in
uid = config.ids.uids.redmine;
});
users.extraGroups = optionalAttrs (cfg.group == "redmine") (singleton
users.groups = optionalAttrs (cfg.group == "redmine") (singleton
{ name = "redmine";
gid = config.ids.gids.redmine;
});

View File

@ -397,6 +397,7 @@ in rec {
tests.quake3 = callTest tests/quake3.nix {};
tests.rabbitmq = callTest tests/rabbitmq.nix {};
tests.radicale = callTest tests/radicale.nix {};
tests.redmine = callTest tests/redmine.nix {};
tests.rspamd = callSubTests tests/rspamd.nix {};
tests.runInMachine = callTest tests/run-in-machine.nix {};
tests.rxe = callTest tests/rxe.nix {};

40
nixos/tests/redmine.nix Normal file
View File

@ -0,0 +1,40 @@
import ./make-test.nix ({ pkgs, lib, ... }:
{
name = "redmine";
meta.maintainers = [ lib.maintainers.aanderse ];
machine =
{ config, pkgs, ... }:
{ services.mysql.enable = true;
services.mysql.package = pkgs.mariadb;
services.mysql.ensureDatabases = [ "redmine" ];
services.mysql.ensureUsers = [
{ name = "redmine";
ensurePermissions = { "redmine.*" = "ALL PRIVILEGES"; };
}
];
services.redmine.enable = true;
services.redmine.database.socket = "/run/mysqld/mysqld.sock";
services.redmine.plugins = {
redmine_env_auth = pkgs.fetchurl {
url = https://github.com/Intera/redmine_env_auth/archive/0.6.zip;
sha256 = "0yyr1yjd8gvvh832wdc8m3xfnhhxzk2pk3gm2psg5w9jdvd6skak";
};
};
services.redmine.themes = {
dkuk-redmine_alex_skin = pkgs.fetchurl {
url = https://bitbucket.org/dkuk/redmine_alex_skin/get/1842ef675ef3.zip;
sha256 = "0hrin9lzyi50k4w2bd2b30vrf1i4fi1c0gyas5801wn8i7kpm9yl";
};
};
};
testScript = ''
startAll;
$machine->waitForUnit('redmine.service');
$machine->waitForOpenPort('3000');
$machine->succeed("curl --fail http://localhost:3000/");
'';
})

View File

@ -54,60 +54,26 @@ platforms :mri, :mingw, :x64_mingw do
end
end
# Include database gems for the adapters found in the database
# configuration file
require 'erb'
require 'yaml'
# NixOS - manually added to ensure mysql and postgres will always be include
# Include database gems for the database adapters NixOS supports
gem "mysql2", "~> 0.4.6", :platforms => [:mri, :mingw, :x64_mingw]
gem "pg", "~> 0.18.1", :platforms => [:mri, :mingw, :x64_mingw]
database_file = File.join(File.dirname(__FILE__), "config/database.yml")
if File.exist?(database_file)
database_config = YAML::load(ERB.new(IO.read(database_file)).result)
adapters = database_config.values.map {|c| c['adapter']}.compact.uniq
if adapters.any?
adapters.each do |adapter|
case adapter
when 'mysql2'
gem "mysql2", "~> 0.4.6", :platforms => [:mri, :mingw, :x64_mingw]
when /postgresql/
gem "pg", "~> 0.18.1", :platforms => [:mri, :mingw, :x64_mingw]
when /sqlite3/
gem "sqlite3", (RUBY_VERSION < "2.0" && RUBY_PLATFORM =~ /mingw/ ? "1.3.12" : "~>1.3.12"),
:platforms => [:mri, :mingw, :x64_mingw]
when /sqlserver/
gem "tiny_tds", (RUBY_VERSION >= "2.0" ? "~> 1.0.5" : "~> 0.7.0"), :platforms => [:mri, :mingw, :x64_mingw]
gem "activerecord-sqlserver-adapter", :platforms => [:mri, :mingw, :x64_mingw]
else
warn("Unknown database adapter `#{adapter}` found in config/database.yml, use Gemfile.local to load your own database gems")
end
end
else
warn("No adapter found in config/database.yml, please configure it first")
end
else
warn("Please configure your config/database.yml first")
group :development do
gem "rdoc", "~> 4.3"
gem "yard"
end
# NixOS - manually removed because I couldn't figure out how to get "bundle exec rails server webrick -e production" to ignore these groups
#group :development do
# gem "rdoc", "~> 4.3"
# gem "yard"
#end
#group :test do
# gem "minitest"
# gem "rails-dom-testing"
# gem "mocha"
# gem "simplecov", "~> 0.9.1", :require => false
# # TODO: remove this after upgrading to Rails 5
# gem "test_after_commit", "~> 0.4.2"
# # For running UI tests
# gem "capybara"
# gem "selenium-webdriver", "~> 2.53.4"
#end
group :test do
gem "minitest"
gem "rails-dom-testing"
gem "mocha"
gem "simplecov", "~> 0.9.1", :require => false
# TODO: remove this after upgrading to Rails 5
gem "test_after_commit", "~> 0.4.2"
# For running UI tests
gem "capybara"
gem "selenium-webdriver", "~> 2.53.4"
end
local_gemfile = File.join(File.dirname(__FILE__), "Gemfile.local")
if File.exists?(local_gemfile)

View File

@ -41,12 +41,23 @@ GEM
public_suffix (>= 2.0.2, < 4.0)
arel (6.0.4)
builder (3.2.3)
capybara (3.9.0)
addressable
mini_mime (>= 0.1.3)
nokogiri (~> 1.8)
rack (>= 1.6.0)
rack-test (>= 0.6.3)
xpath (~> 3.1)
childprocess (0.9.0)
ffi (~> 1.0, >= 1.0.11)
coderay (1.1.2)
concurrent-ruby (1.0.5)
crass (1.0.4)
css_parser (1.6.0)
addressable
docile (1.1.5)
erubis (2.7.0)
ffi (1.9.25)
globalid (0.4.1)
activesupport (>= 4.2.0)
htmlentities (4.3.4)
@ -59,15 +70,20 @@ GEM
nokogiri (>= 1.5.9)
mail (2.6.6)
mime-types (>= 1.16, < 4)
metaclass (0.0.4)
mime-types (3.2.2)
mime-types-data (~> 3.2015)
mime-types-data (3.2018.0812)
mimemagic (0.3.2)
mini_mime (1.0.1)
mini_portile2 (2.3.0)
minitest (5.11.3)
mocha (1.7.0)
metaclass (~> 0.0.1)
multi_json (1.13.1)
mysql2 (0.4.10)
net-ldap (0.12.1)
nokogiri (1.8.4)
nokogiri (1.8.5)
mini_portile2 (~> 2.3.0)
pg (0.18.4)
protected_attributes (1.1.4)
@ -104,10 +120,11 @@ GEM
rake (>= 0.8.7)
thor (>= 0.18.1, < 2.0)
rake (12.3.1)
rbpdf (1.19.5)
rbpdf (1.19.6)
htmlentities
rbpdf-font (~> 1.19.0)
rbpdf-font (1.19.1)
rdoc (4.3.0)
redcarpet (3.4.0)
request_store (1.0.5)
rmagick (2.16.0)
@ -118,6 +135,16 @@ GEM
railties (>= 3.0, < 5.1)
roadie (~> 3.1)
ruby-openid (2.3.0)
rubyzip (1.2.2)
selenium-webdriver (2.53.4)
childprocess (~> 0.5)
rubyzip (~> 1.0)
websocket (~> 1.0)
simplecov (0.9.2)
docile (~> 1.1.0)
multi_json (~> 1.0)
simplecov-html (~> 0.9.0)
simplecov-html (0.9.0)
sprockets (3.7.2)
concurrent-ruby (~> 1.0)
rack (> 1, < 3)
@ -125,22 +152,31 @@ GEM
actionpack (>= 4.0)
activesupport (>= 4.0)
sprockets (>= 3.0.0)
test_after_commit (0.4.2)
activerecord (>= 3.2)
thor (0.20.0)
thread_safe (0.3.6)
tzinfo (1.2.5)
thread_safe (~> 0.1)
websocket (1.2.8)
xpath (3.1.0)
nokogiri (~> 1.8)
yard (0.9.16)
PLATFORMS
ruby
DEPENDENCIES
actionpack-xml_parser
capybara
coderay (~> 1.1.1)
i18n (~> 0.7.0)
jquery-rails (~> 3.1.4)
mail (~> 2.6.4)
mime-types (~> 3.0)
mimemagic
minitest
mocha
mysql2 (~> 0.4.6)
net-ldap (~> 0.12.0)
nokogiri (~> 1.8.1)
@ -148,15 +184,21 @@ DEPENDENCIES
protected_attributes
rack-openid
rails (= 4.2.8)
rails-dom-testing
rails-html-sanitizer (>= 1.0.3)
rbpdf (~> 1.19.3)
rdoc (~> 4.3)
redcarpet (~> 3.4.0)
request_store (= 1.0.5)
rmagick (>= 2.14.0)
roadie (~> 3.2.1)
roadie-rails (~> 1.1.1)
ruby-openid (~> 2.3.0)
selenium-webdriver (~> 2.53.4)
simplecov (~> 0.9.1)
test_after_commit (~> 0.4.2)
tzinfo-data
yard
BUNDLED WITH
1.16.1
1.16.3

View File

@ -7,6 +7,7 @@ let
inherit ruby;
gemdir = ./.;
groups = [ "ldap" "openid" ];
};
in
stdenv.mkDerivation rec {
@ -21,15 +22,15 @@ in
buildPhase = ''
mv config config.dist
mv public/themes public/themes.dist
'';
installPhase = ''
mkdir -p $out/share
cp -r . $out/share/redmine
for i in config files log plugins tmp; do
for i in config files log plugins public/plugin_assets public/themes tmp; do
rm -rf $out/share/redmine/$i
ln -fs /run/redmine/$i $out/share/redmine/
ln -fs /run/redmine/$i $out/share/redmine/$i
done
'';
@ -39,4 +40,4 @@ in
maintainers = [ maintainers.garbas ];
license = licenses.gpl2;
};
}
}

View File

@ -96,6 +96,24 @@
};
version = "3.2.3";
};
capybara = {
dependencies = ["addressable" "mini_mime" "nokogiri" "rack" "rack-test" "xpath"];
source = {
remotes = ["https://rubygems.org"];
sha256 = "1sz6ick0pn7886jh9fd4571wyplshnpb95pr22ds4hd51zcrnfi4";
type = "gem";
};
version = "3.9.0";
};
childprocess = {
dependencies = ["ffi"];
source = {
remotes = ["https://rubygems.org"];
sha256 = "0a61922kmvcxyj5l70fycapr87gz1dzzlkfpq85rfqk5vdh3d28p";
type = "gem";
};
version = "0.9.0";
};
coderay = {
source = {
remotes = ["https://rubygems.org"];
@ -129,6 +147,14 @@
};
version = "1.6.0";
};
docile = {
source = {
remotes = ["https://rubygems.org"];
sha256 = "0m8j31whq7bm5ljgmsrlfkiqvacrw6iz9wq10r3gwrv5785y8gjx";
type = "gem";
};
version = "1.1.5";
};
erubis = {
source = {
remotes = ["https://rubygems.org"];
@ -137,6 +163,14 @@
};
version = "2.7.0";
};
ffi = {
source = {
remotes = ["https://rubygems.org"];
sha256 = "0jpm2dis1j7zvvy3lg7axz9jml316zrn7s0j59vyq3qr127z0m7q";
type = "gem";
};
version = "1.9.25";
};
globalid = {
dependencies = ["activesupport"];
source = {
@ -189,6 +223,14 @@
};
version = "2.6.6";
};
metaclass = {
source = {
remotes = ["https://rubygems.org"];
sha256 = "0hp99y2b1nh0nr8pc398n3f8lakgci6pkrg4bf2b2211j1f6hsc5";
type = "gem";
};
version = "0.0.4";
};
mime-types = {
dependencies = ["mime-types-data"];
source = {
@ -214,6 +256,14 @@
};
version = "0.3.2";
};
mini_mime = {
source = {
remotes = ["https://rubygems.org"];
sha256 = "1q4pshq387lzv9m39jv32vwb8wrq3wc4jwgl4jk209r4l33v09d3";
type = "gem";
};
version = "1.0.1";
};
mini_portile2 = {
source = {
remotes = ["https://rubygems.org"];
@ -230,6 +280,23 @@
};
version = "5.11.3";
};
mocha = {
dependencies = ["metaclass"];
source = {
remotes = ["https://rubygems.org"];
sha256 = "13whjmrm4n48rwx7h7a2jwa5grar3m0fxspbm2pm4lyp7hi119c1";
type = "gem";
};
version = "1.7.0";
};
multi_json = {
source = {
remotes = ["https://rubygems.org"];
sha256 = "1rl0qy4inf1mp8mybfk56dfga0mvx97zwpmq5xmiwl5r770171nv";
type = "gem";
};
version = "1.13.1";
};
mysql2 = {
source = {
remotes = ["https://rubygems.org"];
@ -250,10 +317,10 @@
dependencies = ["mini_portile2"];
source = {
remotes = ["https://rubygems.org"];
sha256 = "1h9nml9h3m0mpvmh8jfnqvblnz5n5y3mmhgfc38avfmfzdrq9bgc";
sha256 = "0byyxrazkfm29ypcx5q4syrv126nvjnf7z6bqi01sqkv4llsi4qz";
type = "gem";
};
version = "1.8.4";
version = "1.8.5";
};
pg = {
source = {
@ -363,10 +430,10 @@
dependencies = ["htmlentities" "rbpdf-font"];
source = {
remotes = ["https://rubygems.org"];
sha256 = "021fda3gcz9pyydxnn40vs1nrkycwslb9ip4q0yg3hlip41k1b49";
sha256 = "159vg56bzy09f6zrh9h3rxm2r0vkvsfn9qczqmv1vi5xkd918s0d";
type = "gem";
};
version = "1.19.5";
version = "1.19.6";
};
rbpdf-font = {
source = {
@ -376,6 +443,14 @@
};
version = "1.19.1";
};
rdoc = {
source = {
remotes = ["https://rubygems.org"];
sha256 = "13ba2mhqqcsp3k97x3iz9x29xk26rv4561lfzzzibcy41vvj1n4c";
type = "gem";
};
version = "4.3.0";
};
redcarpet = {
source = {
remotes = ["https://rubygems.org"];
@ -426,6 +501,40 @@
};
version = "2.3.0";
};
rubyzip = {
source = {
remotes = ["https://rubygems.org"];
sha256 = "1n1lb2sdwh9h27y244hxzg1lrxxg2m53pk1vq7p33bna003qkyrj";
type = "gem";
};
version = "1.2.2";
};
selenium-webdriver = {
dependencies = ["childprocess" "rubyzip" "websocket"];
source = {
remotes = ["https://rubygems.org"];
sha256 = "15qyf7b9fa2nxhhwp551b9fjj82kb3wmy65559yrrcwpdadqvcs4";
type = "gem";
};
version = "2.53.4";
};
simplecov = {
dependencies = ["docile" "multi_json" "simplecov-html"];
source = {
remotes = ["https://rubygems.org"];
sha256 = "1a3wy9zlmfwl3f47cibnxyxrgfz16y6fmy0dj1vyidzyys4mvy12";
type = "gem";
};
version = "0.9.2";
};
simplecov-html = {
source = {
remotes = ["https://rubygems.org"];
sha256 = "0jv9pmpaxihrcsgcf6mgl3qg7rhf9scl5l2k67d768w9cz63xgvc";
type = "gem";
};
version = "0.9.0";
};
sprockets = {
dependencies = ["concurrent-ruby" "rack"];
source = {
@ -444,6 +553,15 @@
};
version = "3.2.1";
};
test_after_commit = {
dependencies = ["activerecord"];
source = {
remotes = ["https://rubygems.org"];
sha256 = "1fzg8qan6f0n0ynr594bld2k0rwwxj99yzhiga2f3pkj9ina1abb";
type = "gem";
};
version = "0.4.2";
};
thor = {
source = {
remotes = ["https://rubygems.org"];
@ -469,4 +587,29 @@
};
version = "1.2.5";
};
websocket = {
source = {
remotes = ["https://rubygems.org"];
sha256 = "0f11rcn4qgffb1rq4kjfwi7di79w8840x9l74pkyif5arp0mb08x";
type = "gem";
};
version = "1.2.8";
};
xpath = {
dependencies = ["nokogiri"];
source = {
remotes = ["https://rubygems.org"];
sha256 = "1y61ijvv04bwga802s8py5xd7fcxci6478wgr9wkd35p45x20jzi";
type = "gem";
};
version = "3.1.0";
};
yard = {
source = {
remotes = ["https://rubygems.org"];
sha256 = "0lmmr1839qgbb3zxfa7jf5mzy17yjl1yirwlgzdhws4452gqhn67";
type = "gem";
};
version = "0.9.16";
};
}

View File

@ -4972,7 +4972,7 @@ with pkgs;
redir = callPackage ../tools/networking/redir { };
redmine = callPackage ../applications/version-management/redmine { };
redmine = callPackage ../applications/version-management/redmine { ruby = pkgs.ruby_2_4; };
redsocks = callPackage ../tools/networking/redsocks { };