Merge master into staging-next
This commit is contained in:
@@ -6242,6 +6242,17 @@
|
||||
github = "Dettorer";
|
||||
githubId = 2761682;
|
||||
};
|
||||
deudz = {
|
||||
name = "Danilo Soares";
|
||||
email = "deudzdev@gmail.com";
|
||||
github = "deudz";
|
||||
githubId = 77695632;
|
||||
keys = [
|
||||
{
|
||||
fingerprint = "42B9 5F7C 4FC2 CA13 FD4E 86B6 F0D8 B7CE 0B7E C148";
|
||||
}
|
||||
];
|
||||
};
|
||||
developer-guy = {
|
||||
name = "Batuhan Apaydın";
|
||||
email = "developerguyn@gmail.com";
|
||||
|
||||
@@ -53,7 +53,7 @@ def get_tmp_dir() -> Path:
|
||||
|
||||
|
||||
def pythonize_name(name: str) -> str:
|
||||
return re.sub(r"^[^A-z_]|[^A-z0-9_]", "_", name)
|
||||
return re.sub(r"^[^A-Za-z_]|[^A-Za-z0-9_]", "_", name)
|
||||
|
||||
|
||||
class Driver:
|
||||
|
||||
@@ -24,8 +24,6 @@ let
|
||||
BOOTSNAP_CACHE_DIR = "/var/cache/mastodon/precompile";
|
||||
LD_PRELOAD = "${pkgs.jemalloc}/lib/libjemalloc.so";
|
||||
|
||||
MASTODON_USE_LIBVIPS = "true";
|
||||
|
||||
# Concurrency mastodon-web
|
||||
WEB_CONCURRENCY = toString cfg.webProcesses;
|
||||
MAX_THREADS = toString cfg.webThreads;
|
||||
@@ -196,7 +194,6 @@ let
|
||||
path = with pkgs; [
|
||||
ffmpeg-headless
|
||||
file
|
||||
imagemagick
|
||||
];
|
||||
}
|
||||
)
|
||||
@@ -257,6 +254,11 @@ in
|
||||
"mastodon"
|
||||
"streamingPort"
|
||||
] "Mastodon currently doesn't support streaming via TCP ports. Please open a PR if you need this.")
|
||||
(lib.mkRemovedOptionModule [
|
||||
"services"
|
||||
"mastodon"
|
||||
"otpSecretFile"
|
||||
] "The OTP_SECRET option was removed from Mastodon in version 4.4.0")
|
||||
];
|
||||
|
||||
options = {
|
||||
@@ -490,19 +492,6 @@ in
|
||||
type = lib.types.str;
|
||||
};
|
||||
|
||||
otpSecretFile = lib.mkOption {
|
||||
description = ''
|
||||
Path to file containing the OTP secret.
|
||||
A new OTP secret can be generated by running:
|
||||
|
||||
`nix build -f '<nixpkgs>' mastodon; cd result; bin/bundle exec rails secret`
|
||||
|
||||
If this file does not exist, it will be created with a new OTP secret.
|
||||
'';
|
||||
default = "/var/lib/mastodon/secrets/otp-secret";
|
||||
type = lib.types.str;
|
||||
};
|
||||
|
||||
trustedProxy = lib.mkOption {
|
||||
description = ''
|
||||
You need to set it to the IP from which your reverse proxy sends requests to Mastodon's web process,
|
||||
@@ -892,10 +881,6 @@ in
|
||||
mkdir -p $(dirname ${cfg.secretKeyBaseFile})
|
||||
bin/bundle exec rails secret > ${cfg.secretKeyBaseFile}
|
||||
fi
|
||||
if ! test -f ${cfg.otpSecretFile}; then
|
||||
mkdir -p $(dirname ${cfg.otpSecretFile})
|
||||
bin/bundle exec rails secret > ${cfg.otpSecretFile}
|
||||
fi
|
||||
if ! test -f ${cfg.vapidPrivateKeyFile}; then
|
||||
mkdir -p $(dirname ${cfg.vapidPrivateKeyFile}) $(dirname ${cfg.vapidPublicKeyFile})
|
||||
keypair=$(bin/rake webpush:generate_keys)
|
||||
@@ -908,7 +893,6 @@ in
|
||||
ACTIVE_RECORD_ENCRYPTION_KEY_DERIVATION_SALT="$(cat ${cfg.activeRecordEncryptionKeyDerivationSaltFile})"
|
||||
ACTIVE_RECORD_ENCRYPTION_PRIMARY_KEY="$(cat ${cfg.activeRecordEncryptionPrimaryKeyFile})"
|
||||
SECRET_KEY_BASE="$(cat ${cfg.secretKeyBaseFile})"
|
||||
OTP_SECRET="$(cat ${cfg.otpSecretFile})"
|
||||
VAPID_PRIVATE_KEY="$(cat ${cfg.vapidPrivateKeyFile})"
|
||||
VAPID_PUBLIC_KEY="$(cat ${cfg.vapidPublicKeyFile})"
|
||||
''
|
||||
|
||||
+10
-10
@@ -445,7 +445,7 @@ in
|
||||
fscrypt = runTest ./fscrypt.nix;
|
||||
fastnetmon-advanced = runTest ./fastnetmon-advanced.nix;
|
||||
lauti = runTest ./lauti.nix;
|
||||
easytier = handleTest ./easytier.nix { };
|
||||
easytier = runTest ./easytier.nix;
|
||||
ejabberd = runTest ./xmpp/ejabberd.nix;
|
||||
elk = handleTestOn [ "x86_64-linux" ] ./elk.nix { };
|
||||
emacs-daemon = runTest ./emacs-daemon.nix;
|
||||
@@ -613,7 +613,7 @@ in
|
||||
gokapi = runTest ./gokapi.nix;
|
||||
gollum = runTest ./gollum.nix;
|
||||
gonic = runTest ./gonic.nix;
|
||||
google-oslogin = handleTest ./google-oslogin { };
|
||||
google-oslogin = runTest ./google-oslogin;
|
||||
gopro-tool = runTest ./gopro-tool.nix;
|
||||
goss = runTest ./goss.nix;
|
||||
gotenberg = runTest ./gotenberg.nix;
|
||||
@@ -853,7 +853,7 @@ in
|
||||
mautrix-meta-sqlite = runTest ./matrix/mautrix-meta-sqlite.nix;
|
||||
mealie = runTest ./mealie.nix;
|
||||
mediamtx = runTest ./mediamtx.nix;
|
||||
mediatomb = handleTest ./mediatomb.nix { };
|
||||
mediatomb = runTest ./mediatomb.nix;
|
||||
mediawiki = handleTest ./mediawiki.nix { };
|
||||
meilisearch = runTest ./meilisearch.nix;
|
||||
memcached = runTest ./memcached.nix;
|
||||
@@ -901,11 +901,11 @@ in
|
||||
mumble = runTest ./mumble.nix;
|
||||
# Fails on aarch64-linux at the PDF creation step - need to debug this on an
|
||||
# aarch64 machine..
|
||||
musescore = handleTestOn [ "x86_64-linux" ] ./musescore.nix { };
|
||||
musescore = runTestOn [ "x86_64-linux" ] ./musescore.nix;
|
||||
music-assistant = runTest ./music-assistant.nix;
|
||||
munin = runTest ./munin.nix;
|
||||
mutableUsers = runTest ./mutable-users.nix;
|
||||
mycelium = handleTest ./mycelium { };
|
||||
mycelium = runTest ./mycelium;
|
||||
mympd = runTest ./mympd.nix;
|
||||
mysql = handleTest ./mysql/mysql.nix { };
|
||||
mysql-autobackup = handleTest ./mysql/mysql-autobackup.nix { };
|
||||
@@ -935,7 +935,7 @@ in
|
||||
};
|
||||
ndppd = runTest ./ndppd.nix;
|
||||
nebula = runTest ./nebula.nix;
|
||||
neo4j = handleTest ./neo4j.nix { };
|
||||
neo4j = runTest ./neo4j.nix;
|
||||
netbird = runTest ./netbird.nix;
|
||||
netdata = runTest ./netdata.nix;
|
||||
nimdow = runTest ./nimdow.nix;
|
||||
@@ -1261,11 +1261,11 @@ in
|
||||
sanoid = runTest ./sanoid.nix;
|
||||
saunafs = runTest ./saunafs.nix;
|
||||
scaphandre = handleTest ./scaphandre.nix { };
|
||||
schleuder = handleTest ./schleuder.nix { };
|
||||
schleuder = runTest ./schleuder.nix;
|
||||
scion-freestanding-deployment = handleTest ./scion/freestanding-deployment { };
|
||||
scrutiny = runTest ./scrutiny.nix;
|
||||
scx = runTest ./scx/default.nix;
|
||||
sddm = handleTest ./sddm.nix { };
|
||||
sddm = import ./sddm.nix { inherit runTest; };
|
||||
sdl3 = runTest ./sdl3.nix;
|
||||
seafile = runTest ./seafile.nix;
|
||||
searx = runTest ./searx.nix;
|
||||
@@ -1454,7 +1454,7 @@ in
|
||||
tracee = handleTestOn [ "x86_64-linux" ] ./tracee.nix { };
|
||||
trezord = runTest ./trezord.nix;
|
||||
trickster = runTest ./trickster.nix;
|
||||
trilium-server = handleTestOn [ "x86_64-linux" ] ./trilium-server.nix { };
|
||||
trilium-server = runTestOn [ "x86_64-linux" ] ./trilium-server.nix;
|
||||
tsm-client-gui = runTest ./tsm-client-gui.nix;
|
||||
ttyd = runTest ./web-servers/ttyd.nix;
|
||||
tt-rss = runTest ./web-apps/tt-rss.nix;
|
||||
@@ -1511,7 +1511,7 @@ in
|
||||
velocity = runTest ./velocity.nix;
|
||||
vengi-tools = runTest ./vengi-tools.nix;
|
||||
victorialogs = runTest ./victorialogs.nix;
|
||||
victoriametrics = handleTest ./victoriametrics { };
|
||||
victoriametrics = import ./victoriametrics { inherit runTest; };
|
||||
vikunja = runTest ./vikunja.nix;
|
||||
virtualbox = handleTestOn [ "x86_64-linux" ] ./virtualbox.nix { };
|
||||
vm-variant = handleTest ./vm-variant.nix { };
|
||||
|
||||
+106
-108
@@ -1,121 +1,119 @@
|
||||
import ./make-test-python.nix (
|
||||
{ lib, ... }:
|
||||
{
|
||||
name = "easytier";
|
||||
meta.maintainers = with lib.maintainers; [ ltrump ];
|
||||
{ lib, ... }:
|
||||
{
|
||||
name = "easytier";
|
||||
meta.maintainers = with lib.maintainers; [ ltrump ];
|
||||
|
||||
nodes =
|
||||
let
|
||||
genPeer =
|
||||
hostConfig: settings:
|
||||
lib.mkMerge [
|
||||
{
|
||||
services.easytier = {
|
||||
enable = true;
|
||||
instances.default = {
|
||||
settings = {
|
||||
network_name = "easytier_test";
|
||||
network_secret = "easytier_test_secret";
|
||||
} // settings;
|
||||
};
|
||||
nodes =
|
||||
let
|
||||
genPeer =
|
||||
hostConfig: settings:
|
||||
lib.mkMerge [
|
||||
{
|
||||
services.easytier = {
|
||||
enable = true;
|
||||
instances.default = {
|
||||
settings = {
|
||||
network_name = "easytier_test";
|
||||
network_secret = "easytier_test_secret";
|
||||
} // settings;
|
||||
};
|
||||
|
||||
networking.useDHCP = false;
|
||||
networking.firewall.allowedTCPPorts = [
|
||||
11010
|
||||
11011
|
||||
];
|
||||
networking.firewall.allowedUDPPorts = [
|
||||
11010
|
||||
11011
|
||||
];
|
||||
}
|
||||
hostConfig
|
||||
];
|
||||
in
|
||||
{
|
||||
relay =
|
||||
genPeer
|
||||
{
|
||||
virtualisation.vlans = [
|
||||
1
|
||||
2
|
||||
];
|
||||
|
||||
networking.interfaces.eth1.ipv4.addresses = [
|
||||
{
|
||||
address = "192.168.1.11";
|
||||
prefixLength = 24;
|
||||
}
|
||||
];
|
||||
|
||||
networking.interfaces.eth2.ipv4.addresses = [
|
||||
{
|
||||
address = "192.168.2.11";
|
||||
prefixLength = 24;
|
||||
}
|
||||
];
|
||||
}
|
||||
{
|
||||
ipv4 = "10.144.144.1";
|
||||
listeners = [
|
||||
"tcp://0.0.0.0:11010"
|
||||
"wss://0.0.0.0:11011"
|
||||
];
|
||||
};
|
||||
|
||||
peer1 =
|
||||
genPeer
|
||||
{
|
||||
virtualisation.vlans = [ 1 ];
|
||||
}
|
||||
{
|
||||
ipv4 = "10.144.144.2";
|
||||
peers = [ "tcp://192.168.1.11:11010" ];
|
||||
};
|
||||
networking.useDHCP = false;
|
||||
networking.firewall.allowedTCPPorts = [
|
||||
11010
|
||||
11011
|
||||
];
|
||||
networking.firewall.allowedUDPPorts = [
|
||||
11010
|
||||
11011
|
||||
];
|
||||
}
|
||||
hostConfig
|
||||
];
|
||||
in
|
||||
{
|
||||
relay =
|
||||
genPeer
|
||||
{
|
||||
virtualisation.vlans = [
|
||||
1
|
||||
2
|
||||
];
|
||||
|
||||
peer2 =
|
||||
genPeer
|
||||
{
|
||||
virtualisation.vlans = [ 2 ];
|
||||
}
|
||||
{
|
||||
ipv4 = "10.144.144.3";
|
||||
peers = [ "wss://192.168.2.11:11011" ];
|
||||
};
|
||||
};
|
||||
networking.interfaces.eth1.ipv4.addresses = [
|
||||
{
|
||||
address = "192.168.1.11";
|
||||
prefixLength = 24;
|
||||
}
|
||||
];
|
||||
|
||||
testScript = ''
|
||||
start_all()
|
||||
networking.interfaces.eth2.ipv4.addresses = [
|
||||
{
|
||||
address = "192.168.2.11";
|
||||
prefixLength = 24;
|
||||
}
|
||||
];
|
||||
}
|
||||
{
|
||||
ipv4 = "10.144.144.1";
|
||||
listeners = [
|
||||
"tcp://0.0.0.0:11010"
|
||||
"wss://0.0.0.0:11011"
|
||||
];
|
||||
};
|
||||
|
||||
relay.wait_for_unit("easytier-default.service")
|
||||
peer1.wait_for_unit("easytier-default.service")
|
||||
peer2.wait_for_unit("easytier-default.service")
|
||||
peer1 =
|
||||
genPeer
|
||||
{
|
||||
virtualisation.vlans = [ 1 ];
|
||||
}
|
||||
{
|
||||
ipv4 = "10.144.144.2";
|
||||
peers = [ "tcp://192.168.1.11:11010" ];
|
||||
};
|
||||
|
||||
# relay is accessible by the other hosts
|
||||
peer1.succeed("ping -c5 192.168.1.11")
|
||||
peer2.succeed("ping -c5 192.168.2.11")
|
||||
peer2 =
|
||||
genPeer
|
||||
{
|
||||
virtualisation.vlans = [ 2 ];
|
||||
}
|
||||
{
|
||||
ipv4 = "10.144.144.3";
|
||||
peers = [ "wss://192.168.2.11:11011" ];
|
||||
};
|
||||
};
|
||||
|
||||
# The other hosts are in separate vlans
|
||||
peer1.fail("ping -c5 192.168.2.11")
|
||||
peer2.fail("ping -c5 192.168.1.11")
|
||||
testScript = ''
|
||||
start_all()
|
||||
|
||||
# Each host can ping themselves through EasyTier
|
||||
relay.succeed("ping -c5 10.144.144.1")
|
||||
peer1.succeed("ping -c5 10.144.144.2")
|
||||
peer2.succeed("ping -c5 10.144.144.3")
|
||||
relay.wait_for_unit("easytier-default.service")
|
||||
peer1.wait_for_unit("easytier-default.service")
|
||||
peer2.wait_for_unit("easytier-default.service")
|
||||
|
||||
# Relay is accessible by the other hosts through EasyTier
|
||||
peer1.succeed("ping -c5 10.144.144.1")
|
||||
peer2.succeed("ping -c5 10.144.144.1")
|
||||
# relay is accessible by the other hosts
|
||||
peer1.succeed("ping -c5 192.168.1.11")
|
||||
peer2.succeed("ping -c5 192.168.2.11")
|
||||
|
||||
# Relay can access the other hosts through EasyTier
|
||||
relay.succeed("ping -c5 10.144.144.2")
|
||||
relay.succeed("ping -c5 10.144.144.3")
|
||||
# The other hosts are in separate vlans
|
||||
peer1.fail("ping -c5 192.168.2.11")
|
||||
peer2.fail("ping -c5 192.168.1.11")
|
||||
|
||||
# The other hosts in separate vlans can access each other through EasyTier
|
||||
peer1.succeed("ping -c5 10.144.144.3")
|
||||
peer2.succeed("ping -c5 10.144.144.2")
|
||||
'';
|
||||
}
|
||||
)
|
||||
# Each host can ping themselves through EasyTier
|
||||
relay.succeed("ping -c5 10.144.144.1")
|
||||
peer1.succeed("ping -c5 10.144.144.2")
|
||||
peer2.succeed("ping -c5 10.144.144.3")
|
||||
|
||||
# Relay is accessible by the other hosts through EasyTier
|
||||
peer1.succeed("ping -c5 10.144.144.1")
|
||||
peer2.succeed("ping -c5 10.144.144.1")
|
||||
|
||||
# Relay can access the other hosts through EasyTier
|
||||
relay.succeed("ping -c5 10.144.144.2")
|
||||
relay.succeed("ping -c5 10.144.144.3")
|
||||
|
||||
# The other hosts in separate vlans can access each other through EasyTier
|
||||
peer1.succeed("ping -c5 10.144.144.3")
|
||||
peer2.succeed("ping -c5 10.144.144.2")
|
||||
'';
|
||||
}
|
||||
|
||||
@@ -1,78 +1,81 @@
|
||||
import ../make-test-python.nix (
|
||||
{ pkgs, ... }:
|
||||
let
|
||||
inherit (import ./../ssh-keys.nix pkgs)
|
||||
snakeOilPrivateKey
|
||||
snakeOilPublicKey
|
||||
;
|
||||
{
|
||||
lib,
|
||||
pkgs,
|
||||
hostPkgs,
|
||||
...
|
||||
}:
|
||||
let
|
||||
inherit (import ./../ssh-keys.nix hostPkgs)
|
||||
snakeOilPrivateKey
|
||||
snakeOilPublicKey
|
||||
;
|
||||
|
||||
# don't check host keys or known hosts, use the snakeoil ssh key
|
||||
ssh-config = builtins.toFile "ssh.conf" ''
|
||||
UserKnownHostsFile=/dev/null
|
||||
StrictHostKeyChecking=no
|
||||
IdentityFile=~/.ssh/id_snakeoil
|
||||
'';
|
||||
in
|
||||
{
|
||||
name = "google-oslogin";
|
||||
meta = with pkgs.lib.maintainers; {
|
||||
maintainers = [ ];
|
||||
};
|
||||
# don't check host keys or known hosts, use the snakeoil ssh key
|
||||
ssh-config = builtins.toFile "ssh.conf" ''
|
||||
UserKnownHostsFile=/dev/null
|
||||
StrictHostKeyChecking=no
|
||||
IdentityFile=~/.ssh/id_snakeoil
|
||||
'';
|
||||
in
|
||||
{
|
||||
name = "google-oslogin";
|
||||
meta = with lib.maintainers; {
|
||||
maintainers = [ ];
|
||||
};
|
||||
|
||||
nodes = {
|
||||
# the server provides both the the mocked google metadata server and the ssh server
|
||||
server = (import ./server.nix pkgs);
|
||||
nodes = {
|
||||
# the server provides both the the mocked google metadata server and the ssh server
|
||||
server = ./server.nix;
|
||||
|
||||
client = { ... }: { };
|
||||
};
|
||||
testScript = ''
|
||||
MOCKUSER = "mockuser_nixos_org"
|
||||
MOCKADMIN = "mockadmin_nixos_org"
|
||||
start_all()
|
||||
client = { ... }: { };
|
||||
};
|
||||
testScript = ''
|
||||
MOCKUSER = "mockuser_nixos_org"
|
||||
MOCKADMIN = "mockadmin_nixos_org"
|
||||
start_all()
|
||||
|
||||
server.wait_for_unit("mock-google-metadata.service")
|
||||
server.wait_for_open_port(80)
|
||||
server.wait_for_unit("mock-google-metadata.service")
|
||||
server.wait_for_open_port(80)
|
||||
|
||||
# mockserver should return a non-expired ssh key for both mockuser and mockadmin
|
||||
server.succeed(
|
||||
f'${pkgs.google-guest-oslogin}/bin/google_authorized_keys {MOCKUSER} | grep -q "${snakeOilPublicKey}"'
|
||||
)
|
||||
server.succeed(
|
||||
f'${pkgs.google-guest-oslogin}/bin/google_authorized_keys {MOCKADMIN} | grep -q "${snakeOilPublicKey}"'
|
||||
)
|
||||
# mockserver should return a non-expired ssh key for both mockuser and mockadmin
|
||||
server.succeed(
|
||||
f'${pkgs.google-guest-oslogin}/bin/google_authorized_keys {MOCKUSER} | grep -q "${snakeOilPublicKey}"'
|
||||
)
|
||||
server.succeed(
|
||||
f'${pkgs.google-guest-oslogin}/bin/google_authorized_keys {MOCKADMIN} | grep -q "${snakeOilPublicKey}"'
|
||||
)
|
||||
|
||||
# install snakeoil ssh key on the client, and provision .ssh/config file
|
||||
client.succeed("mkdir -p ~/.ssh")
|
||||
client.succeed(
|
||||
"cat ${snakeOilPrivateKey} > ~/.ssh/id_snakeoil"
|
||||
)
|
||||
client.succeed("chmod 600 ~/.ssh/id_snakeoil")
|
||||
client.succeed("cp ${ssh-config} ~/.ssh/config")
|
||||
# install snakeoil ssh key on the client, and provision .ssh/config file
|
||||
client.succeed("mkdir -p ~/.ssh")
|
||||
client.succeed(
|
||||
"cat ${snakeOilPrivateKey} > ~/.ssh/id_snakeoil"
|
||||
)
|
||||
client.succeed("chmod 600 ~/.ssh/id_snakeoil")
|
||||
client.succeed("cp ${ssh-config} ~/.ssh/config")
|
||||
|
||||
client.wait_for_unit("network.target")
|
||||
server.wait_for_unit("sshd.service")
|
||||
client.wait_for_unit("network.target")
|
||||
server.wait_for_unit("sshd.service")
|
||||
|
||||
# we should not be able to connect as non-existing user
|
||||
client.fail("ssh ghost@server 'true'")
|
||||
# we should not be able to connect as non-existing user
|
||||
client.fail("ssh ghost@server 'true'")
|
||||
|
||||
# we should be able to connect as mockuser
|
||||
client.succeed(f"ssh {MOCKUSER}@server 'true'")
|
||||
# but we shouldn't be able to sudo
|
||||
client.fail(
|
||||
f"ssh {MOCKUSER}@server '/run/wrappers/bin/sudo /run/current-system/sw/bin/id' | grep -q 'root'"
|
||||
)
|
||||
# we should be able to connect as mockuser
|
||||
client.succeed(f"ssh {MOCKUSER}@server 'true'")
|
||||
# but we shouldn't be able to sudo
|
||||
client.fail(
|
||||
f"ssh {MOCKUSER}@server '/run/wrappers/bin/sudo /run/current-system/sw/bin/id' | grep -q 'root'"
|
||||
)
|
||||
|
||||
# we should also be able to log in as mockadmin
|
||||
client.succeed(f"ssh {MOCKADMIN}@server 'true'")
|
||||
# pam_oslogin_admin.so should now have generated a sudoers file
|
||||
server.succeed(
|
||||
f"find /run/google-sudoers.d | grep -q '/run/google-sudoers.d/{MOCKADMIN}'"
|
||||
)
|
||||
# we should also be able to log in as mockadmin
|
||||
client.succeed(f"ssh {MOCKADMIN}@server 'true'")
|
||||
# pam_oslogin_admin.so should now have generated a sudoers file
|
||||
server.succeed(
|
||||
f"find /run/google-sudoers.d | grep -q '/run/google-sudoers.d/{MOCKADMIN}'"
|
||||
)
|
||||
|
||||
# and we should be able to sudo
|
||||
client.succeed(
|
||||
f"ssh {MOCKADMIN}@server '/run/wrappers/bin/sudo /run/current-system/sw/bin/id' | grep -q 'root'"
|
||||
)
|
||||
'';
|
||||
}
|
||||
)
|
||||
# and we should be able to sudo
|
||||
client.succeed(
|
||||
f"ssh {MOCKADMIN}@server '/run/wrappers/bin/sudo /run/current-system/sw/bin/id' | grep -q 'root'"
|
||||
)
|
||||
'';
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import ./make-test-python.nix {
|
||||
{
|
||||
name = "mediatomb";
|
||||
|
||||
nodes = {
|
||||
|
||||
+73
-76
@@ -1,98 +1,95 @@
|
||||
import ./make-test-python.nix (
|
||||
{ pkgs, ... }:
|
||||
{ lib, hostPkgs, ... }:
|
||||
|
||||
let
|
||||
# Make sure we don't have to go through the startup tutorial
|
||||
customMuseScoreConfig = pkgs.writeText "MuseScore4.ini" ''
|
||||
[application]
|
||||
hasCompletedFirstLaunchSetup=true
|
||||
let
|
||||
# Make sure we don't have to go through the startup tutorial
|
||||
customMuseScoreConfig = hostPkgs.writeText "MuseScore4.ini" ''
|
||||
[application]
|
||||
hasCompletedFirstLaunchSetup=true
|
||||
|
||||
[project]
|
||||
preferredScoreCreationMode=1
|
||||
'';
|
||||
in
|
||||
{
|
||||
name = "musescore";
|
||||
meta = with pkgs.lib.maintainers; {
|
||||
maintainers = [ turion ];
|
||||
[project]
|
||||
preferredScoreCreationMode=1
|
||||
'';
|
||||
in
|
||||
{
|
||||
name = "musescore";
|
||||
meta = with lib.maintainers; {
|
||||
maintainers = [ turion ];
|
||||
};
|
||||
|
||||
nodes.machine =
|
||||
{ pkgs, ... }:
|
||||
{
|
||||
imports = [
|
||||
./common/x11.nix
|
||||
];
|
||||
|
||||
services.xserver.enable = true;
|
||||
environment.systemPackages = with pkgs; [
|
||||
musescore
|
||||
pdfgrep
|
||||
];
|
||||
};
|
||||
|
||||
nodes.machine =
|
||||
{ ... }:
|
||||
enableOCR = true;
|
||||
|
||||
{
|
||||
imports = [
|
||||
./common/x11.nix
|
||||
];
|
||||
testScript =
|
||||
{ ... }:
|
||||
''
|
||||
start_all()
|
||||
machine.wait_for_x()
|
||||
|
||||
services.xserver.enable = true;
|
||||
environment.systemPackages = with pkgs; [
|
||||
musescore
|
||||
pdfgrep
|
||||
];
|
||||
};
|
||||
# Inject custom settings
|
||||
machine.succeed("mkdir -p /root/.config/MuseScore/")
|
||||
machine.succeed(
|
||||
"cp ${customMuseScoreConfig} /root/.config/MuseScore/MuseScore4.ini"
|
||||
)
|
||||
|
||||
enableOCR = true;
|
||||
# Start MuseScore window
|
||||
machine.execute("env XDG_RUNTIME_DIR=$PWD DISPLAY=:0.0 mscore >&2 &")
|
||||
|
||||
testScript =
|
||||
{ ... }:
|
||||
''
|
||||
start_all()
|
||||
machine.wait_for_x()
|
||||
# Wait until MuseScore has launched
|
||||
machine.wait_for_window("MuseScore Studio")
|
||||
|
||||
# Inject custom settings
|
||||
machine.succeed("mkdir -p /root/.config/MuseScore/")
|
||||
machine.succeed(
|
||||
"cp ${customMuseScoreConfig} /root/.config/MuseScore/MuseScore4.ini"
|
||||
)
|
||||
machine.screenshot("MuseScore0")
|
||||
|
||||
# Start MuseScore window
|
||||
machine.execute("env XDG_RUNTIME_DIR=$PWD DISPLAY=:0.0 mscore >&2 &")
|
||||
# Create a new score
|
||||
machine.send_key("ctrl-n")
|
||||
|
||||
# Wait until MuseScore has launched
|
||||
machine.wait_for_window("MuseScore Studio")
|
||||
# Wait until the creation wizard appears
|
||||
machine.wait_for_window("New score")
|
||||
|
||||
machine.screenshot("MuseScore0")
|
||||
machine.screenshot("MuseScore1")
|
||||
|
||||
# Create a new score
|
||||
machine.send_key("ctrl-n")
|
||||
machine.send_key("tab")
|
||||
machine.send_key("tab")
|
||||
machine.send_key("ret")
|
||||
|
||||
# Wait until the creation wizard appears
|
||||
machine.wait_for_window("New score")
|
||||
machine.sleep(2)
|
||||
|
||||
machine.screenshot("MuseScore1")
|
||||
machine.send_key("tab")
|
||||
# Type the beginning of https://de.wikipedia.org/wiki/Alle_meine_Entchen
|
||||
machine.send_chars("cdef6gg5aaaa7g")
|
||||
machine.sleep(1)
|
||||
|
||||
machine.send_key("tab")
|
||||
machine.send_key("tab")
|
||||
machine.send_key("ret")
|
||||
machine.screenshot("MuseScore2")
|
||||
|
||||
machine.sleep(2)
|
||||
# Go to the export dialogue and create a PDF
|
||||
machine.send_key("ctrl-p")
|
||||
|
||||
machine.send_key("tab")
|
||||
# Type the beginning of https://de.wikipedia.org/wiki/Alle_meine_Entchen
|
||||
machine.send_chars("cdef6gg5aaaa7g")
|
||||
machine.sleep(1)
|
||||
# Wait until the Print dialogue appears.
|
||||
machine.wait_for_window("Print")
|
||||
|
||||
machine.screenshot("MuseScore2")
|
||||
machine.screenshot("MuseScore4")
|
||||
machine.send_key("alt-p")
|
||||
machine.sleep(1)
|
||||
|
||||
# Go to the export dialogue and create a PDF
|
||||
machine.send_key("ctrl-p")
|
||||
machine.screenshot("MuseScore5")
|
||||
|
||||
# Wait until the Print dialogue appears.
|
||||
machine.wait_for_window("Print")
|
||||
# Wait until PDF is exported
|
||||
machine.wait_for_file('"/root/Untitled score.pdf"')
|
||||
|
||||
machine.screenshot("MuseScore4")
|
||||
machine.send_key("alt-p")
|
||||
machine.sleep(1)
|
||||
|
||||
machine.screenshot("MuseScore5")
|
||||
|
||||
# Wait until PDF is exported
|
||||
machine.wait_for_file('"/root/Untitled score.pdf"')
|
||||
|
||||
## Check that it contains the title of the score
|
||||
machine.succeed('pdfgrep "Untitled score" "/root/Untitled score.pdf"')
|
||||
machine.copy_from_vm("/root/Untitled score.pdf")
|
||||
'';
|
||||
}
|
||||
)
|
||||
## Check that it contains the title of the score
|
||||
machine.succeed('pdfgrep "Untitled score" "/root/Untitled score.pdf"')
|
||||
machine.copy_from_vm("/root/Untitled score.pdf")
|
||||
'';
|
||||
}
|
||||
|
||||
@@ -1,73 +1,66 @@
|
||||
import ../make-test-python.nix (
|
||||
{ lib, ... }:
|
||||
let
|
||||
peer1-ip = "538:f40f:1c51:9bd9:9569:d3f6:d0a1:b2df";
|
||||
peer2-ip = "5b6:6776:fee0:c1f3:db00:b6a8:d013:d38f";
|
||||
in
|
||||
{
|
||||
name = "mycelium";
|
||||
meta.maintainers = with lib.maintainers; [ lassulus ];
|
||||
{ lib, ... }:
|
||||
let
|
||||
peer1-ip = "538:f40f:1c51:9bd9:9569:d3f6:d0a1:b2df";
|
||||
peer2-ip = "5b6:6776:fee0:c1f3:db00:b6a8:d013:d38f";
|
||||
in
|
||||
{
|
||||
name = "mycelium";
|
||||
meta.maintainers = with lib.maintainers; [ lassulus ];
|
||||
|
||||
nodes = {
|
||||
|
||||
peer1 =
|
||||
{ config, pkgs, ... }:
|
||||
nodes = {
|
||||
peer1 = {
|
||||
virtualisation.vlans = [ 1 ];
|
||||
networking.interfaces.eth1.ipv4.addresses = [
|
||||
{
|
||||
virtualisation.vlans = [ 1 ];
|
||||
networking.interfaces.eth1.ipv4.addresses = [
|
||||
{
|
||||
address = "192.168.1.11";
|
||||
prefixLength = 24;
|
||||
}
|
||||
];
|
||||
address = "192.168.1.11";
|
||||
prefixLength = 24;
|
||||
}
|
||||
];
|
||||
|
||||
services.mycelium = {
|
||||
enable = true;
|
||||
addHostedPublicNodes = false;
|
||||
openFirewall = true;
|
||||
keyFile = ./peer1.key;
|
||||
peers = [
|
||||
"quic://192.168.1.12:9651"
|
||||
"tcp://192.168.1.12:9651"
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
peer2 =
|
||||
{ config, pkgs, ... }:
|
||||
{
|
||||
virtualisation.vlans = [ 1 ];
|
||||
networking.interfaces.eth1.ipv4.addresses = [
|
||||
{
|
||||
address = "192.168.1.12";
|
||||
prefixLength = 24;
|
||||
}
|
||||
];
|
||||
|
||||
services.mycelium = {
|
||||
enable = true;
|
||||
addHostedPublicNodes = false;
|
||||
openFirewall = true;
|
||||
keyFile = ./peer2.key;
|
||||
};
|
||||
};
|
||||
services.mycelium = {
|
||||
enable = true;
|
||||
addHostedPublicNodes = false;
|
||||
openFirewall = true;
|
||||
keyFile = ./peer1.key;
|
||||
peers = [
|
||||
"quic://192.168.1.12:9651"
|
||||
"tcp://192.168.1.12:9651"
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
testScript = ''
|
||||
start_all()
|
||||
peer2 = {
|
||||
virtualisation.vlans = [ 1 ];
|
||||
networking.interfaces.eth1.ipv4.addresses = [
|
||||
{
|
||||
address = "192.168.1.12";
|
||||
prefixLength = 24;
|
||||
}
|
||||
];
|
||||
|
||||
peer1.wait_for_unit("network-online.target")
|
||||
peer2.wait_for_unit("network-online.target")
|
||||
peer1.wait_for_unit("mycelium.service")
|
||||
peer2.wait_for_unit("mycelium.service")
|
||||
services.mycelium = {
|
||||
enable = true;
|
||||
addHostedPublicNodes = false;
|
||||
openFirewall = true;
|
||||
keyFile = ./peer2.key;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
# Give mycelium some time to discover the other peer
|
||||
peer1.wait_until_succeeds("ping -c1 ${peer2-ip}", timeout=10)
|
||||
peer2.succeed("ping -c1 ${peer1-ip}")
|
||||
testScript = ''
|
||||
start_all()
|
||||
|
||||
peer1.succeed("mycelium peers list | grep 192.168.1.12")
|
||||
peer2.succeed("mycelium peers list | grep 192.168.1.11")
|
||||
peer1.wait_for_unit("network-online.target")
|
||||
peer2.wait_for_unit("network-online.target")
|
||||
peer1.wait_for_unit("mycelium.service")
|
||||
peer2.wait_for_unit("mycelium.service")
|
||||
|
||||
'';
|
||||
}
|
||||
)
|
||||
# Give mycelium some time to discover the other peer
|
||||
peer1.wait_until_succeeds("ping -c1 ${peer2-ip}", timeout=10)
|
||||
peer2.succeed("ping -c1 ${peer1-ip}")
|
||||
|
||||
peer1.succeed("mycelium peers list | grep 192.168.1.12")
|
||||
peer2.succeed("mycelium peers list | grep 192.168.1.11")
|
||||
|
||||
'';
|
||||
}
|
||||
|
||||
+8
-13
@@ -1,19 +1,14 @@
|
||||
import ./make-test-python.nix {
|
||||
{
|
||||
name = "neo4j";
|
||||
|
||||
nodes = {
|
||||
server =
|
||||
{ ... }:
|
||||
nodes.server = {
|
||||
virtualisation.memorySize = 4096;
|
||||
virtualisation.diskSize = 1024;
|
||||
|
||||
{
|
||||
virtualisation.memorySize = 4096;
|
||||
virtualisation.diskSize = 1024;
|
||||
|
||||
services.neo4j.enable = true;
|
||||
# require tls certs to be available
|
||||
services.neo4j.https.enable = false;
|
||||
services.neo4j.bolt.enable = false;
|
||||
};
|
||||
services.neo4j.enable = true;
|
||||
# require tls certs to be available
|
||||
services.neo4j.https.enable = false;
|
||||
services.neo4j.bolt.enable = false;
|
||||
};
|
||||
|
||||
testScript = ''
|
||||
|
||||
@@ -2,7 +2,7 @@ let
|
||||
certs = import ./common/acme/server/snakeoil-certs.nix;
|
||||
domain = certs.domain;
|
||||
in
|
||||
import ./make-test-python.nix {
|
||||
{
|
||||
name = "schleuder";
|
||||
nodes.machine =
|
||||
{ pkgs, ... }:
|
||||
|
||||
+51
-66
@@ -1,77 +1,62 @@
|
||||
{ runTest }:
|
||||
{
|
||||
system ? builtins.currentSystem,
|
||||
config ? { },
|
||||
pkgs ? import ../.. { inherit system config; },
|
||||
}:
|
||||
default = runTest {
|
||||
name = "sddm";
|
||||
|
||||
with import ../lib/testing-python.nix { inherit system pkgs; };
|
||||
|
||||
let
|
||||
inherit (pkgs) lib;
|
||||
|
||||
tests = {
|
||||
default = {
|
||||
name = "sddm";
|
||||
|
||||
nodes.machine =
|
||||
{ ... }:
|
||||
{
|
||||
imports = [ ./common/user-account.nix ];
|
||||
services.xserver.enable = true;
|
||||
services.displayManager.sddm.enable = true;
|
||||
services.displayManager.defaultSession = "none+icewm";
|
||||
services.xserver.windowManager.icewm.enable = true;
|
||||
};
|
||||
|
||||
enableOCR = true;
|
||||
|
||||
testScript =
|
||||
{ nodes, ... }:
|
||||
let
|
||||
user = nodes.machine.users.users.alice;
|
||||
in
|
||||
''
|
||||
start_all()
|
||||
machine.wait_for_text("(?i)select your user")
|
||||
machine.screenshot("sddm")
|
||||
machine.send_chars("${user.password}\n")
|
||||
machine.wait_for_file("/tmp/xauth_*")
|
||||
machine.succeed("xauth merge /tmp/xauth_*")
|
||||
machine.wait_for_window("^IceWM ")
|
||||
'';
|
||||
nodes.machine = {
|
||||
imports = [ ./common/user-account.nix ];
|
||||
services.xserver.enable = true;
|
||||
services.displayManager.sddm.enable = true;
|
||||
services.displayManager.defaultSession = "none+icewm";
|
||||
services.xserver.windowManager.icewm.enable = true;
|
||||
};
|
||||
|
||||
autoLogin = {
|
||||
enableOCR = true;
|
||||
|
||||
testScript =
|
||||
{ nodes, ... }:
|
||||
let
|
||||
user = nodes.machine.users.users.alice;
|
||||
in
|
||||
''
|
||||
start_all()
|
||||
machine.wait_for_text("(?i)select your user")
|
||||
machine.screenshot("sddm")
|
||||
machine.send_chars("${user.password}\n")
|
||||
machine.wait_for_file("/tmp/xauth_*")
|
||||
machine.succeed("xauth merge /tmp/xauth_*")
|
||||
machine.wait_for_window("^IceWM ")
|
||||
'';
|
||||
};
|
||||
|
||||
autoLogin = runTest (
|
||||
{ lib, ... }:
|
||||
{
|
||||
name = "sddm-autologin";
|
||||
meta = with pkgs.lib.maintainers; {
|
||||
meta = with lib.maintainers; {
|
||||
maintainers = [ ttuegel ];
|
||||
};
|
||||
|
||||
nodes.machine =
|
||||
{ ... }:
|
||||
{
|
||||
imports = [ ./common/user-account.nix ];
|
||||
services.xserver.enable = true;
|
||||
services.displayManager = {
|
||||
sddm.enable = true;
|
||||
autoLogin = {
|
||||
enable = true;
|
||||
user = "alice";
|
||||
};
|
||||
nodes.machine = {
|
||||
imports = [ ./common/user-account.nix ];
|
||||
services.xserver.enable = true;
|
||||
services.displayManager = {
|
||||
sddm.enable = true;
|
||||
autoLogin = {
|
||||
enable = true;
|
||||
user = "alice";
|
||||
};
|
||||
services.displayManager.defaultSession = "none+icewm";
|
||||
services.xserver.windowManager.icewm.enable = true;
|
||||
};
|
||||
services.displayManager.defaultSession = "none+icewm";
|
||||
services.xserver.windowManager.icewm.enable = true;
|
||||
};
|
||||
|
||||
testScript =
|
||||
{ nodes, ... }:
|
||||
''
|
||||
start_all()
|
||||
machine.wait_for_file("/tmp/xauth_*")
|
||||
machine.succeed("xauth merge /tmp/xauth_*")
|
||||
machine.wait_for_window("^IceWM ")
|
||||
'';
|
||||
};
|
||||
};
|
||||
in
|
||||
lib.mapAttrs (lib.const makeTest) tests
|
||||
testScript = ''
|
||||
start_all()
|
||||
machine.wait_for_file("/tmp/xauth_*")
|
||||
machine.succeed("xauth merge /tmp/xauth_*")
|
||||
machine.wait_for_window("^IceWM ")
|
||||
'';
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,55 +1,52 @@
|
||||
import ./make-test-python.nix (
|
||||
{ ... }:
|
||||
{
|
||||
name = "trilium-server";
|
||||
nodes = {
|
||||
default = {
|
||||
services.trilium-server.enable = true;
|
||||
};
|
||||
configured = {
|
||||
services.trilium-server = {
|
||||
enable = true;
|
||||
dataDir = "/data/trilium";
|
||||
};
|
||||
};
|
||||
|
||||
nginx = {
|
||||
services.trilium-server = {
|
||||
enable = true;
|
||||
nginx.enable = true;
|
||||
nginx.hostName = "trilium.example.com";
|
||||
};
|
||||
{
|
||||
name = "trilium-server";
|
||||
nodes = {
|
||||
default = {
|
||||
services.trilium-server.enable = true;
|
||||
};
|
||||
configured = {
|
||||
services.trilium-server = {
|
||||
enable = true;
|
||||
dataDir = "/data/trilium";
|
||||
};
|
||||
};
|
||||
|
||||
testScript = ''
|
||||
start_all()
|
||||
nginx = {
|
||||
services.trilium-server = {
|
||||
enable = true;
|
||||
nginx.enable = true;
|
||||
nginx.hostName = "trilium.example.com";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
with subtest("by default works without configuration"):
|
||||
default.wait_for_unit("trilium-server.service")
|
||||
testScript = ''
|
||||
start_all()
|
||||
|
||||
with subtest("by default available on port 8080"):
|
||||
default.wait_for_unit("trilium-server.service")
|
||||
default.wait_for_open_port(8080)
|
||||
# we output to /dev/null here to avoid a python UTF-8 decode error
|
||||
# but the check will still fail if the service doesn't respond
|
||||
default.succeed("curl --fail -o /dev/null 127.0.0.1:8080")
|
||||
with subtest("by default works without configuration"):
|
||||
default.wait_for_unit("trilium-server.service")
|
||||
|
||||
with subtest("by default creates empty document"):
|
||||
default.wait_for_unit("trilium-server.service")
|
||||
default.succeed("test -f /var/lib/trilium/document.db")
|
||||
with subtest("by default available on port 8080"):
|
||||
default.wait_for_unit("trilium-server.service")
|
||||
default.wait_for_open_port(8080)
|
||||
# we output to /dev/null here to avoid a python UTF-8 decode error
|
||||
# but the check will still fail if the service doesn't respond
|
||||
default.succeed("curl --fail -o /dev/null 127.0.0.1:8080")
|
||||
|
||||
with subtest("configured with custom data store"):
|
||||
configured.wait_for_unit("trilium-server.service")
|
||||
configured.succeed("test -f /data/trilium/document.db")
|
||||
with subtest("by default creates empty document"):
|
||||
default.wait_for_unit("trilium-server.service")
|
||||
default.succeed("test -f /var/lib/trilium/document.db")
|
||||
|
||||
with subtest("nginx with custom host name"):
|
||||
nginx.wait_for_unit("trilium-server.service")
|
||||
nginx.wait_for_unit("nginx.service")
|
||||
with subtest("configured with custom data store"):
|
||||
configured.wait_for_unit("trilium-server.service")
|
||||
configured.succeed("test -f /data/trilium/document.db")
|
||||
|
||||
nginx.succeed(
|
||||
"curl --resolve 'trilium.example.com:80:127.0.0.1' http://trilium.example.com/"
|
||||
)
|
||||
'';
|
||||
}
|
||||
)
|
||||
with subtest("nginx with custom host name"):
|
||||
nginx.wait_for_unit("trilium-server.service")
|
||||
nginx.wait_for_unit("nginx.service")
|
||||
|
||||
nginx.succeed(
|
||||
"curl --resolve 'trilium.example.com:80:127.0.0.1' http://trilium.example.com/"
|
||||
)
|
||||
'';
|
||||
}
|
||||
|
||||
@@ -1,11 +1,6 @@
|
||||
{ runTest }:
|
||||
{
|
||||
system ? builtins.currentSystem,
|
||||
config ? { },
|
||||
pkgs ? import ../../.. { inherit system config; },
|
||||
}:
|
||||
|
||||
{
|
||||
remote-write = import ./remote-write.nix { inherit system pkgs; };
|
||||
vmalert = import ./vmalert.nix { inherit system pkgs; };
|
||||
external-promscrape-config = import ./external-promscrape-config.nix { inherit system pkgs; };
|
||||
remote-write = runTest ./remote-write.nix;
|
||||
vmalert = runTest ./vmalert.nix;
|
||||
external-promscrape-config = runTest ./external-promscrape-config.nix;
|
||||
}
|
||||
|
||||
@@ -1,82 +1,70 @@
|
||||
import ../make-test-python.nix (
|
||||
{
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
let
|
||||
nodeExporterPort = 9100;
|
||||
promscrapeConfig = {
|
||||
global = {
|
||||
scrape_interval = "2s";
|
||||
};
|
||||
scrape_configs = [
|
||||
{
|
||||
job_name = "node";
|
||||
static_configs = [
|
||||
{
|
||||
targets = [
|
||||
"node:${toString nodeExporterPort}"
|
||||
];
|
||||
}
|
||||
];
|
||||
}
|
||||
];
|
||||
{ lib, pkgs, ... }:
|
||||
let
|
||||
nodeExporterPort = 9100;
|
||||
promscrapeConfig = {
|
||||
global = {
|
||||
scrape_interval = "2s";
|
||||
};
|
||||
settingsFormat = pkgs.formats.yaml { };
|
||||
promscrapeConfigYaml = settingsFormat.generate "prometheusConfig.yaml" promscrapeConfig;
|
||||
in
|
||||
{
|
||||
name = "victoriametrics-external-promscrape-config";
|
||||
meta = with pkgs.lib.maintainers; {
|
||||
maintainers = [
|
||||
ryan4yin
|
||||
];
|
||||
};
|
||||
|
||||
nodes = {
|
||||
victoriametrics =
|
||||
{
|
||||
config,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
{
|
||||
environment.systemPackages = [ pkgs.jq ];
|
||||
networking.firewall.allowedTCPPorts = [ 8428 ];
|
||||
services.victoriametrics = {
|
||||
enable = true;
|
||||
extraOptions = [
|
||||
"-promscrape.config=${toString promscrapeConfigYaml}"
|
||||
scrape_configs = [
|
||||
{
|
||||
job_name = "node";
|
||||
static_configs = [
|
||||
{
|
||||
targets = [
|
||||
"node:${toString nodeExporterPort}"
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
||||
];
|
||||
}
|
||||
];
|
||||
};
|
||||
settingsFormat = pkgs.formats.yaml { };
|
||||
promscrapeConfigYaml = settingsFormat.generate "prometheusConfig.yaml" promscrapeConfig;
|
||||
in
|
||||
{
|
||||
name = "victoriametrics-external-promscrape-config";
|
||||
meta = with lib.maintainers; {
|
||||
maintainers = [
|
||||
ryan4yin
|
||||
];
|
||||
};
|
||||
|
||||
node =
|
||||
{ ... }:
|
||||
{
|
||||
services.prometheus.exporters.node = {
|
||||
enable = true;
|
||||
openFirewall = true;
|
||||
};
|
||||
nodes = {
|
||||
victoriametrics =
|
||||
{ pkgs, ... }:
|
||||
{
|
||||
environment.systemPackages = [ pkgs.jq ];
|
||||
networking.firewall.allowedTCPPorts = [ 8428 ];
|
||||
services.victoriametrics = {
|
||||
enable = true;
|
||||
extraOptions = [
|
||||
"-promscrape.config=${toString promscrapeConfigYaml}"
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
node = {
|
||||
services.prometheus.exporters.node = {
|
||||
enable = true;
|
||||
openFirewall = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
testScript = ''
|
||||
node.wait_for_unit("prometheus-node-exporter")
|
||||
node.wait_for_open_port(${toString nodeExporterPort})
|
||||
testScript = ''
|
||||
node.wait_for_unit("prometheus-node-exporter")
|
||||
node.wait_for_open_port(${toString nodeExporterPort})
|
||||
|
||||
victoriametrics.wait_for_unit("victoriametrics")
|
||||
victoriametrics.wait_for_open_port(8428)
|
||||
victoriametrics.wait_for_unit("victoriametrics")
|
||||
victoriametrics.wait_for_open_port(8428)
|
||||
|
||||
|
||||
promscrape_config = victoriametrics.succeed("journalctl -u victoriametrics -o cat | grep 'promscrape.config'")
|
||||
assert '${toString promscrapeConfigYaml}' in promscrape_config
|
||||
promscrape_config = victoriametrics.succeed("journalctl -u victoriametrics -o cat | grep 'promscrape.config'")
|
||||
assert '${toString promscrapeConfigYaml}' in promscrape_config
|
||||
|
||||
victoriametrics.wait_until_succeeds(
|
||||
"curl -sf 'http://localhost:8428/api/v1/query?query=node_exporter_build_info\{instance=\"node:9100\"\}' | "
|
||||
+ "jq '.data.result[0].value[1]' | grep '\"1\"'"
|
||||
)
|
||||
'';
|
||||
}
|
||||
)
|
||||
victoriametrics.wait_until_succeeds(
|
||||
"curl -sf 'http://localhost:8428/api/v1/query?query=node_exporter_build_info\{instance=\"node:9100\"\}' | "
|
||||
+ "jq '.data.result[0].value[1]' | grep '\"1\"'"
|
||||
)
|
||||
'';
|
||||
}
|
||||
|
||||
@@ -1,103 +1,87 @@
|
||||
# Primarily reference the implementation of <nixos/tests/prometheus/remote-write.nix>
|
||||
import ../make-test-python.nix (
|
||||
{
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
let
|
||||
username = "vmtest";
|
||||
password = "fsddfy8233rb"; # random string
|
||||
passwordFile = pkgs.writeText "password-file" password;
|
||||
in
|
||||
{
|
||||
name = "victoriametrics-remote-write";
|
||||
meta = with pkgs.lib.maintainers; {
|
||||
maintainers = [
|
||||
yorickvp
|
||||
ryan4yin
|
||||
];
|
||||
};
|
||||
{ lib, pkgs, ... }:
|
||||
let
|
||||
username = "vmtest";
|
||||
password = "fsddfy8233rb"; # random string
|
||||
passwordFile = pkgs.writeText "password-file" password;
|
||||
in
|
||||
{
|
||||
name = "victoriametrics-remote-write";
|
||||
meta = with lib.maintainers; {
|
||||
maintainers = [
|
||||
yorickvp
|
||||
ryan4yin
|
||||
];
|
||||
};
|
||||
|
||||
nodes = {
|
||||
victoriametrics =
|
||||
{
|
||||
config,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
{
|
||||
environment.systemPackages = [ pkgs.jq ];
|
||||
networking.firewall.allowedTCPPorts = [ 8428 ];
|
||||
services.victoriametrics = {
|
||||
enable = true;
|
||||
extraOptions = [
|
||||
"-httpAuth.username=${username}"
|
||||
"-httpAuth.password=file://${toString passwordFile}"
|
||||
nodes = {
|
||||
victoriametrics =
|
||||
{ pkgs, ... }:
|
||||
{
|
||||
environment.systemPackages = [ pkgs.jq ];
|
||||
networking.firewall.allowedTCPPorts = [ 8428 ];
|
||||
services.victoriametrics = {
|
||||
enable = true;
|
||||
extraOptions = [
|
||||
"-httpAuth.username=${username}"
|
||||
"-httpAuth.password=file://${toString passwordFile}"
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
vmagent =
|
||||
{ config, pkgs, ... }:
|
||||
{
|
||||
environment.systemPackages = [ pkgs.jq ];
|
||||
services.vmagent = {
|
||||
enable = true;
|
||||
remoteWrite = {
|
||||
url = "http://victoriametrics:8428/api/v1/write";
|
||||
basicAuthUsername = username;
|
||||
basicAuthPasswordFile = toString passwordFile;
|
||||
};
|
||||
|
||||
prometheusConfig = {
|
||||
global = {
|
||||
scrape_interval = "2s";
|
||||
};
|
||||
scrape_configs = [
|
||||
{
|
||||
job_name = "node";
|
||||
static_configs = [
|
||||
{
|
||||
targets = [
|
||||
"node:${toString config.services.prometheus.exporters.node.port}"
|
||||
];
|
||||
}
|
||||
];
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
vmagent =
|
||||
{
|
||||
config,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
{
|
||||
environment.systemPackages = [ pkgs.jq ];
|
||||
services.vmagent = {
|
||||
enable = true;
|
||||
remoteWrite = {
|
||||
url = "http://victoriametrics:8428/api/v1/write";
|
||||
basicAuthUsername = username;
|
||||
basicAuthPasswordFile = toString passwordFile;
|
||||
};
|
||||
|
||||
prometheusConfig = {
|
||||
global = {
|
||||
scrape_interval = "2s";
|
||||
};
|
||||
scrape_configs = [
|
||||
{
|
||||
job_name = "node";
|
||||
static_configs = [
|
||||
{
|
||||
targets = [
|
||||
"node:${toString config.services.prometheus.exporters.node.port}"
|
||||
];
|
||||
}
|
||||
];
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
node =
|
||||
{ ... }:
|
||||
{
|
||||
services.prometheus.exporters.node = {
|
||||
enable = true;
|
||||
openFirewall = true;
|
||||
};
|
||||
};
|
||||
node = {
|
||||
services.prometheus.exporters.node = {
|
||||
enable = true;
|
||||
openFirewall = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
testScript = ''
|
||||
node.wait_for_unit("prometheus-node-exporter")
|
||||
node.wait_for_open_port(9100)
|
||||
testScript = ''
|
||||
node.wait_for_unit("prometheus-node-exporter")
|
||||
node.wait_for_open_port(9100)
|
||||
|
||||
victoriametrics.wait_for_unit("victoriametrics")
|
||||
victoriametrics.wait_for_open_port(8428)
|
||||
victoriametrics.wait_for_unit("victoriametrics")
|
||||
victoriametrics.wait_for_open_port(8428)
|
||||
|
||||
vmagent.wait_for_unit("vmagent")
|
||||
vmagent.wait_for_unit("vmagent")
|
||||
|
||||
# check remote write
|
||||
victoriametrics.wait_until_succeeds(
|
||||
"curl --user '${username}:${password}' -sf 'http://localhost:8428/api/v1/query?query=node_exporter_build_info\{instance=\"node:9100\"\}' | "
|
||||
+ "jq '.data.result[0].value[1]' | grep '\"1\"'"
|
||||
)
|
||||
'';
|
||||
}
|
||||
)
|
||||
# check remote write
|
||||
victoriametrics.wait_until_succeeds(
|
||||
"curl --user '${username}:${password}' -sf 'http://localhost:8428/api/v1/query?query=node_exporter_build_info\{instance=\"node:9100\"\}' | "
|
||||
+ "jq '.data.result[0].value[1]' | grep '\"1\"'"
|
||||
)
|
||||
'';
|
||||
}
|
||||
|
||||
@@ -1,179 +1,157 @@
|
||||
# Primarily reference the implementation of <nixos/tests/prometheus/alertmanager.nix>
|
||||
import ../make-test-python.nix (
|
||||
{
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
{
|
||||
name = "victoriametrics-vmalert";
|
||||
meta = with pkgs.lib.maintainers; {
|
||||
maintainers = [
|
||||
yorickvp
|
||||
ryan4yin
|
||||
];
|
||||
{ lib, pkgs, ... }:
|
||||
{
|
||||
name = "victoriametrics-vmalert";
|
||||
meta = with lib.maintainers; {
|
||||
maintainers = [
|
||||
yorickvp
|
||||
ryan4yin
|
||||
];
|
||||
};
|
||||
|
||||
nodes = {
|
||||
victoriametrics =
|
||||
{ config, pkgs, ... }:
|
||||
{
|
||||
environment.systemPackages = [ pkgs.jq ];
|
||||
networking.firewall.allowedTCPPorts = [ 8428 ];
|
||||
services.victoriametrics = {
|
||||
enable = true;
|
||||
prometheusConfig = {
|
||||
global = {
|
||||
scrape_interval = "2s";
|
||||
};
|
||||
scrape_configs = [
|
||||
{
|
||||
job_name = "alertmanager";
|
||||
static_configs = [
|
||||
{
|
||||
targets = [
|
||||
"alertmanager:${toString config.services.prometheus.alertmanager.port}"
|
||||
];
|
||||
}
|
||||
];
|
||||
}
|
||||
{
|
||||
job_name = "node";
|
||||
static_configs = [
|
||||
{
|
||||
targets = [
|
||||
"node:${toString config.services.prometheus.exporters.node.port}"
|
||||
];
|
||||
}
|
||||
];
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
services.vmalert.instances."" = {
|
||||
enable = true;
|
||||
settings = {
|
||||
"datasource.url" = "http://localhost:8428"; # victoriametrics' api
|
||||
"notifier.url" = [
|
||||
"http://alertmanager:${toString config.services.prometheus.alertmanager.port}"
|
||||
]; # alertmanager's api
|
||||
rule = [
|
||||
(pkgs.writeText "instance-down.yml" ''
|
||||
groups:
|
||||
- name: test
|
||||
rules:
|
||||
- alert: InstanceDown
|
||||
expr: up == 0
|
||||
for: 5s
|
||||
labels:
|
||||
severity: page
|
||||
annotations:
|
||||
summary: "Instance {{ $labels.instance }} down"
|
||||
'')
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
alertmanager = {
|
||||
services.prometheus.alertmanager = {
|
||||
enable = true;
|
||||
openFirewall = true;
|
||||
|
||||
configuration = {
|
||||
global = {
|
||||
resolve_timeout = "1m";
|
||||
};
|
||||
|
||||
route = {
|
||||
# Root route node
|
||||
receiver = "test";
|
||||
group_by = [ "..." ];
|
||||
continue = false;
|
||||
group_wait = "1s";
|
||||
group_interval = "15s";
|
||||
repeat_interval = "24h";
|
||||
};
|
||||
|
||||
receivers = [
|
||||
{
|
||||
name = "test";
|
||||
webhook_configs = [
|
||||
{
|
||||
url = "http://logger:6725";
|
||||
send_resolved = true;
|
||||
max_alerts = 0;
|
||||
}
|
||||
];
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
nodes = {
|
||||
victoriametrics =
|
||||
{
|
||||
config,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
{
|
||||
environment.systemPackages = [ pkgs.jq ];
|
||||
networking.firewall.allowedTCPPorts = [ 8428 ];
|
||||
services.victoriametrics = {
|
||||
enable = true;
|
||||
prometheusConfig = {
|
||||
global = {
|
||||
scrape_interval = "2s";
|
||||
};
|
||||
scrape_configs = [
|
||||
{
|
||||
job_name = "alertmanager";
|
||||
static_configs = [
|
||||
{
|
||||
targets = [
|
||||
"alertmanager:${toString config.services.prometheus.alertmanager.port}"
|
||||
];
|
||||
}
|
||||
];
|
||||
}
|
||||
{
|
||||
job_name = "node";
|
||||
static_configs = [
|
||||
{
|
||||
targets = [
|
||||
"node:${toString config.services.prometheus.exporters.node.port}"
|
||||
];
|
||||
}
|
||||
];
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
logger = {
|
||||
networking.firewall.allowedTCPPorts = [ 6725 ];
|
||||
|
||||
services.vmalert.instances."" = {
|
||||
enable = true;
|
||||
settings = {
|
||||
"datasource.url" = "http://localhost:8428"; # victoriametrics' api
|
||||
"notifier.url" = [
|
||||
"http://alertmanager:${toString config.services.prometheus.alertmanager.port}"
|
||||
]; # alertmanager's api
|
||||
rule = [
|
||||
(pkgs.writeText "instance-down.yml" ''
|
||||
groups:
|
||||
- name: test
|
||||
rules:
|
||||
- alert: InstanceDown
|
||||
expr: up == 0
|
||||
for: 5s
|
||||
labels:
|
||||
severity: page
|
||||
annotations:
|
||||
summary: "Instance {{ $labels.instance }} down"
|
||||
'')
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
alertmanager =
|
||||
{
|
||||
config,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
{
|
||||
services.prometheus.alertmanager = {
|
||||
enable = true;
|
||||
openFirewall = true;
|
||||
|
||||
configuration = {
|
||||
global = {
|
||||
resolve_timeout = "1m";
|
||||
};
|
||||
|
||||
route = {
|
||||
# Root route node
|
||||
receiver = "test";
|
||||
group_by = [ "..." ];
|
||||
continue = false;
|
||||
group_wait = "1s";
|
||||
group_interval = "15s";
|
||||
repeat_interval = "24h";
|
||||
};
|
||||
|
||||
receivers = [
|
||||
{
|
||||
name = "test";
|
||||
webhook_configs = [
|
||||
{
|
||||
url = "http://logger:6725";
|
||||
send_resolved = true;
|
||||
max_alerts = 0;
|
||||
}
|
||||
];
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
logger =
|
||||
{
|
||||
config,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
{
|
||||
networking.firewall.allowedTCPPorts = [ 6725 ];
|
||||
|
||||
services.prometheus.alertmanagerWebhookLogger.enable = true;
|
||||
};
|
||||
services.prometheus.alertmanagerWebhookLogger.enable = true;
|
||||
};
|
||||
};
|
||||
|
||||
testScript = ''
|
||||
alertmanager.wait_for_unit("alertmanager")
|
||||
alertmanager.wait_for_open_port(9093)
|
||||
alertmanager.wait_until_succeeds("curl -s http://127.0.0.1:9093/-/ready")
|
||||
testScript = ''
|
||||
alertmanager.wait_for_unit("alertmanager")
|
||||
alertmanager.wait_for_open_port(9093)
|
||||
alertmanager.wait_until_succeeds("curl -s http://127.0.0.1:9093/-/ready")
|
||||
|
||||
logger.wait_for_unit("alertmanager-webhook-logger")
|
||||
logger.wait_for_open_port(6725)
|
||||
logger.wait_for_unit("alertmanager-webhook-logger")
|
||||
logger.wait_for_open_port(6725)
|
||||
|
||||
victoriametrics.wait_for_unit("victoriametrics")
|
||||
victoriametrics.wait_for_unit("vmalert")
|
||||
victoriametrics.wait_for_open_port(8428)
|
||||
victoriametrics.wait_for_unit("victoriametrics")
|
||||
victoriametrics.wait_for_unit("vmalert")
|
||||
victoriametrics.wait_for_open_port(8428)
|
||||
|
||||
victoriametrics.wait_until_succeeds(
|
||||
"curl -sf 'http://127.0.0.1:8428/api/v1/query?query=count(up\{job=\"alertmanager\"\}==1)' | "
|
||||
+ "jq '.data.result[0].value[1]' | grep '\"1\"'"
|
||||
)
|
||||
victoriametrics.wait_until_succeeds(
|
||||
"curl -sf 'http://127.0.0.1:8428/api/v1/query?query=count(up\{job=\"alertmanager\"\}==1)' | "
|
||||
+ "jq '.data.result[0].value[1]' | grep '\"1\"'"
|
||||
)
|
||||
|
||||
victoriametrics.wait_until_succeeds(
|
||||
"curl -sf 'http://127.0.0.1:8428/api/v1/query?query=sum(alertmanager_build_info)%20by%20(version)' | "
|
||||
+ "jq '.data.result[0].metric.version' | grep '\"${pkgs.prometheus-alertmanager.version}\"'"
|
||||
)
|
||||
victoriametrics.wait_until_succeeds(
|
||||
"curl -sf 'http://127.0.0.1:8428/api/v1/query?query=sum(alertmanager_build_info)%20by%20(version)' | "
|
||||
+ "jq '.data.result[0].metric.version' | grep '\"${pkgs.prometheus-alertmanager.version}\"'"
|
||||
)
|
||||
|
||||
victoriametrics.wait_until_succeeds(
|
||||
"curl -sf 'http://127.0.0.1:8428/api/v1/query?query=count(up\{job=\"node\"\}!=1)' | "
|
||||
+ "jq '.data.result[0].value[1]' | grep '\"1\"'"
|
||||
)
|
||||
victoriametrics.wait_until_succeeds(
|
||||
"curl -sf 'http://127.0.0.1:8428/api/v1/query?query=count(up\{job=\"node\"\}!=1)' | "
|
||||
+ "jq '.data.result[0].value[1]' | grep '\"1\"'"
|
||||
)
|
||||
|
||||
victoriametrics.wait_until_succeeds(
|
||||
"curl -sf 'http://127.0.0.1:8428/api/v1/query?query=alertmanager_notifications_total\{integration=\"webhook\"\}' | "
|
||||
+ "jq '.data.result[0].value[1]' | grep -v '\"0\"'"
|
||||
)
|
||||
victoriametrics.wait_until_succeeds(
|
||||
"curl -sf 'http://127.0.0.1:8428/api/v1/query?query=alertmanager_notifications_total\{integration=\"webhook\"\}' | "
|
||||
+ "jq '.data.result[0].value[1]' | grep -v '\"0\"'"
|
||||
)
|
||||
|
||||
logger.wait_until_succeeds(
|
||||
"journalctl -o cat -u alertmanager-webhook-logger.service | grep '\"alertname\":\"InstanceDown\"'"
|
||||
)
|
||||
logger.wait_until_succeeds(
|
||||
"journalctl -o cat -u alertmanager-webhook-logger.service | grep '\"alertname\":\"InstanceDown\"'"
|
||||
)
|
||||
|
||||
logger.log(logger.succeed("systemd-analyze security alertmanager-webhook-logger.service | grep -v '✓'"))
|
||||
logger.log(logger.succeed("systemd-analyze security alertmanager-webhook-logger.service | grep -v '✓'"))
|
||||
|
||||
alertmanager.log(alertmanager.succeed("systemd-analyze security alertmanager.service | grep -v '✓'"))
|
||||
'';
|
||||
}
|
||||
)
|
||||
alertmanager.log(alertmanager.succeed("systemd-analyze security alertmanager.service | grep -v '✓'"))
|
||||
'';
|
||||
}
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
{
|
||||
lib,
|
||||
stdenv,
|
||||
fetchFromGitHub,
|
||||
deadbeef,
|
||||
pkg-config,
|
||||
gtk3,
|
||||
sqlite,
|
||||
}:
|
||||
|
||||
stdenv.mkDerivation {
|
||||
pname = "deadbeef-waveform-seekbar-plugin";
|
||||
version = "0-unstable-2024-11-13";
|
||||
|
||||
# using a fork because original throws a compilation error
|
||||
src = fetchFromGitHub {
|
||||
owner = "Jbsco";
|
||||
repo = "ddb_waveform_seekbar";
|
||||
rev = "2e5ea867a77e37698524d22f41fc59ffae16e63d";
|
||||
hash = "sha256-m6lBF+Yq1gah6kjb9VvIsjVg1i++08JPLzcLLMt+8J8=";
|
||||
};
|
||||
|
||||
nativeBuildInputs = [ pkg-config ];
|
||||
buildInputs = [
|
||||
deadbeef
|
||||
gtk3
|
||||
sqlite
|
||||
];
|
||||
makeFlags = [ "gtk3" ];
|
||||
|
||||
installPhase = ''
|
||||
runHook preInstall
|
||||
|
||||
mkdir -p $out/lib/deadbeef/
|
||||
install -v -c -m 644 gtk3/ddb_misc_waveform_GTK3.so $out/lib/deadbeef/
|
||||
|
||||
runHook postInstall
|
||||
'';
|
||||
|
||||
meta = {
|
||||
description = "Waveform Seekbar plugin for DeaDBeeF audio player";
|
||||
homepage = "https://github.com/cboxdoerfer/ddb_waveform_seekbar";
|
||||
license = lib.licenses.gpl2Plus;
|
||||
platforms = lib.platforms.linux;
|
||||
maintainers = [ lib.maintainers.deudz ];
|
||||
};
|
||||
}
|
||||
@@ -6,16 +6,16 @@
|
||||
|
||||
buildGoModule rec {
|
||||
pname = "helm-diff";
|
||||
version = "3.12.2";
|
||||
version = "3.12.3";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "databus23";
|
||||
repo = pname;
|
||||
repo = "helm-diff";
|
||||
rev = "v${version}";
|
||||
hash = "sha256-N7n9/MjZR9jCRk2iZmFBOxwn6GVUNuUBaQHJqcgOQc4=";
|
||||
hash = "sha256-zYeZwR8hDNYVJGdYjQNrQmyD5AwGcgyO7LzC5bd10k0=";
|
||||
};
|
||||
|
||||
vendorHash = "sha256-uJxLpbFKdH5t08wZD/zPS5UPZO7YPtiBqcdN6997ik4=";
|
||||
vendorHash = "sha256-rz5RZiKGM1AdDm4R2IPOYn///fKKmo96u2LROShFPJM=";
|
||||
|
||||
ldflags = [
|
||||
"-s"
|
||||
|
||||
@@ -60,34 +60,35 @@
|
||||
libvpl,
|
||||
qrcodegencpp,
|
||||
nix-update-script,
|
||||
extra-cmake-modules,
|
||||
}:
|
||||
|
||||
let
|
||||
inherit (lib) optional optionals;
|
||||
|
||||
cef = cef-binary.overrideAttrs (oldAttrs: {
|
||||
version = "127.3.5";
|
||||
version = "138.0.17";
|
||||
__intentionallyOverridingVersion = true; # `cef-binary` uses the overridden `srcHash` values in its source FOD
|
||||
gitRevision = "114ea2a";
|
||||
chromiumVersion = "127.0.6533.120";
|
||||
gitRevision = "ac9b751";
|
||||
chromiumVersion = "138.0.7204.97";
|
||||
|
||||
srcHash =
|
||||
{
|
||||
aarch64-linux = "sha256-s8dR97rAO0mCUwbpYnPWyY3t8movq05HhZZKllhZdBs=";
|
||||
x86_64-linux = "sha256-57E7bZKpViWno9W4AaaSjL9B4uxq+rDXAou1tsiODUg=";
|
||||
aarch64-linux = "sha256-kdO7c9oUfv0HK8wTmvYzw9S6EapnSGEQNCGN9D1JSL0=";
|
||||
x86_64-linux = "sha256-3qgIhen6l/kxttyw0z78nmwox62riVhlmFSGPkUot7g=";
|
||||
}
|
||||
.${stdenv.hostPlatform.system} or (throw "unsupported system ${stdenv.hostPlatform.system}");
|
||||
});
|
||||
in
|
||||
stdenv.mkDerivation (finalAttrs: {
|
||||
pname = "obs-studio";
|
||||
version = "31.0.4";
|
||||
version = "31.1.0";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "obsproject";
|
||||
repo = "obs-studio";
|
||||
rev = finalAttrs.version;
|
||||
hash = "sha256-YxBPVXin8oJlo++oJogY1WMamIJmRqtSmKZDBsIZPU4=";
|
||||
hash = "sha256-espGKoKldgjWoCEE+Xor7+N5N86HvWCf0V18tb8GaC8=";
|
||||
fetchSubmodules = true;
|
||||
};
|
||||
|
||||
@@ -107,6 +108,7 @@ stdenv.mkDerivation (finalAttrs: {
|
||||
pkg-config
|
||||
wrapGAppsHook3
|
||||
wrapQtAppsHook
|
||||
extra-cmake-modules
|
||||
]
|
||||
++ optional scriptingSupport swig
|
||||
++ optional cudaSupport autoAddDriverRunpath;
|
||||
|
||||
@@ -7,13 +7,13 @@
|
||||
|
||||
buildGoModule (finalAttrs: {
|
||||
pname = "atlantis";
|
||||
version = "0.34.0";
|
||||
version = "0.35.0";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "runatlantis";
|
||||
repo = "atlantis";
|
||||
tag = "v${finalAttrs.version}";
|
||||
hash = "sha256-2xgU3H6X9EcbySV9RXN5oCn+7EkfdwebeYsL5+Vl69E=";
|
||||
hash = "sha256-mdUh/fJo4pA80++nJoYdiAS5oTPpvBsR0TIMHrQO4u8=";
|
||||
};
|
||||
|
||||
ldflags = [
|
||||
@@ -21,7 +21,7 @@ buildGoModule (finalAttrs: {
|
||||
"-X=main.date=1970-01-01T00:00:00Z"
|
||||
];
|
||||
|
||||
vendorHash = "sha256-1xII3GIQQCku3UzwPJnJu//zAJGuGCOSETR6sU4lPR8=";
|
||||
vendorHash = "sha256-QtAR0vO2K014WlzAriAYg7272tZ1iu72g4a3OBsy6Wo=";
|
||||
|
||||
subPackages = [ "." ];
|
||||
|
||||
|
||||
@@ -52,6 +52,7 @@ let
|
||||
"8.1" = "sha256-5EW9BkG154HQ6TrMyan5EhXiGlSRFPXMMTUasIwuC/U=";
|
||||
"8.2" = "sha256-hRjh9Bf04LVBtS08fWMxrE1iyn6SGBQfNNLuSyQPjes=";
|
||||
"8.3" = "sha256-WWsDPQhu1GXMDe6NhlMuVcwi7wGzRLJcJwxItxFCOiI=";
|
||||
"8.4" = "sha256-tRxQfrFJmyaGRTa5ZWXhSHLx3V6QcBGe0EzKYbOjmG8=";
|
||||
};
|
||||
};
|
||||
"x86_64-darwin" = {
|
||||
@@ -60,6 +61,7 @@ let
|
||||
"8.1" = "sha256-w56HItrNtHA8jj9K5LhGTKFRX5i9UYJpxVwR0eFQe4E=";
|
||||
"8.2" = "sha256-vkEAVyZ6Vs3VjWb3oNrlRz5zAzPbgIngeoDAHZLme3Q=";
|
||||
"8.3" = "sha256-uzobd13RzYGFrXHyFH0Ud9Qg7AWMPAA5dvHCp7R3HrU=";
|
||||
"8.4" = "sha256-PtMXo/NTV8E32b9aWuuxBoHeeFN3vP2ufEo1Ed0w2iI=";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
Generated
+554
-324
File diff suppressed because it is too large
Load Diff
Generated
+4814
-5070
File diff suppressed because it is too large
Load Diff
@@ -34,7 +34,7 @@ rustPlatform.buildRustPackage (finalAttrs: {
|
||||
ln -s ${./package-lock.json} package-lock.json
|
||||
'';
|
||||
|
||||
npmDepsHash = "sha256-6oSm3H6RItHOrBIvP6uvR7sBboBRWFuP3VwU38GMfgQ=";
|
||||
npmDepsHash = "sha256-yYTRoxKnTF9y3RA4fuDlVYxv9d37Fc905TYVc/gPIRw=";
|
||||
|
||||
installPhase = ''
|
||||
runHook preInstall
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
}:
|
||||
|
||||
let
|
||||
version = "0.17.75";
|
||||
version = "0.17.76";
|
||||
in
|
||||
buildGoModule {
|
||||
pname = "gqlgen";
|
||||
@@ -16,10 +16,10 @@ buildGoModule {
|
||||
owner = "99designs";
|
||||
repo = "gqlgen";
|
||||
tag = "v${version}";
|
||||
hash = "sha256-VtpD7UfrypaREUu/uon6OTi3jvSzUaj1Y0yTiUw9u0A=";
|
||||
hash = "sha256-b226pRpO693e48OlzVwSaDlPM5RAivIoX/KHXESVEJI=";
|
||||
};
|
||||
|
||||
vendorHash = "sha256-sOiEgSGxIp4COfSQjDXv5sm/iryOcRK8MUbnvrglpbc=";
|
||||
vendorHash = "sha256-cqNRfKPneq4BxVA+kGAxSalwfeNI/hFxsrOgVhkUbLs=";
|
||||
|
||||
subPackages = [ "." ];
|
||||
|
||||
|
||||
@@ -7,13 +7,13 @@
|
||||
|
||||
buildNpmPackage (finalAttrs: {
|
||||
pname = "hypercore";
|
||||
version = "11.9.1";
|
||||
version = "11.10.0";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "holepunchto";
|
||||
repo = "hypercore";
|
||||
tag = "v${finalAttrs.version}";
|
||||
hash = "sha256-aOF/wsq3m+CBrnZkkheukSmYuujOzRb8nJKp4AhZ3kc=";
|
||||
hash = "sha256-6Z6HbolPa3b4EKjUwNGw7gDAg4ijFadBDwpt3l6GUqo=";
|
||||
};
|
||||
|
||||
npmDepsHash = "sha256-ZJxVmQWKgHyKkuYfGIlANXFcROjI7fibg6mxIhDZowM=";
|
||||
|
||||
@@ -17,13 +17,13 @@
|
||||
|
||||
stdenv.mkDerivation (finalAttrs: {
|
||||
pname = "hyprgraphics";
|
||||
version = "0.1.3";
|
||||
version = "0.1.4";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "hyprwm";
|
||||
repo = "hyprgraphics";
|
||||
tag = "v${finalAttrs.version}";
|
||||
hash = "sha256-prQ5JKopXtzCMX2eT3dXbaVvGmzjMRE2bXStQDdazpM=";
|
||||
hash = "sha256-8u6b5oAdX0rCuoR8wFenajBRmI+mzbpNig6hSCuWUzE=";
|
||||
};
|
||||
|
||||
nativeBuildInputs = [
|
||||
|
||||
@@ -17,13 +17,13 @@
|
||||
|
||||
stdenv.mkDerivation (finalAttrs: {
|
||||
pname = "lua-language-server";
|
||||
version = "3.14.0";
|
||||
version = "3.15.0";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "luals";
|
||||
repo = "lua-language-server";
|
||||
tag = finalAttrs.version;
|
||||
hash = "sha256-+pxDCjBcNYpSGZJpwJhL/PsARNhqdIXRHKj9DQvOyLE=";
|
||||
hash = "sha256-frsq5OA3giLOJ/KPcAqVhme+0CtJuZrS3F4zHN1PnFM=";
|
||||
fetchSubmodules = true;
|
||||
};
|
||||
|
||||
|
||||
@@ -18,6 +18,11 @@ buildNpmPackage rec {
|
||||
|
||||
dontNpmBuild = true;
|
||||
|
||||
# remove broken links to build tools
|
||||
postInstall = ''
|
||||
rm -r $out/lib/node_modules/mapscii/node_modules/.bin
|
||||
'';
|
||||
|
||||
meta = with lib; {
|
||||
description = "MapSCII is a Braille & ASCII world map renderer for your console";
|
||||
homepage = "https://github.com/rastapasta/mapscii";
|
||||
|
||||
@@ -27,18 +27,18 @@
|
||||
|
||||
stdenv.mkDerivation (finalAttrs: {
|
||||
pname = "newsflash";
|
||||
version = "3.3.5";
|
||||
version = "4.0.3";
|
||||
|
||||
src = fetchFromGitLab {
|
||||
owner = "news-flash";
|
||||
repo = "news_flash_gtk";
|
||||
tag = "v.${finalAttrs.version}";
|
||||
hash = "sha256-H2/qKnsByidziUldX5MZBrMyMHfuQ4SN9wXizJUGQ8I=";
|
||||
hash = "sha256-TVQZq+Akb7EFUazAgUqvlwC7htVpUf7Hck8p7vY0o3M=";
|
||||
};
|
||||
|
||||
cargoDeps = rustPlatform.fetchCargoVendor {
|
||||
inherit (finalAttrs) pname version src;
|
||||
hash = "sha256-hyu1sk/VcRLjxUFYiFeTvwlFVYq5crMMg+4Afb34Hvc=";
|
||||
hash = "sha256-fjb/AVvWbSq+Mc+5D7wCncLQ8OPjnTqHMzFFYgmCCjY=";
|
||||
};
|
||||
|
||||
postPatch = ''
|
||||
@@ -56,6 +56,7 @@ stdenv.mkDerivation (finalAttrs: {
|
||||
ninja
|
||||
pkg-config
|
||||
rustc
|
||||
rustPlatform.bindgenHook
|
||||
rustPlatform.cargoSetupHook
|
||||
wrapGAppsHook4
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@ from .html import HTMLRenderer, UnresolvedXrefError
|
||||
from .manual_structure import check_structure, FragmentType, is_include, make_xml_id, TocEntry, TocEntryType, XrefTarget
|
||||
from .md import Converter, Renderer
|
||||
from .redirects import Redirects
|
||||
from .src_error import SrcError
|
||||
|
||||
class BaseConverter(Converter[md.TR], Generic[md.TR]):
|
||||
# per-converter configuration for ns:arg=value arguments to include blocks, following
|
||||
@@ -44,14 +45,18 @@ class BaseConverter(Converter[md.TR], Generic[md.TR]):
|
||||
def _postprocess(self, infile: Path, outfile: Path, tokens: Sequence[Token]) -> None:
|
||||
pass
|
||||
|
||||
def _handle_headings(self, tokens: list[Token], *, on_heading: Callable[[Token,str],None]) -> None:
|
||||
def _handle_headings(self, tokens: list[Token], *, src: str, on_heading: Callable[[Token,str],None]) -> None:
|
||||
# Headings in a globally numbered order
|
||||
# h1 to h6
|
||||
curr_heading_pos: list[int] = []
|
||||
for token in tokens:
|
||||
if token.type == "heading_open":
|
||||
if token.tag not in ["h1", "h2", "h3", "h4", "h5", "h6"]:
|
||||
raise RuntimeError(f"Got invalid heading tag {token.tag} in line {token.map[0] + 1 if token.map else 'NOT FOUND'}. Only h1 to h6 headings are allowed.")
|
||||
raise SrcError(
|
||||
src=src,
|
||||
description=f"Got invalid heading tag {token.tag!r}. Only h1 to h6 headings are allowed.",
|
||||
token=token,
|
||||
)
|
||||
|
||||
idx = int(token.tag[1:]) - 1
|
||||
|
||||
@@ -75,10 +80,10 @@ class BaseConverter(Converter[md.TR], Generic[md.TR]):
|
||||
if "id" not in token.attrs:
|
||||
token.attrs["id"] = f"{auto_id_prefix}-{ident}"
|
||||
|
||||
self._handle_headings(tokens, on_heading=set_token_ident)
|
||||
self._handle_headings(tokens, src=src, on_heading=set_token_ident)
|
||||
|
||||
|
||||
check_structure(self._current_type[-1], tokens)
|
||||
check_structure(src, self._current_type[-1], tokens)
|
||||
for token in tokens:
|
||||
if not is_include(token):
|
||||
continue
|
||||
@@ -89,35 +94,46 @@ class BaseConverter(Converter[md.TR], Generic[md.TR]):
|
||||
typ = directive[0]
|
||||
if typ == 'options':
|
||||
token.type = 'included_options'
|
||||
self._process_include_args(token, args, self.INCLUDE_OPTIONS_ALLOWED_ARGS)
|
||||
self._parse_options(token, args)
|
||||
self._process_include_args(src, token, args, self.INCLUDE_OPTIONS_ALLOWED_ARGS)
|
||||
self._parse_options(src, token, args)
|
||||
else:
|
||||
fragment_type = typ.removesuffix('s')
|
||||
if fragment_type not in get_args(FragmentType):
|
||||
raise RuntimeError(f"unsupported structural include type '{typ}'")
|
||||
raise SrcError(
|
||||
src=src,
|
||||
description=f"unsupported structural include type {typ!r}",
|
||||
token=token,
|
||||
)
|
||||
self._current_type.append(cast(FragmentType, fragment_type))
|
||||
token.type = 'included_' + typ
|
||||
self._process_include_args(token, args, self.INCLUDE_FRAGMENT_ALLOWED_ARGS)
|
||||
self._parse_included_blocks(token, args)
|
||||
self._process_include_args(src, token, args, self.INCLUDE_FRAGMENT_ALLOWED_ARGS)
|
||||
self._parse_included_blocks(src, token, args)
|
||||
self._current_type.pop()
|
||||
return tokens
|
||||
|
||||
def _process_include_args(self, token: Token, args: dict[str, str], allowed: set[str]) -> None:
|
||||
def _process_include_args(self, src: str, token: Token, args: dict[str, str], allowed: set[str]) -> None:
|
||||
ns = self.INCLUDE_ARGS_NS + ":"
|
||||
args = { k[len(ns):]: v for k, v in args.items() if k.startswith(ns) }
|
||||
if unknown := set(args.keys()) - allowed:
|
||||
assert token.map
|
||||
raise RuntimeError(f"unrecognized include argument in line {token.map[0] + 1}", unknown)
|
||||
raise SrcError(
|
||||
src=src,
|
||||
description=f"unrecognized include argument(s): {unknown}",
|
||||
token=token,
|
||||
)
|
||||
token.meta['include-args'] = args
|
||||
|
||||
def _parse_included_blocks(self, token: Token, block_args: dict[str, str]) -> None:
|
||||
def _parse_included_blocks(self, src: str, token: Token, block_args: dict[str, str]) -> None:
|
||||
assert token.map
|
||||
included = token.meta['included'] = []
|
||||
for (lnum, line) in enumerate(token.content.splitlines(), token.map[0] + 2):
|
||||
for (lnum, line) in enumerate(token.content.splitlines(), token.map[0] + 1):
|
||||
line = line.strip()
|
||||
path = self._base_paths[-1].parent / line
|
||||
if path in self._base_paths:
|
||||
raise RuntimeError(f"circular include found in line {lnum}")
|
||||
raise SrcError(
|
||||
src=src,
|
||||
description="circular include found",
|
||||
token=token,
|
||||
)
|
||||
try:
|
||||
self._base_paths.append(path)
|
||||
with open(path, 'r') as f:
|
||||
@@ -130,29 +146,57 @@ class BaseConverter(Converter[md.TR], Generic[md.TR]):
|
||||
included.append((tokens, path))
|
||||
self._base_paths.pop()
|
||||
except Exception as e:
|
||||
raise RuntimeError(f"processing included file {path} from line {lnum}") from e
|
||||
raise SrcError(
|
||||
src=src,
|
||||
description=f"processing included file {path}",
|
||||
token=lnum,
|
||||
) from e
|
||||
|
||||
def _parse_options(self, token: Token, block_args: dict[str, str]) -> None:
|
||||
def _parse_options(self, src: str, token: Token, block_args: dict[str, str]) -> None:
|
||||
assert token.map
|
||||
|
||||
items = {}
|
||||
for (lnum, line) in enumerate(token.content.splitlines(), token.map[0] + 2):
|
||||
for (lnum, line) in enumerate(token.content.splitlines(), token.map[0] + 1):
|
||||
if len(args := line.split(":", 1)) != 2:
|
||||
raise RuntimeError(f"options directive with no argument in line {lnum}")
|
||||
raise SrcError(
|
||||
src=src,
|
||||
description=f"options directive with no argument",
|
||||
tokens={
|
||||
"Directive": lnum,
|
||||
"Block": token,
|
||||
},
|
||||
)
|
||||
(k, v) = (args[0].strip(), args[1].strip())
|
||||
if k in items:
|
||||
raise RuntimeError(f"duplicate options directive {k} in line {lnum}")
|
||||
raise SrcError(
|
||||
src=src,
|
||||
description=f"duplicate options directive {k!r}",
|
||||
tokens={
|
||||
"Directive": lnum,
|
||||
"Block": token,
|
||||
},
|
||||
)
|
||||
items[k] = v
|
||||
|
||||
try:
|
||||
id_prefix = items.pop('id-prefix')
|
||||
varlist_id = items.pop('list-id')
|
||||
source = items.pop('source')
|
||||
except KeyError as e:
|
||||
raise RuntimeError(f"options directive {e} missing in block at line {token.map[0] + 1}")
|
||||
raise SrcError(
|
||||
src=src,
|
||||
description=f"options directive {e} missing",
|
||||
tokens={
|
||||
"Block": token,
|
||||
},
|
||||
) from e
|
||||
|
||||
if items.keys():
|
||||
raise RuntimeError(
|
||||
f"unsupported options directives in block at line {token.map[0] + 1}",
|
||||
" ".join(items.keys()))
|
||||
raise SrcError(
|
||||
src=src,
|
||||
description=f"unsupported options directives: {set(items.keys())}",
|
||||
token=token,
|
||||
)
|
||||
|
||||
try:
|
||||
with open(self._base_paths[-1].parent / source, 'r') as f:
|
||||
@@ -160,7 +204,11 @@ class BaseConverter(Converter[md.TR], Generic[md.TR]):
|
||||
token.meta['list-id'] = varlist_id
|
||||
token.meta['source'] = json.load(f)
|
||||
except Exception as e:
|
||||
raise RuntimeError(f"processing options block in line {token.map[0] + 1}") from e
|
||||
raise SrcError(
|
||||
src=src,
|
||||
description="processing options block",
|
||||
token=token,
|
||||
) from e
|
||||
|
||||
class RendererMixin(Renderer):
|
||||
_toplevel_tag: str
|
||||
@@ -542,14 +590,26 @@ class HTMLConverter(BaseConverter[ManualHTMLRenderer]):
|
||||
continue
|
||||
assert token.map
|
||||
if len(token.meta['included']) == 0:
|
||||
raise RuntimeError(f"redirection target {into} in line {token.map[0] + 1} is empty!")
|
||||
raise SrcError(
|
||||
src=src,
|
||||
description=f"redirection target {into!r} is empty!",
|
||||
token=token,
|
||||
)
|
||||
# we use blender-style //path to denote paths relative to the origin file
|
||||
# (usually index.html). this makes everything a lot easier and clearer.
|
||||
if not into.startswith("//") or '/' in into[2:]:
|
||||
raise RuntimeError("html:into-file must be a relative-to-origin //filename", into)
|
||||
raise SrcError(
|
||||
src=src,
|
||||
description=f"html:into-file must be a relative-to-origin //filename: {into}",
|
||||
token=token,
|
||||
)
|
||||
into = token.meta['include-args']['into-file'] = into[2:]
|
||||
if into in self._redirection_targets:
|
||||
raise RuntimeError(f"redirection target {into} in line {token.map[0] + 1} is already in use")
|
||||
raise SrcError(
|
||||
src=src,
|
||||
description=f"redirection target {into} is already in use",
|
||||
token=token,
|
||||
)
|
||||
self._redirection_targets.add(into)
|
||||
return tokens
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ from typing import cast, get_args, Iterable, Literal, Sequence
|
||||
from markdown_it.token import Token
|
||||
|
||||
from .utils import Freezeable
|
||||
from .src_error import SrcError
|
||||
|
||||
# FragmentType is used to restrict structural include blocks.
|
||||
FragmentType = Literal['preface', 'part', 'chapter', 'section', 'appendix']
|
||||
@@ -21,37 +22,45 @@ def is_include(token: Token) -> bool:
|
||||
|
||||
# toplevel file must contain only the title headings and includes, anything else
|
||||
# would cause strange rendering.
|
||||
def _check_book_structure(tokens: Sequence[Token]) -> None:
|
||||
def _check_book_structure(src: str, tokens: Sequence[Token]) -> None:
|
||||
for token in tokens[6:]:
|
||||
if not is_include(token):
|
||||
assert token.map
|
||||
raise RuntimeError(f"unexpected content in line {token.map[0] + 1}, "
|
||||
"expected structural include")
|
||||
raise SrcError(
|
||||
src=src,
|
||||
description=f"unexpected content; expected structural include",
|
||||
token=token,
|
||||
)
|
||||
|
||||
# much like books, parts may not contain headings other than their title heading.
|
||||
# this is a limitation of the current renderers and TOC generators that do not handle
|
||||
# this case well even though it is supported in docbook (and probably supportable
|
||||
# anywhere else).
|
||||
def _check_part_structure(tokens: Sequence[Token]) -> None:
|
||||
_check_fragment_structure(tokens)
|
||||
def _check_part_structure(src: str,tokens: Sequence[Token]) -> None:
|
||||
_check_fragment_structure(src, tokens)
|
||||
for token in tokens[3:]:
|
||||
if token.type == 'heading_open':
|
||||
assert token.map
|
||||
raise RuntimeError(f"unexpected heading in line {token.map[0] + 1}")
|
||||
raise SrcError(
|
||||
src=src,
|
||||
description="unexpected heading",
|
||||
token=token,
|
||||
)
|
||||
|
||||
# two include blocks must either be adjacent or separated by a heading, otherwise
|
||||
# we cannot generate a correct TOC (since there'd be nothing to link to between
|
||||
# the two includes).
|
||||
def _check_fragment_structure(tokens: Sequence[Token]) -> None:
|
||||
def _check_fragment_structure(src: str, tokens: Sequence[Token]) -> None:
|
||||
for i, token in enumerate(tokens):
|
||||
if is_include(token) \
|
||||
and i + 1 < len(tokens) \
|
||||
and not (is_include(tokens[i + 1]) or tokens[i + 1].type == 'heading_open'):
|
||||
assert token.map
|
||||
raise RuntimeError(f"unexpected content in line {token.map[0] + 1}, "
|
||||
"expected heading or structural include")
|
||||
raise SrcError(
|
||||
src=src,
|
||||
description="unexpected content; expected heading or structural include",
|
||||
token=token,
|
||||
)
|
||||
|
||||
def check_structure(kind: TocEntryType, tokens: Sequence[Token]) -> None:
|
||||
def check_structure(src: str, kind: TocEntryType, tokens: Sequence[Token]) -> None:
|
||||
wanted = { 'h1': 'title' }
|
||||
wanted |= { 'h2': 'subtitle' } if kind == 'book' else {}
|
||||
for (i, (tag, role)) in enumerate(wanted.items()):
|
||||
@@ -59,17 +68,21 @@ def check_structure(kind: TocEntryType, tokens: Sequence[Token]) -> None:
|
||||
raise RuntimeError(f"missing {role} ({tag}) heading")
|
||||
token = tokens[3 * i]
|
||||
if token.type != 'heading_open' or token.tag != tag:
|
||||
assert token.map
|
||||
raise RuntimeError(f"expected {role} ({tag}) heading in line {token.map[0] + 1}", token)
|
||||
raise SrcError(
|
||||
src=src,
|
||||
description=f"expected {role} ({tag}) heading",
|
||||
token=token,
|
||||
)
|
||||
for t in tokens[3 * len(wanted):]:
|
||||
if t.type != 'heading_open' or not (role := wanted.get(t.tag, '')):
|
||||
continue
|
||||
assert t.map
|
||||
raise RuntimeError(
|
||||
f"only one {role} heading ({t.markup} [text...]) allowed per "
|
||||
f"{kind}, but found a second in line {t.map[0] + 1}. "
|
||||
"please remove all such headings except the first or demote the subsequent headings.",
|
||||
t)
|
||||
raise SrcError(
|
||||
src=src,
|
||||
description=f"only one {role} heading ({t.markup} [text...]) allowed per "
|
||||
f"{kind}, but found a second. "
|
||||
"Please remove all such headings except the first or demote the subsequent headings.",
|
||||
token=t,
|
||||
)
|
||||
|
||||
last_heading_level = 0
|
||||
for token in tokens:
|
||||
@@ -80,22 +93,28 @@ def check_structure(kind: TocEntryType, tokens: Sequence[Token]) -> None:
|
||||
# every other headings needs one too. we need this to build a TOC and to
|
||||
# provide stable links if the manual changes shape.
|
||||
if 'id' not in token.attrs and (kind != 'book' or token.tag != 'h2'):
|
||||
assert token.map
|
||||
raise RuntimeError(f"heading in line {token.map[0] + 1} does not have an id")
|
||||
raise SrcError(
|
||||
src=src,
|
||||
description=f"heading does not have an id",
|
||||
token=token,
|
||||
)
|
||||
|
||||
level = int(token.tag[1:]) # because tag = h1..h6
|
||||
if level > last_heading_level + 1:
|
||||
assert token.map
|
||||
raise RuntimeError(f"heading in line {token.map[0] + 1} skips one or more heading levels, "
|
||||
"which is currently not allowed")
|
||||
raise SrcError(
|
||||
src=src,
|
||||
description=f"heading skips one or more heading levels, "
|
||||
"which is currently not allowed",
|
||||
token=token,
|
||||
)
|
||||
last_heading_level = level
|
||||
|
||||
if kind == 'book':
|
||||
_check_book_structure(tokens)
|
||||
_check_book_structure(src, tokens)
|
||||
elif kind == 'part':
|
||||
_check_part_structure(tokens)
|
||||
_check_part_structure(src, tokens)
|
||||
else:
|
||||
_check_fragment_structure(tokens)
|
||||
_check_fragment_structure(src, tokens)
|
||||
|
||||
@dc.dataclass(frozen=True)
|
||||
class XrefTarget:
|
||||
|
||||
@@ -6,6 +6,7 @@ import dataclasses
|
||||
import re
|
||||
|
||||
from .types import RenderFn
|
||||
from .src_error import SrcError
|
||||
|
||||
import markdown_it
|
||||
from markdown_it.token import Token
|
||||
@@ -446,12 +447,16 @@ def _footnote_ids(md: markdown_it.MarkdownIt) -> None:
|
||||
generate here are derived from the footnote label, making numeric footnote
|
||||
labels invalid.
|
||||
"""
|
||||
def generate_ids(tokens: Sequence[Token]) -> None:
|
||||
def generate_ids(src: str, tokens: Sequence[Token]) -> None:
|
||||
for token in tokens:
|
||||
if token.type == 'footnote_open':
|
||||
if token.meta["label"][:1].isdigit():
|
||||
assert token.map
|
||||
raise RuntimeError(f"invalid footnote label in line {token.map[0] + 1}")
|
||||
raise SrcError(
|
||||
src=src,
|
||||
description="invalid footnote label",
|
||||
token=token,
|
||||
)
|
||||
token.attrs['id'] = token.meta["label"]
|
||||
elif token.type == 'footnote_anchor':
|
||||
token.meta['target'] = f'{token.meta["label"]}.__back.{token.meta["subId"]}'
|
||||
@@ -460,10 +465,10 @@ def _footnote_ids(md: markdown_it.MarkdownIt) -> None:
|
||||
token.meta['target'] = token.meta["label"]
|
||||
elif token.type == 'inline':
|
||||
assert token.children is not None
|
||||
generate_ids(token.children)
|
||||
generate_ids(src, token.children)
|
||||
|
||||
def footnote_ids(state: markdown_it.rules_core.StateCore) -> None:
|
||||
generate_ids(state.tokens)
|
||||
generate_ids(state.src, state.tokens)
|
||||
|
||||
md.core.ruler.after("footnote_tail", "footnote_ids", footnote_ids)
|
||||
|
||||
@@ -537,7 +542,7 @@ def _block_titles(block: str) -> Callable[[markdown_it.MarkdownIt], None]:
|
||||
non-title heading since those would make toc generation extremely complicated.
|
||||
"""
|
||||
def block_titles(state: markdown_it.rules_core.StateCore) -> None:
|
||||
in_example = [False]
|
||||
in_example = [None]
|
||||
for i, token in enumerate(state.tokens):
|
||||
if token.type == open:
|
||||
if state.tokens[i + 1].type == 'heading_open':
|
||||
@@ -545,14 +550,29 @@ def _block_titles(block: str) -> Callable[[markdown_it.MarkdownIt], None]:
|
||||
state.tokens[i + 1].type = title_open
|
||||
state.tokens[i + 3].type = title_close
|
||||
else:
|
||||
assert token.map
|
||||
raise RuntimeError(f"found {block} without title in line {token.map[0] + 1}")
|
||||
in_example.append(True)
|
||||
raise SrcError(
|
||||
src=state.src,
|
||||
description=f"found {block} without title",
|
||||
token=token,
|
||||
)
|
||||
in_example.append(token)
|
||||
elif token.type == close:
|
||||
in_example.pop()
|
||||
elif token.type == 'heading_open' and in_example[-1]:
|
||||
assert token.map
|
||||
raise RuntimeError(f"unexpected non-title heading in {block} in line {token.map[0] + 1}")
|
||||
started_at = in_example[-1]
|
||||
|
||||
block_display = ":::{." + block + "}"
|
||||
|
||||
raise SrcError(
|
||||
description=f"unexpected non-title heading in `{block_display}`; are you missing a `:::`?\n"
|
||||
f"Note: blocks like `{block_display}` are only allowed to contain a single heading in order to simplify TOC generation.",
|
||||
src=state.src,
|
||||
tokens={
|
||||
f"`{block_display}` block": started_at,
|
||||
"Unexpected heading": token,
|
||||
},
|
||||
)
|
||||
|
||||
def do_add(md: markdown_it.MarkdownIt) -> None:
|
||||
md.core.ruler.push(f"{block}_titles", block_titles)
|
||||
|
||||
@@ -0,0 +1,154 @@
|
||||
from typing import Tuple
|
||||
|
||||
from markdown_it.token import Token
|
||||
|
||||
LineSpan = int | Tuple[int, int] | Token
|
||||
|
||||
|
||||
class SrcError(Exception):
|
||||
"""An error associated with a source file and location."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
description: str,
|
||||
src: str,
|
||||
tokens: dict[str, LineSpan] | None = None,
|
||||
token: LineSpan | None = None,
|
||||
):
|
||||
"""Create a new `SrcError`.
|
||||
|
||||
Arguments:
|
||||
- `description`: A description of the error.
|
||||
|
||||
- `src`: The source text the `token`s are from.
|
||||
|
||||
- `tokens`: A dictionary from descriptions to `Tokens` (or lines) associated with
|
||||
the error.
|
||||
|
||||
The tokens are used for their source location.
|
||||
|
||||
A location like ` at lines 6-9` will be added to the description.
|
||||
|
||||
If the description is empty, the location will be described as `At
|
||||
lines 6-9`.
|
||||
|
||||
- `token`: Shorthand for `tokens={"": token}`.
|
||||
"""
|
||||
self.src = src
|
||||
|
||||
tokens = tokens or {}
|
||||
if token:
|
||||
tokens[""] = token
|
||||
self.tokens = tokens
|
||||
|
||||
self.description = description
|
||||
|
||||
self.message = _src_error_str(src=src, tokens=tokens, description=description)
|
||||
|
||||
super().__init__(self.message)
|
||||
|
||||
def __str__(self) -> str:
|
||||
return self.message
|
||||
|
||||
|
||||
def _get_line_span(location: LineSpan) -> Tuple[int, int] | None:
|
||||
if isinstance(location, Token):
|
||||
if location.map:
|
||||
return (location.map[0], location.map[1])
|
||||
else:
|
||||
return None
|
||||
elif isinstance(location, int):
|
||||
return (location, location + 1)
|
||||
else:
|
||||
return location
|
||||
|
||||
|
||||
def _src_error_str(*, src: str, tokens: dict[str, LineSpan], description: str) -> str:
|
||||
"""Python exceptions are a bit goofy and need a `message` string attribute
|
||||
right away, so we basically need a way to generate the string before we
|
||||
actually finish `__init__`.
|
||||
"""
|
||||
|
||||
result = [description]
|
||||
|
||||
src_lines = src.splitlines()
|
||||
|
||||
for description, token in tokens.items():
|
||||
result.append("\n\n\x1b[33m")
|
||||
|
||||
if description:
|
||||
result.append(description)
|
||||
result.append(" at ")
|
||||
else:
|
||||
result.append("At ")
|
||||
|
||||
maybe_span = _get_line_span(token)
|
||||
|
||||
if not maybe_span:
|
||||
result.append("unknown location\x1b[0m")
|
||||
continue
|
||||
|
||||
start, end = maybe_span
|
||||
# Note: `end` is exclusive, so single-line spans are represented as
|
||||
# `(n, n+1)`.
|
||||
if start == end - 1:
|
||||
result.append("line ")
|
||||
result.append(str(start + 1))
|
||||
else:
|
||||
result.append("lines ")
|
||||
result.append(str(start + 1))
|
||||
result.append("-")
|
||||
result.append(str(end))
|
||||
|
||||
result.append(":\x1b[0m\n")
|
||||
|
||||
result.append(src_excerpt(src_lines=src_lines, start=start, end=end))
|
||||
|
||||
return "".join(result)
|
||||
|
||||
|
||||
def src_excerpt(
|
||||
*, src_lines: list[str], start: int, end: int, context: int = 3, max_lines: int = 20
|
||||
) -> str:
|
||||
output = []
|
||||
|
||||
def clamp_line(line_num: int) -> int:
|
||||
return max(0, min(len(src_lines), line_num))
|
||||
|
||||
def add_line(line_num: int, *, is_context: bool) -> None:
|
||||
# Lines start with the line number, dimmed.
|
||||
prefix = "\x1b[2m\x1b[37m" + format(line_num + 1, " 4d") + "\x1b[0m"
|
||||
|
||||
# Context lines are prefixed with a dotted line, non-context lines are
|
||||
# prefixed with a bold yellow line.
|
||||
if is_context:
|
||||
# Note: No reset here because context lines are dimmed.
|
||||
prefix += " \x1b[2m\x1b[37m┆ "
|
||||
else:
|
||||
prefix += " \x1b[1m\x1b[33m┃\x1b[0m "
|
||||
|
||||
output.append(prefix + src_lines[line_num] + "\x1b[0m")
|
||||
|
||||
def add_lines(start: int, end: int, is_context: bool) -> None:
|
||||
for i in range(clamp_line(start), clamp_line(end)):
|
||||
add_line(i, is_context=is_context)
|
||||
|
||||
if end - start > max_lines:
|
||||
# If we have more than `max_lines` in the range, show a `...` in the middle.
|
||||
half_max_lines = max_lines // 2
|
||||
|
||||
add_lines(start - context, start, is_context=True)
|
||||
add_lines(start, start + half_max_lines, is_context=False)
|
||||
|
||||
output.append(" \x1b[2m\x1b[37m...\x1b[0m")
|
||||
|
||||
add_lines(end - half_max_lines, end, is_context=False)
|
||||
add_lines(end, end + context, is_context=True)
|
||||
|
||||
else:
|
||||
add_lines(start - context, start, is_context=True)
|
||||
add_lines(start, end, is_context=False)
|
||||
add_lines(end, end + context, is_context=True)
|
||||
|
||||
return "\n".join(output)
|
||||
@@ -3,7 +3,6 @@ from pathlib import Path
|
||||
from markdown_it.token import Token
|
||||
from nixos_render_docs.manual import HTMLConverter, HTMLParameters
|
||||
from nixos_render_docs.md import Converter
|
||||
from nixos_render_docs.redirects import Redirects
|
||||
|
||||
auto_id_prefix="TEST_PREFIX"
|
||||
def set_prefix(token: Token, ident: str) -> None:
|
||||
@@ -19,7 +18,7 @@ def test_auto_id_prefix_simple() -> None:
|
||||
## subtitle
|
||||
"""
|
||||
tokens = Converter()._parse(src)
|
||||
md._handle_headings(tokens, on_heading=set_prefix)
|
||||
md._handle_headings(tokens, src=src, on_heading=set_prefix)
|
||||
|
||||
assert [
|
||||
{**token.attrs, "tag": token.tag}
|
||||
@@ -44,7 +43,7 @@ def test_auto_id_prefix_repeated() -> None:
|
||||
## subtitle2
|
||||
"""
|
||||
tokens = Converter()._parse(src)
|
||||
md._handle_headings(tokens, on_heading=set_prefix)
|
||||
md._handle_headings(tokens, src=src, on_heading=set_prefix)
|
||||
|
||||
assert [
|
||||
{**token.attrs, "tag": token.tag}
|
||||
@@ -76,7 +75,7 @@ def test_auto_id_prefix_maximum_nested() -> None:
|
||||
## h2.2
|
||||
"""
|
||||
tokens = Converter()._parse(src)
|
||||
md._handle_headings(tokens, on_heading=set_prefix)
|
||||
md._handle_headings(tokens, src=src, on_heading=set_prefix)
|
||||
|
||||
assert [
|
||||
{**token.attrs, "tag": token.tag}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import nixos_render_docs
|
||||
from nixos_render_docs.options import AnchorStyle
|
||||
|
||||
import json
|
||||
from markdown_it.token import Token
|
||||
from pathlib import Path
|
||||
import pytest
|
||||
from markdown_it.token import Token
|
||||
|
||||
import nixos_render_docs
|
||||
from nixos_render_docs.options import AnchorStyle
|
||||
|
||||
def test_option_headings() -> None:
|
||||
c = nixos_render_docs.options.HTMLConverter({}, 'local', 'vars', 'opt-', {})
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
import nixos_render_docs as nrd
|
||||
import pytest
|
||||
import textwrap
|
||||
|
||||
import pytest
|
||||
from markdown_it.token import Token
|
||||
|
||||
import nixos_render_docs as nrd
|
||||
from nixos_render_docs.src_error import SrcError
|
||||
|
||||
class Converter(nrd.md.Converter[nrd.html.HTMLRenderer]):
|
||||
# actual renderer doesn't matter, we're just parsing.
|
||||
def __init__(self, manpage_urls: dict[str, str]) -> None:
|
||||
@@ -498,9 +501,27 @@ def test_example() -> None:
|
||||
Token(type='paragraph_close', tag='p', nesting=-1, block=True)
|
||||
]
|
||||
|
||||
with pytest.raises(RuntimeError) as exc:
|
||||
with pytest.raises(SrcError) as exc:
|
||||
c._parse("::: {.example}\n### foo\n### bar\n:::")
|
||||
assert exc.value.args[0] == 'unexpected non-title heading in example in line 3'
|
||||
|
||||
assert str(exc.value) == textwrap.dedent(
|
||||
"""
|
||||
unexpected non-title heading in `:::{.example}`; are you missing a `:::`?
|
||||
Note: blocks like `:::{.example}` are only allowed to contain a single heading in order to simplify TOC generation.
|
||||
|
||||
\x1b[33m`:::{.example}` block at lines 1-3:\x1b[0m
|
||||
\x1b[2m\x1b[37m 1\x1b[0m \x1b[1m\x1b[33m┃\x1b[0m ::: {.example}\x1b[0m
|
||||
\x1b[2m\x1b[37m 2\x1b[0m \x1b[1m\x1b[33m┃\x1b[0m ### foo\x1b[0m
|
||||
\x1b[2m\x1b[37m 3\x1b[0m \x1b[1m\x1b[33m┃\x1b[0m ### bar\x1b[0m
|
||||
\x1b[2m\x1b[37m 4\x1b[0m \x1b[2m\x1b[37m┆ :::\x1b[0m
|
||||
|
||||
\x1b[33mUnexpected heading at line 3:\x1b[0m
|
||||
\x1b[2m\x1b[37m 1\x1b[0m \x1b[2m\x1b[37m┆ ::: {.example}\x1b[0m
|
||||
\x1b[2m\x1b[37m 2\x1b[0m \x1b[2m\x1b[37m┆ ### foo\x1b[0m
|
||||
\x1b[2m\x1b[37m 3\x1b[0m \x1b[1m\x1b[33m┃\x1b[0m ### bar\x1b[0m
|
||||
\x1b[2m\x1b[37m 4\x1b[0m \x1b[2m\x1b[37m┆ :::\x1b[0m
|
||||
"""
|
||||
).strip()
|
||||
|
||||
def test_footnotes() -> None:
|
||||
c = Converter({})
|
||||
|
||||
@@ -16,17 +16,17 @@ let
|
||||
in
|
||||
rustPlatform.buildRustPackage rec {
|
||||
pname = "onefetch";
|
||||
version = "2.24.0";
|
||||
version = "2.25.0";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "o2sh";
|
||||
repo = "onefetch";
|
||||
rev = version;
|
||||
hash = "sha256-Q74iqCSH8sdGFWC5DmMZhvUoL/Hzz4XNj548Gls6Hzk=";
|
||||
hash = "sha256-ZaaSuHWkhJx0q1CBAiRhwoLeeyyoAj6/vP3AJwybjAo=";
|
||||
};
|
||||
|
||||
useFetchCargoVendor = true;
|
||||
cargoHash = "sha256-BpWc1GEj94vGEXDJEyocItggP1vQC441wp8r3DwalFw=";
|
||||
cargoHash = "sha256-56Net4nNRndePhdsQPbmqiPHpOUGMmnQt6BuplQpvSU=";
|
||||
|
||||
cargoPatches = [
|
||||
# enable pkg-config feature of zstd
|
||||
|
||||
@@ -3,20 +3,26 @@
|
||||
buildNpmPackage,
|
||||
fetchFromGitHub,
|
||||
nix-update-script,
|
||||
npm-lockfile-fix,
|
||||
}:
|
||||
|
||||
buildNpmPackage rec {
|
||||
pname = "opencommit";
|
||||
version = "3.2.7";
|
||||
version = "3.2.9";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "di-sukharev";
|
||||
repo = "opencommit";
|
||||
rev = "v${version}";
|
||||
hash = "sha256-vmVOrNwUsgB3iBvO8QhpJfI2OO0Kb9ZthcAXVaQ2cBM=";
|
||||
hash = "sha256-nn+Whjs3qLXhydrELXzogr66H6btY/TPbmWT/MH6w+M=";
|
||||
postFetch = ''
|
||||
cd $out
|
||||
# Fix lockfile issues with bundled dependencies
|
||||
${lib.getExe npm-lockfile-fix} package-lock.json
|
||||
'';
|
||||
};
|
||||
|
||||
npmDepsHash = "sha256-F19xbiZoIC2JA+3rLqJBbFZvs2XbAk94F2borp/7gMo=";
|
||||
npmDepsHash = "sha256-1lUMtQFGlM1Z2oQ4nktsePyce/EwAu75BbkBiqBrdnQ=";
|
||||
|
||||
passthru.updateScript = nix-update-script { };
|
||||
|
||||
|
||||
@@ -9,13 +9,13 @@
|
||||
|
||||
stdenvNoCC.mkDerivation (finalAttrs: {
|
||||
pname = "sketchybar-app-font";
|
||||
version = "2.0.35";
|
||||
version = "2.0.39";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "kvndrsslr";
|
||||
repo = "sketchybar-app-font";
|
||||
rev = "v2.0.35";
|
||||
hash = "sha256-qXXxpx/thEJuFnNUWmMXYMoir5CGqCktV1emzVPcTIY=";
|
||||
rev = "v2.0.39";
|
||||
hash = "sha256-TTkw/LhRnqJYBn6Mt+T3qgyLHhLIyACdUoShq/mIONY=";
|
||||
};
|
||||
|
||||
pnpmDeps = pnpm_9.fetchDeps {
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
{
|
||||
lib,
|
||||
stdenv,
|
||||
rustPlatform,
|
||||
fetchFromGitHub,
|
||||
installShellFiles,
|
||||
versionCheckHook,
|
||||
nix-update-script,
|
||||
}:
|
||||
|
||||
rustPlatform.buildRustPackage (finalAttrs: {
|
||||
pname = "somo";
|
||||
version = "1.1.0";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "theopfr";
|
||||
repo = "somo";
|
||||
tag = "v${finalAttrs.version}";
|
||||
hash = "sha256-HUTaBSy3FemAQH1aKZYTJnUWiq0bU/H6c5Gz3yamPiA=";
|
||||
};
|
||||
|
||||
cargoHash = "sha256-e3NrEfbWz6h9q4TJnn8jnRmMJbeaEc4Yo3hFlaRLzzQ=";
|
||||
|
||||
nativeBuildInputs =
|
||||
[
|
||||
installShellFiles
|
||||
]
|
||||
++ lib.optionals stdenv.hostPlatform.isDarwin [
|
||||
# Avoids "couldn't find any valid shared libraries matching: ['libclang.dylib']" error on darwin in sandbox mode.
|
||||
rustPlatform.bindgenHook
|
||||
];
|
||||
|
||||
postInstall = lib.optionalString (stdenv.buildPlatform.canExecute stdenv.hostPlatform) ''
|
||||
installShellCompletion --cmd somo \
|
||||
--bash <("$out/bin/somo" generate-completions bash) \
|
||||
--zsh <("$out/bin/somo" generate-completions zsh) \
|
||||
--fish <("$out/bin/somo" generate-completions fish)
|
||||
'';
|
||||
|
||||
nativeInstallCheckInputs = [
|
||||
versionCheckHook
|
||||
];
|
||||
doInstallCheck = true;
|
||||
versionCheckProgramArg = "--version";
|
||||
|
||||
passthru = {
|
||||
updateScript = nix-update-script { };
|
||||
};
|
||||
|
||||
meta = {
|
||||
description = "Socket and port monitoring tool";
|
||||
homepage = "https://github.com/theopfr/somo";
|
||||
changelog = "https://github.com/theopfr/somo/blob/v${finalAttrs.version}/CHANGELOG.md";
|
||||
license = lib.licenses.mit;
|
||||
platforms = with lib.platforms; linux ++ darwin;
|
||||
maintainers = with lib.maintainers; [
|
||||
kachick
|
||||
];
|
||||
mainProgram = "somo";
|
||||
};
|
||||
})
|
||||
@@ -9,11 +9,11 @@
|
||||
|
||||
stdenv.mkDerivation (finalAttrs: {
|
||||
pname = "tcsh";
|
||||
version = "6.24.15";
|
||||
version = "6.24.16";
|
||||
|
||||
src = fetchurl {
|
||||
url = "mirror://tcsh/tcsh-${finalAttrs.version}.tar.gz";
|
||||
hash = "sha256-1NCypN8yD1elGORMNZ7za7z4XWT1FG0MuP80mE4NI/0=";
|
||||
hash = "sha256-QgjPRjD7ZNkdgZh/hU+VcKWg6KABqSgn3vN9Dtjzc2Q=";
|
||||
};
|
||||
|
||||
strictDeps = true;
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
|
||||
stdenv.mkDerivation {
|
||||
pname = "wlvncc";
|
||||
version = "0-unstable-2025-04-21";
|
||||
version = "0-unstable-2025-04-20";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "any1";
|
||||
|
||||
@@ -10,13 +10,13 @@
|
||||
|
||||
buildPythonPackage rec {
|
||||
pname = "pyside6-fluent-widgets";
|
||||
version = "1.8.2";
|
||||
version = "1.8.3";
|
||||
pyproject = true;
|
||||
|
||||
src = fetchPypi {
|
||||
pname = "pyside6_fluent_widgets";
|
||||
inherit version;
|
||||
hash = "sha256-FspFnfu4f3PS2ARTOqaH7NCKMpg9r4YTj5LYsHyduBI=";
|
||||
hash = "sha256-A9lKRFGpfrWKGAKJS9ETIbSTBF/Ba6KUBBc4Pht2eBE=";
|
||||
};
|
||||
|
||||
build-system = [ setuptools ];
|
||||
|
||||
@@ -8,13 +8,13 @@
|
||||
|
||||
buildPythonPackage rec {
|
||||
pname = "weblate-language-data";
|
||||
version = "2025.7";
|
||||
version = "2025.8";
|
||||
pyproject = true;
|
||||
|
||||
src = fetchPypi {
|
||||
pname = "weblate_language_data";
|
||||
inherit version;
|
||||
hash = "sha256-eDefK2g4EwJJttFHCNurOYifC2OXQXjRcqRT36nfLOc=";
|
||||
hash = "sha256-buZNp7iWF7Ppx5RcTRs2kawwmzCPmwXSqarRbmgP0i8=";
|
||||
};
|
||||
|
||||
build-system = [ setuptools ];
|
||||
|
||||
@@ -629,6 +629,12 @@ in
|
||||
'';
|
||||
};
|
||||
|
||||
hiredis-client = attrs: {
|
||||
buildInputs = [
|
||||
openssl
|
||||
];
|
||||
};
|
||||
|
||||
hpricot = attrs: {
|
||||
dontBuild = false;
|
||||
patches = [
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -33,7 +33,7 @@ stdenv.mkDerivation rec {
|
||||
gemdir = src;
|
||||
};
|
||||
|
||||
mastodonModules = stdenv.mkDerivation {
|
||||
mastodonModules = stdenv.mkDerivation (finalAttrs: {
|
||||
pname = "${pname}-modules";
|
||||
inherit src version;
|
||||
|
||||
@@ -80,8 +80,9 @@ stdenv.mkDerivation rec {
|
||||
find public/assets -type f -regextype posix-extended -iregex '.*\.(css|html|js|json|svg)' \
|
||||
-exec gzip --best --keep --force {} ';' \
|
||||
-exec brotli --best --keep {} ';'
|
||||
gzip --best --keep public/packs/report.html
|
||||
brotli --best --keep public/packs/report.html
|
||||
|
||||
gzip --best --keep public/packs/sw.js
|
||||
brotli --best --keep public/packs/sw.js
|
||||
|
||||
runHook postBuild
|
||||
'';
|
||||
@@ -96,7 +97,7 @@ stdenv.mkDerivation rec {
|
||||
|
||||
runHook postInstall
|
||||
'';
|
||||
};
|
||||
});
|
||||
|
||||
propagatedBuildInputs = [ mastodonGems.wrappedRuby ];
|
||||
nativeBuildInputs = [ brotli ];
|
||||
@@ -135,8 +136,6 @@ stdenv.mkDerivation rec {
|
||||
ln -s assets/500.html.br public/500.html.br
|
||||
ln -s packs/sw.js.gz public/sw.js.gz
|
||||
ln -s packs/sw.js.br public/sw.js.br
|
||||
ln -s packs/sw.js.map.gz public/sw.js.map.gz
|
||||
ln -s packs/sw.js.map.br public/sw.js.map.br
|
||||
|
||||
rm -rf log
|
||||
ln -s /var/log/mastodon log
|
||||
|
||||
+842
-731
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,75 @@
|
||||
{
|
||||
"@esbuild/aix-ppc64@npm:0.25.5": "fb872b34a2843293dc60e809968fedf93e0d8f7174b062decffae6ba861eb56aaea0cd0aba87ba99162ceb2a690f0cde4fc29c000b52c035e40c91ec7861d43e",
|
||||
"@esbuild/android-arm64@npm:0.25.5": "c818e799b19b5587466bf68a27b578ccaaf866c1d144573fbde7659e3fd3f555422ec3e67f5bd186a87648957d1b6e74df4f847edea7219c16979c9916f36e91",
|
||||
"@esbuild/android-arm@npm:0.25.5": "a5384933f9f2ffcadce2be49da6ff43249fe42f32a04071316434e9f633fc20c8d4029072e9a53555620c3531045786297607b852579eee30b6dbc3bc9d98cd9",
|
||||
"@esbuild/android-x64@npm:0.25.5": "8ce115dc7e1e6735f23b4aadb2dfca29c0abd8577ce34802ea3d017a64e388928949134fe225dfe190babdc5ec01be5fc7794eca84738cdefc12c5e3789ce43b",
|
||||
"@esbuild/darwin-arm64@npm:0.25.5": "a009eab62f2bd284a6f2001d5e08217059186ffc16907bbe873e1de40fe9b5ed92c0db2f4c4d0dc41545838850a430c8f2f35d7bdb9cd01a1a04293acd97afca",
|
||||
"@esbuild/darwin-x64@npm:0.25.5": "cac8021a7a0c549263e076913346b35a5bb81f76ffbc1abfad5e7b67303f013ac0c76f111bf624ea8447b327ec86c18a60c6ff307d743a2269f5d47313f5b2de",
|
||||
"@esbuild/freebsd-arm64@npm:0.25.5": "d248e7103b7094eb4288db7c9a78b2905a25b4a957f2b945531ca88d3394f45ceca2343a7c84954734534af6159bc741eb3d5c1ed9df990f7395337a1b14192c",
|
||||
"@esbuild/freebsd-x64@npm:0.25.5": "8a7be0740f07f5dbb3e24bf782ca6ef518a8ce9b53e5d864221722045713586d41774cbd531df97dc868b291b3b303c12e50ca8611c3cb7b5fe09a30b38285eb",
|
||||
"@esbuild/linux-arm64@npm:0.25.5": "ce3c8fca47cf0a92148fb288eb35a5c4a4dcf7a700730b3a48fdd63c13e17c719eb6b350378203fba773477eb5be637f47a6d52c5d4ce5bdc0075ee917156006",
|
||||
"@esbuild/linux-arm@npm:0.25.5": "cc81ea76ab86ed2a837c9da329f7c63412d288dc0aa608c8dcdf51705dc93d5b7f966a429be4896babe611074e5898c7e6c8e07ad7f50123a05478975294fbb4",
|
||||
"@esbuild/linux-ia32@npm:0.25.5": "bfed6750923afd56148f658f6ec8995479f5115116dc212ecb9e4c556064422e22eda855177e7c02cbc945494e4db1167101918c5fa932278115db2c7025a3f6",
|
||||
"@esbuild/linux-loong64@npm:0.25.5": "e5c20140bbbdba53f0d86dd72961ed73e6255d2ada2d3a626f390b352170605644822ad7592f695b6e520edcefe0c5f6ba19d10694b5d11d725745d9792bde01",
|
||||
"@esbuild/linux-mips64el@npm:0.25.5": "6b3559517efd0dd1301debc7af7e275b055859c26facdda2e229b1aaab6ebea4c480a1da151c46211ee4035d95bfa7f0cdacf735b57ee99d41b69c77357310b9",
|
||||
"@esbuild/linux-ppc64@npm:0.25.5": "a1a1af99d758efce928335637924dcd8ddec4201af51014e1f831b012d53a0a673b1e0c31036ec9e8c5a0311439283419ec8abdfc67ecb245fa7f7b653006ed0",
|
||||
"@esbuild/linux-riscv64@npm:0.25.5": "6cd8dce6723b73e0f89898ab6cd52e0d009afdacdfc0d5529134de7b832c92c2e0421fbb5cbfc0e0c0b2b00a9b1ff2c4cdb9695b2c535ebc174960e986c727a7",
|
||||
"@esbuild/linux-s390x@npm:0.25.5": "31b86dbc93d19eb362bad3353e65d6da771118346e723582d06c05f1b6ffad1c3765001b5215ef1e8f0c2bb29130d98815359bbc88e5c08304354d5a92e6ea94",
|
||||
"@esbuild/linux-x64@npm:0.25.5": "f878a3e40edfd8a50de94bf982a9eaf03e636a0332af163a6c905490063aae652384fb392d4765c4338fb6f991034949c92ec768ee65c3b2fceeb494b89fe8b3",
|
||||
"@esbuild/netbsd-arm64@npm:0.25.5": "941c5e28a63a93f19122271b5490e196db12815702c2266c6d66401b6909a4364ab889611ba81c5359624e3ce61f0505a680a1179ed9a555d1415fa1c485d75d",
|
||||
"@esbuild/netbsd-x64@npm:0.25.5": "edbefdd88ca24a373497a7c8d1fdab418827ff89c6eee1c574159dbb4d9174552aa87753f35525a894964b77c14b012164ec5582b9f19dd4d6c1f5d45df411c7",
|
||||
"@esbuild/openbsd-arm64@npm:0.25.5": "d44633a374c109d2fb9c678882016e3ec3d79f0c5f21a6e6fb0114ea709bc539200b037a4e3ec52304eea2f8c5957bf16c6f0a7af5cfde41b652c4bac604bba6",
|
||||
"@esbuild/openbsd-x64@npm:0.25.5": "efc4641ea653dedc9886f0603c2e7cfc6fbe94c34d4cdaee9b060a8b9d8143d1192c45da93b3e802af2c26f72ab1ad3a3fad0e0cb297d06de55814fe83ccd32c",
|
||||
"@esbuild/sunos-x64@npm:0.25.5": "29860663381b6098c0fda6f69235407654dfad953e83b3f9f06a270950d5c37da4ca60a4b5915b8e2606d468b560be6179870f64a22d5b046e8a930c31a7b554",
|
||||
"@esbuild/win32-arm64@npm:0.25.5": "a77d395251c8a62ab0cec07d5230222823fa02fbf3ef008d94b5213a335c9f949872c3f1c2f947abaa28098b669018e429af42f59616e049860a0072f3b006de",
|
||||
"@esbuild/win32-ia32@npm:0.25.5": "ff1b6cbe835082aef5b93c3e2012d51be431d05c6ae5f90a5bc89687c687e8e2340c262dedddd124b27b511616bbc4088b5a4a949d3147f677084dc6ec572629",
|
||||
"@esbuild/win32-x64@npm:0.25.5": "266e69e8d37bd4deb77443588e49472e4e9791178cb39e1692eabb67cf65d8e85a932ac468e7ebb2072c8a9ee23ad413c8f0f7d954c474f643cedbbf7aad952a",
|
||||
"@parcel/watcher-android-arm64@npm:2.5.0": "2d5d66f4e904546cff638d0b27a871d695dda1205e32902f917723dc1b09a5edef4ed8064fc5c85192a4e5e5b531eb4a2d3b349015ff6170c8228e3c098d5376",
|
||||
"@parcel/watcher-darwin-arm64@npm:2.5.0": "bbdbaeb31ccea5ec172adab2bb2b1a5f4b2e18ed31054d7f6b1db718238f5880e3b8bc8ac1b55c00048c7a1973e75c0c86fa04c02679f99c0bb355145c8b685b",
|
||||
"@parcel/watcher-darwin-x64@npm:2.5.0": "85089bf1c0f7fb0b4007d54f97e890bf2173d1a11166e9e601b9afe6e260e9cff2eed150ea80f51aae358436376c36af75a70523f53711f16a773987422cf93b",
|
||||
"@parcel/watcher-freebsd-x64@npm:2.5.0": "1355a42a68beb177f9d15b8e379b63dd2e633494e0f09a7e28a778c6a5eb082206d6690e3776e79da5263ecc8791be047c33943cfd2d09019f8f545800ed583b",
|
||||
"@parcel/watcher-linux-arm-glibc@npm:2.5.0": "3c78f9ab9e9d52745f3d44200e290a64843a9346bbe6628485cc6d777a1d329fd0345a5c919daad05fb436fda59143ec2f1810789c8e594a51c7f5d8099ac682",
|
||||
"@parcel/watcher-linux-arm-musl@npm:2.5.0": "80f7f97115e4d98d95735149c6b210ed1902dbf0020d20b245801272a1459f3cef75307c124c1a947450dff9d7d62440ad85e46a98e06523523170fdffab5bf1",
|
||||
"@parcel/watcher-linux-arm64-glibc@npm:2.5.0": "f82fb66b301754f9bf67c7abfe41b18c987ed47f8de05750395ac7453a2c396104d44090b20450d90d5af3e9de54e06aed1520e8401343b824f3c19747cf0aa1",
|
||||
"@parcel/watcher-linux-arm64-musl@npm:2.5.0": "914ebc3387884a8948594fa91520726ef9a7dfbbf7663fd00e7c0de13e08a4e7a525c9132b5439b64b9deb9b62fdfb8c5e02148013cd2383d171334ea76641c0",
|
||||
"@parcel/watcher-linux-x64-glibc@npm:2.5.0": "5db33f6a134d20e8bfd8bed6d13107e7d30947e832a4f677136abee8e1c2855ea19629ccf220e95056dbff753b55fe2b698dd936f31e492b095cc6434451e9d4",
|
||||
"@parcel/watcher-linux-x64-musl@npm:2.5.0": "dbf3f903c4eb6014660f4c3c0d44dcef0e21ee16908288ad0149d6c1a5c9fd7f0405d8d0e91a2493fbeef83df5784bd43f7d1426a0150e00a415b6c0eab38c98",
|
||||
"@parcel/watcher-win32-arm64@npm:2.5.0": "cff6516b1dad597ca1ec8c385cf8251f5050b32ab46fc15360f2eff3a40b61b7107eee56df73764007d9bd6b826960d2f3589c8e0ce270bb5b2a292313bd7a1b",
|
||||
"@parcel/watcher-win32-ia32@npm:2.5.0": "ad9d2c9ae3a7031105fc90418050a910d4b679ead36e5fdcbb1b3e4afbaf56aec6566863e3a374c645c82f57073d8f643183f19c67c8c48b0aa62224c05fdb9d",
|
||||
"@parcel/watcher-win32-x64@npm:2.5.0": "aa9660bdb2fe70de5163f9f8419e263711fd30612244fb7feb58fce49a653b88ac0e1e29646fb1fc76b86fd8215e62eea5ded0616725987dfca5372041925bd2",
|
||||
"@rollup/rollup-android-arm-eabi@npm:4.40.2": "cb502d6933de94860f9d49a4b4e849a206d10d9b1a424847cb2545667f8937ac891a37854e2934992b39521dc8b8daa2ec6b683da6bb47ef893ab24f9424c887",
|
||||
"@rollup/rollup-android-arm64@npm:4.40.2": "42e04ae6605f8a31cc7daf484f9104e6d2174a99e39d829c24d77780cd257a6dab67f5c6a38e84e5a967ad4a64a042f1e6dfbe75444aa03517e83d8436179726",
|
||||
"@rollup/rollup-darwin-arm64@npm:4.40.2": "8e641fd8a888504c516e76e525a7fcc099d363a82ce8569a1a5bb2fdcf632fa262e1a73b47932a922d132e0c46fab6ba04490053f63e6e4fb30c313a499b139f",
|
||||
"@rollup/rollup-darwin-x64@npm:4.40.2": "9dca62986fa2afef8c5addcb1eb4ee08afbd3aa03ece3c5372a82a785af67ae441b9782dd542018fa5bb39a6de34ea53f10795d6f6f801a0469ce7979c52c729",
|
||||
"@rollup/rollup-freebsd-arm64@npm:4.40.2": "f21c73712c4cb74a797998e8adfa83bb7ff0d6cc3e7353eae5b213b4bb3f9f481e025d37dd67aeee7488b9fc9ecd0bc8f85a61469cfa6592ed9292d14ba868d0",
|
||||
"@rollup/rollup-freebsd-x64@npm:4.40.2": "9f8b6abb5be2527e6cffdaf0dd95a8bbb6f4aa5599be2bfe919e8252f57558f0a06b66748d29cb1e42d0b65e1d2ef0ec2d6a429d3c8a1a85352269d88ffbda17",
|
||||
"@rollup/rollup-linux-arm-gnueabihf@npm:4.40.2": "fc205b61c54ddaac7bb45768c3b4bbd79632df3f7bbe65532f5453d54e1a31c1d3f1e4508a00323cf0656d6c5a69f0793989d11fd0805dc2621053c8c6fbcaa3",
|
||||
"@rollup/rollup-linux-arm-musleabihf@npm:4.40.2": "14fde6bac72d734462b9c2fa3594934454069d01422fe12e650ae6fc9e998daac3d43d1726a0aa040cac9d4de43cf75ca34d82932e0a2c3f564f49f0b6fba4af",
|
||||
"@rollup/rollup-linux-arm64-gnu@npm:4.40.2": "1a7c361022d74025076d322cdeb741923f1d3e0d5e1a12fd4dcc678a7c3dc8a07002f6ec4d537b6f089c75b90273cd700580b9ac1b1d45fa68908eadb524f1c7",
|
||||
"@rollup/rollup-linux-arm64-musl@npm:4.40.2": "2fbf7f6f28bfe5148b1a82b04569574bc865b65f6e8f874aa8b175ad3c3ee9197a9a22bc3693153f0d55ff2bd78938b15e162cafa4b77756d1933036b0520bf0",
|
||||
"@rollup/rollup-linux-loongarch64-gnu@npm:4.40.2": "ae77d9e7a797868fbd6887b8b4a8a26bcd96ea632022ddc47c570d90ad6e47b2ac0b3a933885c06a0af5ad57b5f818f4531ff6961b351e9705f5af6dd26b2427",
|
||||
"@rollup/rollup-linux-powerpc64le-gnu@npm:4.40.2": "867b6bc576e07110181f41c588b1a7ee22a6571bf5a3ceff0527c1e7c4540b5122d34b99f0c56c00d5c33a2e517fbb16c3e269cc4c08110e69dc0f0e4b2fbf26",
|
||||
"@rollup/rollup-linux-riscv64-gnu@npm:4.40.2": "52f07f3e5e008cd0d277d5290524682c8ec5c03e08659b07a800fddc00b450dbf8df08612921b9fe6e4e16d60d5e282027d9b260ff520c40bf3e7c5e1efabb60",
|
||||
"@rollup/rollup-linux-riscv64-musl@npm:4.40.2": "6483ab13ac5626c5b94d72aad3ffafe63a3572899824b1d37e59bc071b147f3d498864a0e19942e013a4488aa9262a92817232ca6c38339e3de62c3c4aca87e3",
|
||||
"@rollup/rollup-linux-s390x-gnu@npm:4.40.2": "842ad92a20ff994091d4ba4c16f87e2f8a57e1eb9e3004c20aaeeb692bc2061619dd43ba4dd246712f8904fe1480e6211b43e9fd2e11a5faebbeebea0c79da63",
|
||||
"@rollup/rollup-linux-x64-gnu@npm:4.40.2": "c440df4beca32d238b0a0f0b1017fb30da52c0f705946177c01a08d7d214ae190b2070885d93e15ff5fb5741e0964e1370bdd45f8a94e9a4689816f06f18c5a0",
|
||||
"@rollup/rollup-linux-x64-musl@npm:4.40.2": "9874b4cce42573d460634443ddb730d348360089bf93667309e660301e4e389d8ae80abe7f33fa9a20db5e67984e107e17d1479bdfee278d74bc60dde6ab5f83",
|
||||
"@rollup/rollup-win32-arm64-msvc@npm:4.40.2": "b61552ab831efde1ca4823cab1982d3d681e1be269d67d60558cd2ac86fe3802f6d569300d9ada084acebae27257b00c68f9d858261a579b5d8686956aa92ba0",
|
||||
"@rollup/rollup-win32-ia32-msvc@npm:4.40.2": "13ad059483b26bbf12af5108207d66a98ae2aef7599f27a506b998c781921b653dacc63ee0db57bb6f37c920163fd8bc40072e0be0ec6b1e5f52eb3f1455efeb",
|
||||
"@rollup/rollup-win32-x64-msvc@npm:4.40.2": "98ab8600ecbeab358c53ed563a7b586da0c5cdf26c03456a982a016b2f8eff6e2ec07055d15fe039b982a18a970744390d85a05970c9a8b1533c54702026f8df",
|
||||
"@unrs/resolver-binding-darwin-arm64@npm:1.3.2": "c8c61120e2bead2e0fec054399107e1ebd39455a2b7d59a5446cafad86cca376e0010e65644c41da0958a065869dcbe0509a29394b52a469a48990d32bf7a6e8",
|
||||
"@unrs/resolver-binding-darwin-x64@npm:1.3.2": "ee67a4043d2e297cb1362b7aa25be3f5defef9eb13f4e80358c3f22ffdef043ef905ac661fc9e70359383bafed5837a52bd001b49a8ea4f70372051d89ee6eff",
|
||||
"@unrs/resolver-binding-freebsd-x64@npm:1.3.2": "5f19ef3991435a96e682d427a8d9b28886b4afc9ea5b723e51c4bca51f25bb24add8819ed91c9f228bd39e139d51625cc127ddd35efd6c3f6e1d88106808fad1",
|
||||
"@unrs/resolver-binding-linux-arm-gnueabihf@npm:1.3.2": "f77b2345c2b572b569089092fa6c08b5a55fdb08d26e1db3cdfa0d195511a0efbe109c558e77bfd78d7aed4ffe47b6542890c9cad032cc00bb0fcd5f373f5090",
|
||||
"@unrs/resolver-binding-linux-arm-musleabihf@npm:1.3.2": "8b7156d8c641994c39626522ba42e69eef8d868a69b319c9ea5f7584ef0c4ea98bc698c1a4417d209dd3a786630be404d459680cf5b5b2500d3c4b0eb1be894f",
|
||||
"@unrs/resolver-binding-linux-arm64-gnu@npm:1.3.2": "93b28c2ea0dae2d452659e0afde6099107b70362043e19800e35b7ae86350856dfa0a4d6ba2be566c225965b458b5fba78a10219cf78e6fc0c581373cd2e2a52",
|
||||
"@unrs/resolver-binding-linux-arm64-musl@npm:1.3.2": "49ed9f24838e876eb1bba9b5f3e283af0716ee23f7d11a799a6376a47fa59a2e28b724431ca165a3874d60b1ed5a6b6c7650fe207f0610a788c88baa7862688f",
|
||||
"@unrs/resolver-binding-linux-ppc64-gnu@npm:1.3.2": "9fad22ffbf7aadf471a6d054c833a9b4cea74e2c38be40d546e6ba71058a6be10fa4e28947425ef33d42dc77de1c81b631fbff5a96a637c3a7652910f3e27d76",
|
||||
"@unrs/resolver-binding-linux-s390x-gnu@npm:1.3.2": "dd28e351f19268c4735da984e96301d8433603cf109b2b6880aab9bb8f448242699b7f84c36c536ca4a9443f944153098a3d3e78fce26d0c56fe3406d73d4b55",
|
||||
"@unrs/resolver-binding-linux-x64-gnu@npm:1.3.2": "e1cc70d8e012bc61bf5af85c2e9905aa1953c06daaab9b3857d780424c62807ccd0c5a20acb919e3accec7152badee426b1514ab9a4256b77945c3e7c8df3496",
|
||||
"@unrs/resolver-binding-linux-x64-musl@npm:1.3.2": "e97b95e53d029e4ccaf7cf32072e644c495d8e1f097b6fdeb417860db4db4b752d84f5fa6310b9f170a1fbf0562696f0145005dda4a95d658ea0857fac6c51dd",
|
||||
"@unrs/resolver-binding-wasm32-wasi@npm:1.3.2": "d3f16f36ba5dd714ef3eaf7bc57597e9f9a1fab7c6b5fb5dc5bf688d81a1bd4a574da16bd3e2b383181032a71001583b6534c21e5ffde1ee43fcfa95bc292f3b",
|
||||
"@unrs/resolver-binding-win32-arm64-msvc@npm:1.3.2": "de65010d133e99a062827f698a7e50c30db15d9f6b9011d351762cc8809497e97c4617b7d6ca3052583ca3f6b8c3cb1f2857fd0c9afd944c7ebb65d5e1da74f6",
|
||||
"@unrs/resolver-binding-win32-ia32-msvc@npm:1.3.2": "f214a8950e823c60656d2d113584c3cd20c6e92668f43f73c13c3ddfe38a7063615e42537645e2aa52a0652ace9c82e8fd5d9411043a6985ccb49d8dc8bb2595",
|
||||
"@unrs/resolver-binding-win32-x64-msvc@npm:1.3.2": "38ca5f5912d7cddd3f3e1983ad8e79d084ab3f5990189ce8cdfcfc3b58d97cc0dd7b543cc78ff43eb1769d15a8c235339a5942c688ab680192caa4c97116a511"
|
||||
}
|
||||
@@ -5,19 +5,18 @@
|
||||
patches ? [ ],
|
||||
}:
|
||||
let
|
||||
version = "4.3.9";
|
||||
version = "4.4.0";
|
||||
in
|
||||
applyPatches {
|
||||
src = fetchFromGitHub {
|
||||
owner = "mastodon";
|
||||
repo = "mastodon";
|
||||
rev = "v${version}";
|
||||
hash = "sha256-A2WxVwaarT866s97uwfStBVtv7T5czF7ymRswtZ2K4M=";
|
||||
|
||||
hash = "sha256-boAf0TnUlr+o4UqjFPzoRk2K6yFlxTo74BbkRowwkhw=";
|
||||
passthru = {
|
||||
inherit version;
|
||||
yarnHash = "sha256-IC4d/skIHEzJPuKlq4rMAqV+ydqquA6toq4WWCfuDxo=";
|
||||
yarnMissingHashes = null;
|
||||
yarnHash = "sha256-Qh2jli99rxrT10KVGKnePxP6RXYIjtehDCJB5PfOngM=";
|
||||
yarnMissingHashes = ./missing-hashes.json;
|
||||
};
|
||||
};
|
||||
patches = patches ++ [ ];
|
||||
|
||||
@@ -90,19 +90,19 @@ cat > source.nix << EOF
|
||||
let
|
||||
version = "$VERSION";
|
||||
in
|
||||
(applyPatches {
|
||||
applyPatches {
|
||||
src = fetchFromGitHub {
|
||||
owner = "$OWNER";
|
||||
repo = "$REPO";
|
||||
rev = "v\${version}";
|
||||
hash = "$HASH";
|
||||
passthru = {
|
||||
inherit version;
|
||||
yarnHash = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=";
|
||||
yarnMissingHashes = ./missing-hashes.json;
|
||||
};
|
||||
};
|
||||
patches = patches ++ [$PATCHES];
|
||||
})
|
||||
// {
|
||||
inherit version;
|
||||
yarnHash = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=";
|
||||
yarnMissingHashes = null;
|
||||
patches = patches ++ [ $PATCHES];
|
||||
}
|
||||
EOF
|
||||
SOURCE_DIR="$(nix-build --no-out-link -E '(import <nixpkgs> {}).callPackage ./source.nix {}')"
|
||||
@@ -112,5 +112,7 @@ bundix --lockfile="$SOURCE_DIR/Gemfile.lock" --gemfile="$SOURCE_DIR/Gemfile"
|
||||
echo "" >> gemset.nix # Create trailing newline to please EditorConfig checks
|
||||
|
||||
echo "Updating yarnHash"
|
||||
yarn-berry-fetcher missing-hashes "$SOURCE_DIR/yarn.lock" > missing-hashes.json
|
||||
YARN_HASH="$(yarn-berry-fetcher prefetch "$SOURCE_DIR/yarn.lock" 2>/dev/null)"
|
||||
sed -i "s;sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=;$YARN_HASH;g" source.nix
|
||||
|
||||
|
||||
@@ -3,6 +3,9 @@
|
||||
buildGoModule,
|
||||
fetchFromGitHub,
|
||||
nixosTests,
|
||||
|
||||
# Test dependencies
|
||||
redisTestHook,
|
||||
}:
|
||||
|
||||
buildGoModule rec {
|
||||
@@ -24,8 +27,31 @@ buildGoModule rec {
|
||||
"-X main.BuildDate=unknown"
|
||||
];
|
||||
|
||||
# needs a redis server
|
||||
doCheck = false;
|
||||
nativeCheckInputs = [
|
||||
redisTestHook
|
||||
];
|
||||
|
||||
preCheck = ''
|
||||
export TEST_REDIS_URI="redis://localhost:6379"
|
||||
'';
|
||||
|
||||
__darwinAllowLocalNetworking = true;
|
||||
|
||||
checkFlags =
|
||||
let
|
||||
skippedTests = [
|
||||
"TestLatencySpike" # timing-sensitive
|
||||
|
||||
# The following tests require ad-hoc generated TLS certificates in the source dir.
|
||||
# This is not possible in the read-only Nix store.
|
||||
"TestCreateClientTLSConfig"
|
||||
"TestValkeyTLSScheme"
|
||||
"TestCreateServerTLSConfig"
|
||||
"TestGetServerCertificateFunc"
|
||||
"TestGetConfigForClientFunc"
|
||||
];
|
||||
in
|
||||
[ "-skip=^${builtins.concatStringsSep "$|^" skippedTests}$" ];
|
||||
|
||||
passthru.tests = { inherit (nixosTests.prometheus-exporters) redis; };
|
||||
|
||||
|
||||
@@ -17,13 +17,13 @@ let
|
||||
in
|
||||
postgresqlBuildExtension (finalAttrs: {
|
||||
pname = "plv8";
|
||||
version = "3.2.3";
|
||||
version = "3.2.4";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "plv8";
|
||||
repo = "plv8";
|
||||
tag = "v${finalAttrs.version}";
|
||||
hash = "sha256-ivQZJSNn5giWF351fqZ7mBZoJkGtby5T7beK45g3Zqs=";
|
||||
hash = "sha256-v4r/6qwDwb3+PQPYV3FqmIcDEkSr8F46PVlFnhUWUGc=";
|
||||
};
|
||||
|
||||
patches = [
|
||||
@@ -132,7 +132,7 @@ postgresqlBuildExtension (finalAttrs: {
|
||||
meta = {
|
||||
description = "V8 Engine Javascript Procedural Language add-on for PostgreSQL";
|
||||
homepage = "https://plv8.github.io/";
|
||||
changelog = "https://github.com/plv8/plv8/blob/r${finalAttrs.version}/Changes";
|
||||
changelog = "https://github.com/plv8/plv8/blob/v${finalAttrs.version}/Changes";
|
||||
maintainers = [ ];
|
||||
platforms = postgresql.meta.platforms;
|
||||
license = lib.licenses.postgresql;
|
||||
|
||||
@@ -11976,6 +11976,7 @@ with pkgs;
|
||||
musical-spectrum = callPackage ../applications/audio/deadbeef/plugins/musical-spectrum.nix { };
|
||||
statusnotifier = callPackage ../applications/audio/deadbeef/plugins/statusnotifier.nix { };
|
||||
playlist-manager = callPackage ../applications/audio/deadbeef/plugins/playlist-manager.nix { };
|
||||
waveform-seekbar = callPackage ../applications/audio/deadbeef/plugins/waveform-seekbar.nix { };
|
||||
};
|
||||
|
||||
deadbeef-with-plugins = callPackage ../applications/audio/deadbeef/wrapper.nix {
|
||||
|
||||
Reference in New Issue
Block a user