Merge remote-tracking branch 'origin/master' into staging-next

This commit is contained in:
K900 2026-06-27 17:13:58 +03:00
commit caea65bc86
121 changed files with 1570 additions and 899 deletions

View file

@ -361,7 +361,8 @@ pkgs/development/python-modules/buildcatrust/ @ajs124 @lukegb @mweinelt
/pkgs/development/lua-modules @NixOS/lua
# Neovim
/pkgs/applications/editors/neovim @NixOS/neovim
/pkgs/applications/editors/neovim @NixOS/neovim
/doc/languages-frameworks/neovim.section.md @NixOS/neovim
# VimPlugins
/pkgs/applications/editors/vim/plugins @NixOS/neovim

View file

@ -25,7 +25,7 @@ neovim.override {
withRuby = false;
configure = {
customRC = ''
# here your custom viml configuration goes!
" here your custom viml configuration goes!
'';
packages.myVimPackage = with pkgs.vimPlugins; {
# See examples below on how to use custom packages.
@ -47,7 +47,7 @@ neovim-qt.override {
neovim = neovim.override {
configure = {
customRC = ''
# your custom viml configuration
" your custom viml configuration
'';
};
};
@ -64,11 +64,14 @@ For instance, `sqlite-lua` needs `g:sqlite_clib_path` to be set to work. Nixpkgs
- `wrapRc`: Nix, not being able to write in your `$HOME`, loads the
generated Neovim configuration via the `$VIMINIT` environment variable, i.e. : `export VIMINIT='lua dofile("/nix/store/…-init.lua")'`. This has side effects like preventing Neovim from sourcing your `init.lua` in `$XDG_CONFIG_HOME/nvim` (see bullet 7 of [`:help startup`](https://neovim.io/doc/user/starting.html#startup) in Neovim). Disable it if you want to generate your own wrapper. You can still reuse the generated vimscript init code via `neovim.passthru.initRc`.
- `plugins`: A list of plugins to add to the wrapper.
- `extraLuaPackages`: A function passed on to `lua.withPackages`
- `withPython3`, `withNodeJs`, `withRuby` control when to enable neovim
- `extraLuaPackages`: A function passed on to `lua.withPackages`.
- `extraPython3Packages`: A function passed on to `python3.withPackages`.
- `withPython3`, `withNodeJs`, `withRuby`, `withPerl` control when to enable neovim
providers (see `:h provider`).
- `vimAlias` and `viAlias` control whether to symlink the `vim` and `vi` binaries to `nvim` respectively.
- `extraName` is a string appended to the package name and derivation name.
```
```nix
wrapNeovimUnstable neovim-unwrapped {
autoconfigure = true;
autowrapRuntimeDeps = true;
@ -80,7 +83,8 @@ wrapNeovimUnstable neovim-unwrapped {
vim.opt.colorcolumn = { 100 }
vim.opt.termguicolors = true
'';
# plugins accepts a list of either plugins or { plugin = ...; config = ..vimscript.. };
# plugins accepts a list of either plugins or attribute sets containing:
# { plugin = ...; config = ...; type = "viml"|"lua"; } (type defaults to "viml")
plugins = with vimPlugins; [
{
plugin = vim-obsession;
@ -88,7 +92,19 @@ wrapNeovimUnstable neovim-unwrapped {
map <Leader>$ <Cmd>Obsession<CR>
'';
}
(nvim-treesitter.withPlugins (p: [ p.nix p.python ]))
{
plugin = grug-far-nvim;
type = "lua";
config = ''
require('grug-far').setup({
startInInsertMode = false,
})
'';
}
(nvim-treesitter.withPlugins (p: [
p.nix
p.python
]))
hex-nvim
];
extraLuaPackages = lp: [ lp.mpack ];
@ -98,12 +114,12 @@ wrapNeovimUnstable neovim-unwrapped {
}
```
You can explore the configuration with`nix repl` to discover these options and
You can explore the configuration with `nix repl` to discover these options and
override them. For instance:
```nix
neovim.overrideAttrs (oldAttrs: {
neovim.override {
autowrapRuntimeDeps = false;
})
}
```
## Specificities for some plugins {#neovim-plugin-specificities}

View file

@ -160,7 +160,7 @@ Once approved, the team will have the right privileges to be pinged and requeste
> [!TIP]
> The team name should be as short as possible; because it is nested under the maintainers group, no -maintainers suffix is needed.
After the first [weekly team sync](../.github/workflows/team-sync.yml) with the new team, it's then also possible to link it to the entry in `team-list.nix` by setting its `github` field to the GitHub team name.
After the first [weekly team sync](../.github/workflows/teams.yml) with the new team, it's then also possible to link it to the entry in `team-list.nix` by setting its `github` field to the GitHub team name.
# Maintainer scripts

View file

@ -19,8 +19,6 @@
netpbm,
vhost-device-vsock,
nixosTests,
qemu_pkg ? qemu_test,
qemu_test,
setuptools,
socat,
systemd,
@ -58,7 +56,6 @@ buildPythonApplication {
propagatedBuildInputs = [
coreutils
netpbm
qemu_pkg
socat
util-linux
vde2

View file

@ -1730,6 +1730,7 @@ class NspawnMachine(BaseMachine):
self.process = subprocess.Popen(
[self.start_command],
cwd=self.state_dir,
env={
"RUN_NSPAWN_ROOT_DIR": str(self.state_dir),
"RUN_NSPAWN_SHARED_DIR": str(self.shared_dir),

View file

@ -20,7 +20,6 @@ let
# the respective qemu version and with or without ocr support
testDriver = config.pythonTestDriverPackage.override {
inherit (config) enableOCR extraPythonPackages;
qemu_pkg = config.qemu.package;
enableNspawn = config.containers != { };
};

View file

@ -461,10 +461,17 @@ in
"${config.boot.initrd.systemd.package}/lib/systemd/systemd-udevd"
"${config.boot.initrd.systemd.package}/lib/udev/ata_id"
"${config.boot.initrd.systemd.package}/lib/udev/cdrom_id"
"${config.boot.initrd.systemd.package}/lib/udev/dmi_memory_id"
"${config.boot.initrd.systemd.package}/lib/udev/scsi_id"
"${config.boot.initrd.systemd.package}/lib/udev/rules.d"
]
++ lib.optional (
# https://github.com/systemd/systemd/blob/v259/meson.build#L1529-L1530
pkgs.stdenv.hostPlatform.isx86
|| pkgs.stdenv.hostPlatform.isAarch
|| pkgs.stdenv.hostPlatform.isLoongArch64
|| pkgs.stdenv.hostPlatform.isMips
|| pkgs.stdenv.hostPlatform.isRiscV64
) "${config.boot.initrd.systemd.package}/lib/udev/dmi_memory_id"
++ map (x: "${x}/bin") config.boot.initrd.services.udev.binPackages;
# Generate the udev rules for the initrd

View file

@ -7,7 +7,6 @@
let
inherit (lib)
all
attrsToList
concatMapStringsSep
concatStringsSep
@ -19,7 +18,6 @@ let
isBool
isDerivation
isInt
isList
isPath
isString
listToAttrs
@ -98,53 +96,67 @@ let
i: n: v:
"${i}${toString n} = ${v}";
formatKeyValue =
indent: n: v:
if (v == null) then
""
else if isInt v then
toOption indent n (toString v)
isPrimitive = v: !isAttrs v || isDerivation v;
formatPrimitive =
v:
if isInt v then
toString v
else if isBool v then
toOption indent n (yesOrNo v)
yesOrNo v
else if isString v then
toOption indent n v
else if isList v then
if all isString v then
toOption indent n (concatStringsSep " " v)
else
map (formatKeyValue indent n) v
v
else if isPath v || isDerivation v then
# paths -> copy to store
# derivations -> just use output path instead of looping over the attrs
toOption indent n "${v}"
else if isAttrs v && v ? _section then
let
sectionType = v._section.type;
sectionName = v._section.name;
sectionTitle = concatStringsSep " " (
filter (s: s != null) [
sectionType
sectionName
]
);
in
concatStringsSep "\n" (
[
"${indent}${sectionTitle} {"
]
++ (mapAttrsToList (formatKeyValue "${indent} ") (removeAttrs v [ "_section" ]))
++ [ "${indent}}" ]
)
else if isAttrs v then
concatStringsSep "\n" (
[
"${indent}${n} {"
]
++ (mapAttrsToList (formatKeyValue "${indent} ") v)
++ [ "${indent}}" ]
)
"${v}"
else
throw (traceSeq v "services.dovecot2.settings: unexpected type");
throw (traceSeq v "services.dovecot2.settings: unexpected primitive type");
formatSection =
indent: n: v:
let
sectionTitle =
if v ? _section then
concatStringsSep " " (
filter (s: s != null) [
v._section.type
v._section.name
]
)
else
n;
inner = removeAttrs v [ "_section" ];
in
concatStringsSep "\n" (
[ "${indent}${sectionTitle} {" ]
++ flatten (mapAttrsToList (primitiveLinesFor "${indent} ") inner)
++ flatten (mapAttrsToList (sectionLinesFor "${indent} ") inner)
++ [ "${indent}}" ]
);
# emit lines for a k=v pair only when the value is a primitive
primitiveLinesFor =
indent: n: v:
let
primitives = filter isPrimitive (flatten [ v ]);
hasOnlySections = primitives == [ ] && v != [ ];
in
# Only emit an empty list if the original entry was also an empty list.
# This is so that values like k = [{ ... }] will not produce an output
# here, but k = [] will, even though they result in the same
# primitives = [].
optional (!hasOnlySections && v != null) (
toOption indent n (concatMapStringsSep " " formatPrimitive primitives)
);
# emit lines for a k=v pair only when the value is *not* a primitive
sectionLinesFor =
indent: n: v:
let
sections = filter (e: !isPrimitive e) (flatten [ v ]);
in
map (e: formatSection indent n e) sections;
doveConf =
let
@ -156,10 +168,13 @@ let
];
in
concatStringsSep "\n" (
optional (configVersion != null) (formatKeyValue "" "dovecot_config_version" configVersion)
++ optional (storageVersion != null) (formatKeyValue "" "dovecot_storage_version" storageVersion)
optionals (configVersion != null) (primitiveLinesFor "" "dovecot_config_version" configVersion)
++ optionals (storageVersion != null) (
primitiveLinesFor "" "dovecot_storage_version" storageVersion
)
++ optionals (cfg.includeFiles != [ ]) (map (f: "!include ${f}") cfg.includeFiles)
++ flatten (mapAttrsToList (formatKeyValue "") remainingSettings)
++ flatten (mapAttrsToList (primitiveLinesFor "") remainingSettings)
++ flatten (mapAttrsToList (sectionLinesFor "") remainingSettings)
);
isPre24 = versionOlder cfg.package.version "2.4";

View file

@ -334,7 +334,7 @@ in
programs.fuse = {
enable = lib.mkIf cfg.autoMount true;
userAllowOther = lib.mkIf cfg.settings.Mounts.fuseAllowOther true;
userAllowOther = lib.mkIf cfg.settings.Mounts.FuseAllowOther true;
};
users.users = lib.mkIf (cfg.user == "ipfs") {

View file

@ -167,6 +167,13 @@ in
wantedBy = [ "multi-user.target" ];
description = "TabbyAPI - OAI compatible server for Exllama";
# Triton & huggingface downloader need writable cache folders
environment = {
HOME = "/var/lib/tabbyapi";
XDG_CACHE_HOME = "/var/lib/tabbyapi/.cache";
TRITON_CACHE_DIR = "/tmp/triton";
};
serviceConfig = {
ExecStart = "${lib.getExe cfg.package} --config=${configFile}";
Restart = "on-failure";

View file

@ -4231,8 +4231,10 @@ let
"systemd-networkd-wait-online@.service"
"systemd-networkd.service"
"systemd-networkd.socket"
"systemd-networkd-persistent-storage.service"
"systemd-networkd-resolve-hook.socket"
"systemd-networkd-varlink-metrics.socket"
"systemd-networkd-varlink.socket"
"systemd-networkd-persistent-storage.service"
];
systemd.sockets.systemd-networkd-varlink-metrics.wantedBy = [ "sockets.target" ];
@ -4314,6 +4316,9 @@ let
systemd.additionalUpstreamUnits = [
"systemd-networkd-wait-online.service"
"systemd-networkd.service"
"systemd-networkd-resolve-hook.socket"
"systemd-networkd-varlink-metrics.socket"
"systemd-networkd-varlink.socket"
"systemd-networkd.socket"
"systemd-network-generator.service"
"network-online.target"

View file

@ -185,7 +185,11 @@ in
# added with order 501 to allow modules to go before with mkBefore
system.nssDatabases.hosts = (mkOrder 501 [ "resolve [!UNAVAIL=return]" ]);
systemd.additionalUpstreamSystemUnits = [ "systemd-resolved.service" ];
systemd.additionalUpstreamSystemUnits = [
"systemd-resolved.service"
"systemd-resolved-monitor.socket"
"systemd-resolved-varlink.socket"
];
systemd.services.systemd-resolved = {
wantedBy = [ "sysinit.target" ];
@ -248,7 +252,12 @@ in
tmpfiles.settings.systemd-resolved-stub."/etc/resolv.conf".L.argument =
"/run/systemd/resolve/stub-resolv.conf";
additionalUpstreamUnits = [ "systemd-resolved.service" ];
additionalUpstreamUnits = [
"systemd-resolved.service"
"systemd-resolved-monitor.socket"
"systemd-resolved-varlink.socket"
];
users.systemd-resolve = { };
groups.systemd-resolve = { };
storePaths = [ "${config.boot.initrd.systemd.package}/lib/systemd/systemd-resolved" ];

View file

@ -65,6 +65,7 @@ let
# Udev.
"systemd-udevd-control.socket"
"systemd-udevd-kernel.socket"
"systemd-udevd-varlink.socket"
"systemd-udevd.service"
]
++ (optional (!config.boot.isContainer) "systemd-udev-trigger.service")
@ -157,6 +158,8 @@ let
"systemd-ask-password-wall.service"
# Varlink APIs
"systemd-ask-password@.service"
"systemd-ask-password.socket"
]
++ lib.optionals cfg.package.withBootloader [
"systemd-bootctl@.service"
@ -178,11 +181,13 @@ let
]
++ optionals cfg.package.withImportd [
"systemd-importd.service"
"systemd-importd.socket"
]
++ optionals cfg.package.withMachined [
"machine.slice"
"machines.target"
"systemd-machined.service"
"systemd-machined.socket"
]
++ optionals cfg.package.withNspawn [
"systemd-nspawn@.service"
@ -191,6 +196,9 @@ let
# Misc.
"systemd-sysctl.service"
"systemd-machine-id-commit.service"
"systemd-mute-console@.service"
"systemd-mute-console.socket"
]
++ optionals cfg.package.withTimedated [
"dbus-org.freedesktop.timedate1.service"
@ -209,6 +217,11 @@ let
"dbus-org.freedesktop.portable1.service"
"systemd-portabled.service"
]
++ optionals cfg.package.withRepart [
# Varlink APIs
"systemd-repart@.service"
"systemd-repart.socket"
]
++ [
"systemd-exit.service"
"systemd-update-done.service"
@ -221,6 +234,8 @@ let
"factory-reset.target"
"systemd-factory-reset-request.service"
"systemd-factory-reset-reboot.service"
"systemd-factory-reset@.service"
"systemd-factory-reset.socket"
]
++ cfg.additionalUpstreamSystemUnits;

View file

@ -157,6 +157,12 @@ in
boot.initrd.systemd = lib.mkIf initrdCfg.enable {
additionalUpstreamUnits = [
"systemd-repart.service"
# Varlink APIs
# NOTE: compared to stage 2 where the IPC is enabled in the global location, initrd
# might be optimized to keep away the repart binary.
# As a result, we enable repart IPC in the initrd only if repart is enabled in the initrd.
"systemd-repart.socket"
"systemd-repart@.service"
];
storePaths = [

View file

@ -317,6 +317,7 @@ in
mkdir -p $out/lib/tmpfiles.d
cd $out/lib/tmpfiles.d
ln -s "${systemd}/example/tmpfiles.d/credstore.conf"
ln -s "${systemd}/example/tmpfiles.d/home.conf"
ln -s "${systemd}/example/tmpfiles.d/journal-nocow.conf"
ln -s "${systemd}/example/tmpfiles.d/portables.conf"

View file

@ -43,6 +43,8 @@
"tpm2.target"
"systemd-tpm2-setup-early.service"
"systemd-tpm2-setup.service"
"systemd-pcrextend.socket"
"systemd-pcrextend@.service"
];
}
)
@ -69,6 +71,8 @@
boot.initrd.systemd.additionalUpstreamUnits = [
"tpm2.target"
"systemd-tpm2-setup-early.service"
"systemd-pcrextend.socket"
"systemd-pcrextend@.service"
];
boot.initrd.availableKernelModules = [
@ -81,6 +85,7 @@
pkgs.tpm2-tss
"${cfg.package}/lib/systemd/systemd-tpm2-setup"
"${cfg.package}/lib/systemd/system-generators/systemd-tpm2-generator"
"${cfg.package}/lib/systemd/systemd-pcrextend"
];
}
)
@ -89,7 +94,9 @@
cfg = config.boot.initrd.systemd;
in
lib.mkIf (cfg.enable && cfg.tpm2.enable && cfg.tpm2.pcrphases.enable) {
boot.initrd.systemd.additionalUpstreamUnits = [ "systemd-pcrphase-initrd.service" ];
boot.initrd.systemd.additionalUpstreamUnits = [
"systemd-pcrphase-initrd.service"
];
boot.initrd.systemd.services.systemd-pcrphase-initrd.wantedBy = [ "initrd.target" ];
boot.initrd.systemd.storePaths = [ "${cfg.package}/lib/systemd/systemd-pcrextend" ];
}

View file

@ -0,0 +1,63 @@
{ lib, pkgs, ... }:
{
options.virtualisation.credentials = lib.mkOption {
description = ''
Credentials to pass to the VM or container using systemd's credential system.
See {manpage}`systemd.exec(5)`, {manpage}`systemd-creds(1)` and https://systemd.io/CREDENTIALS/ for more
information about systemd credentials.
'';
default = { };
example = lib.literalExpression ''
{
database-password = {
text = "my-secret-password";
};
ssl-cert = {
source = "./cert.pem";
};
binary-key = {
source = "./private.der";
};
}
'';
type = lib.types.attrsOf (
lib.types.submodule (
{
name,
options,
config,
...
}:
{
options = {
source = lib.mkOption {
type = lib.types.nullOr (lib.types.pathWith { });
default = null;
description = ''
Source file on the host containing the credential data.
'';
};
text = lib.mkOption {
default = null;
type = lib.types.nullOr lib.types.str;
description = ''
Text content of the credential.
For binary data or when the credential content should come from
an existing file, use `source` instead.
::: {.warning}
The text here is stored in the host's nix store as a file.
:::
'';
};
};
config.source = lib.mkIf (config.text != null) (
lib.mkDerivedConfig options.text (pkgs.writeText name)
);
}
)
);
};
}

View file

@ -21,6 +21,10 @@ let
cfg = config.virtualisation;
in
{
imports = [
../credentials-options.nix
];
options = {
virtualisation.cmdline = lib.mkOption {
@ -131,7 +135,8 @@ in
# Send a READY=1 notification to a socket when the container is fully booted.
"--notify-ready=yes"
];
]
++ lib.mapAttrsToList (name: cred: "--load-credential=${name}:${cred.source}") cfg.credentials;
system.build.nspawn =
let

View file

@ -399,6 +399,7 @@ in
imports = [
../profiles/qemu-guest.nix
./disk-size-option.nix
./credentials-options.nix
(mkRenamedOptionModule
[
"virtualisation"
@ -1126,81 +1127,20 @@ in
};
virtualisation.credentials = mkOption {
description = ''
Credentials to pass to the VM using systemd's credential system.
See {manpage}`systemd.exec(5)` , {manpage}`systemd-creds(1)` and https://systemd.io/CREDENTIALS/ for more
information about systemd credentials.
'';
default = { };
example = {
database-password = {
text = "my-secret-password";
};
ssl-cert = {
source = "./cert.pem";
};
binary-key = {
mechanism = "fw_cfg";
source = "./private.der";
};
config-file = {
mechanism = "smbios";
text = ''
[database]
host=localhost
port=5432
'';
};
};
type = types.attrsOf (
lib.types.submodule (
{
name,
options,
config,
...
}:
{
options = {
mechanism = lib.mkOption {
type = lib.types.enum [
"fw_cfg"
"smbios"
];
default = if pkgs.stdenv.hostPlatform.isx86 then "smbios" else "fw_cfg";
defaultText = lib.literalExpression ''if pkgs.stdenv.hostPlatform.isx86 then "smbios" else "fw_cfg"'';
description = ''
The mechanism used to pass the credential to the VM.
'';
};
source = lib.mkOption {
type = lib.types.nullOr (lib.types.pathWith { });
default = null;
description = ''
Source file on the host containing the credential data.
'';
};
text = lib.mkOption {
default = null;
type = lib.types.nullOr lib.types.str;
description = ''
Text content of the credential.
For binary data or when the credential content should come from
an existing file, use `source` instead.
::: {.warning}
The text here is stored in the host's nix store as a file.
:::
'';
};
};
config.source = lib.mkIf (config.text != null) (
lib.mkDerivedConfig options.text (pkgs.writeText name)
);
}
)
lib.types.submodule {
options.mechanism = lib.mkOption {
type = lib.types.enum [
"fw_cfg"
"smbios"
];
default = if pkgs.stdenv.hostPlatform.isx86 then "smbios" else "fw_cfg";
defaultText = lib.literalExpression ''if pkgs.stdenv.hostPlatform.isx86 then "smbios" else "fw_cfg"'';
description = ''
The mechanism used to pass the credential to the VM.
'';
};
}
);
};

View file

@ -448,6 +448,14 @@ in
};
coturn = runTest ./coturn.nix;
couchdb = runTest ./couchdb.nix;
credentials-fwcfg = runTest {
imports = [ ./credentials.nix ];
_module.args.mechanism = "fw_cfg";
};
credentials-smbios = runTestOn [ "x86_64-linux" ] {
imports = [ ./credentials.nix ];
_module.args.mechanism = "smbios";
};
cri-o = runTestOn [ "aarch64-linux" "x86_64-linux" ] ./cri-o.nix;
croc = runTest ./croc.nix;
cross-seed = runTest ./cross-seed.nix;
@ -1425,14 +1433,6 @@ in
pykms = runTest ./pykms.nix;
qbittorrent = runTest ./qbittorrent.nix;
qboot = runTestOn [ "x86_64-linux" "i686-linux" ] ./qboot.nix;
qemu-vm-credentials-fwcfg = runTest {
imports = [ ./qemu-vm-credentials.nix ];
_module.args.mechanism = "fw_cfg";
};
qemu-vm-credentials-smbios = runTestOn [ "x86_64-linux" ] {
imports = [ ./qemu-vm-credentials.nix ];
_module.args.mechanism = "smbios";
};
qemu-vm-external-disk-image = runTest ./qemu-vm-external-disk-image.nix;
qemu-vm-restrictnetwork = handleTest ./qemu-vm-restrictnetwork.nix { };
qemu-vm-store = runTest ./qemu-vm-store.nix;
@ -1715,6 +1715,7 @@ in
systemd-user-settings = runTest ./systemd-user-settings.nix;
systemd-user-tmpfiles-rules = runTest ./systemd-user-tmpfiles-rules.nix;
systemd-userdbd = runTest ./systemd-userdbd.nix;
systemd-varlink = runTest ./systemd-varlink.nix;
systemtap = handleTest ./systemtap.nix { };
szurubooru = handleTest ./szurubooru.nix { };
taler = handleTest ./taler { };

View file

@ -207,7 +207,7 @@ in
import os
# Create a mutable linked image backed by the read-only SD image
if os.system("qemu-img create -f qcow2 -F raw -b ${sdImage} ${mutableImage}") != 0:
if os.system("${pkgs.qemu}/bin/qemu-img create -f qcow2 -F raw -b ${sdImage} ${mutableImage}") != 0:
raise RuntimeError("Could not create mutable linked image")
machine = create_machine("${startCommand}")

View file

@ -51,9 +51,11 @@ in
)
os.makedirs(image_dir, mode=0o700, exist_ok=True)
disk_image = os.path.join(image_dir, "machine.qcow2")
QEMU_BIN = "${pkgs.qemu}"
QEMU_IMG = f"{QEMU_BIN}/bin/qemu-img"
subprocess.check_call(
[
"qemu-img",
QEMU_IMG,
"create",
"-f",
"qcow2",
@ -64,7 +66,7 @@ in
disk_image,
]
)
subprocess.check_call(["qemu-img", "resize", disk_image, "10G"])
subprocess.check_call([QEMU_IMG, "resize", disk_image, "10G"])
# Note: we use net=169.0.0.0/8 rather than
# net=169.254.0.0/16 to prevent dhcpcd from getting horribly
@ -74,7 +76,7 @@ in
# turn off the DHCP server, but qemu does not have an option
# to do that.
start_command = (
"qemu-kvm -m 1024"
f"{QEMU_BIN}/bin/qemu-kvm -m 1024"
+ " -device virtio-net-pci,netdev=vlan0"
+ " -netdev 'user,id=vlan0,net=169.0.0.0/8,guestfwd=tcp:169.254.169.254:80-cmd:${getExe imdsServer} ${metaData}'"
+ f" -drive file={disk_image},if=virtio,werror=report"

106
nixos/tests/credentials.nix Normal file
View file

@ -0,0 +1,106 @@
{
lib,
pkgs,
mechanism,
...
}:
let
secret = ''
foo
bar
baz
'';
secret-file = "bar";
common-credentials = {
secret-default-mechanism = {
text = "default-mechanism";
};
secret-file-nix-store = {
source = pkgs.writeText "secret-file-nix-store" secret-file;
};
secret-file-host = {
source = "./secret-file-host";
};
secret-file-host-binary = {
source = "./secret-file-host-binary";
};
};
in
{
name = "credentials-${mechanism}";
meta.maintainers = with lib.maintainers; [ arianvp ];
# No VM<->container traffic in this test; credentials are static.
requiredFeatures.devnet = lib.mkForce false;
nodes.vm = {
virtualisation.credentials = common-credentials // {
secret = {
inherit mechanism;
text = secret;
};
};
};
containers.container = {
virtualisation.credentials = common-credentials // {
secret = {
text = secret;
};
};
};
testScript = ''
import base64
secret_file_host = "baz"
# Binary data with null bytes, high bytes, and other problematic characters.
secret_file_host_binary = bytes([
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
0xDE, 0xAD, 0xBE, 0xEF,
0xFF, 0xFE, 0xFD, 0xFC,
0x00, 0x00, 0x00, 0x00,
0x80, 0x81, 0x82, 0x83,
])
def assert_credentials(m):
with open(m.state_dir / "secret-file-host", "w") as f:
f.write(secret_file_host)
with open(m.state_dir / "secret-file-host-binary", "wb") as f2:
f2.write(secret_file_host_binary)
t.assertEqual(
m.succeed("systemd-creds --system cat secret").strip(),
"foo\nbar\nbaz",
)
t.assertEqual(
m.succeed("systemd-creds --system cat secret-default-mechanism").strip(),
"default-mechanism",
)
t.assertEqual(
m.succeed("systemd-creds --system cat secret-file-nix-store").strip(),
"${secret-file}",
)
t.assertEqual(
m.succeed("systemd-creds --system cat secret-file-host").strip(),
secret_file_host,
)
result = m.succeed(
"systemd-creds --system cat secret-file-host-binary --transcode=base64"
).strip()
expected = base64.b64encode(secret_file_host_binary).decode("ascii")
t.assertEqual(
result,
expected,
f"Binary credential mismatch: got {result}, expected {expected}",
)
assert_credentials(vm)
assert_credentials(container)
'';
}

View file

@ -88,294 +88,298 @@ in
};
};
testScript = ''
import os
import re
import subprocess
import tempfile
testScript =
{ nodes, ... }:
''
import os
import re
import subprocess
import tempfile
# Instance Metadata Service (IMDSv2 with 1.0 metadata version)
# TODO: Use 'latest' metadata version instead of '1.0'
# TODO: [Test matrix] also test providing the host key through IMDS
# - i.e. a test module argument to select between writing or reading the host key
def create_ec2_metadata_dir(temp_dir, client_pubkey):
"""Create fake EC2 metadata directory structure with mock data"""
metadata_dir = os.path.join(temp_dir.name, "ec2-metadata")
# Instance Metadata Service (IMDSv2 with 1.0 metadata version)
# TODO: Use 'latest' metadata version instead of '1.0'
# TODO: [Test matrix] also test providing the host key through IMDS
# - i.e. a test module argument to select between writing or reading the host key
def create_ec2_metadata_dir(temp_dir, client_pubkey):
"""Create fake EC2 metadata directory structure with mock data"""
metadata_dir = os.path.join(temp_dir.name, "ec2-metadata")
# Create directory structure
os.makedirs(os.path.join(metadata_dir, "1.0", "meta-data", "public-keys", "0"), exist_ok=True)
os.makedirs(os.path.join(metadata_dir, "latest", "api"), exist_ok=True)
# Create directory structure
os.makedirs(os.path.join(metadata_dir, "1.0", "meta-data", "public-keys", "0"), exist_ok=True)
os.makedirs(os.path.join(metadata_dir, "latest", "api"), exist_ok=True)
# Metadata version 1.0 endpoints (what fetch-ec2-metadata.sh actually fetches)
with open(os.path.join(metadata_dir, "1.0", "meta-data", "hostname"), "w") as f:
f.write("test-instance")
with open(os.path.join(metadata_dir, "1.0", "meta-data", "ami-manifest-path"), "w") as f:
f.write("(test)")
with open(os.path.join(metadata_dir, "1.0", "meta-data", "instance-id"), "w") as f:
f.write("i-1234567890abcdef0")
with open(os.path.join(metadata_dir, "1.0", "user-data"), "w") as f:
f.write("")
with open(os.path.join(metadata_dir, "1.0", "meta-data", "public-keys", "0", "openssh-key"), "w") as f:
f.write(client_pubkey)
# Metadata version 1.0 endpoints (what fetch-ec2-metadata.sh actually fetches)
with open(os.path.join(metadata_dir, "1.0", "meta-data", "hostname"), "w") as f:
f.write("test-instance")
with open(os.path.join(metadata_dir, "1.0", "meta-data", "ami-manifest-path"), "w") as f:
f.write("(test)")
with open(os.path.join(metadata_dir, "1.0", "meta-data", "instance-id"), "w") as f:
f.write("i-1234567890abcdef0")
with open(os.path.join(metadata_dir, "1.0", "user-data"), "w") as f:
f.write("")
with open(os.path.join(metadata_dir, "1.0", "meta-data", "public-keys", "0", "openssh-key"), "w") as f:
f.write(client_pubkey)
# IMDSv2 token endpoint - return a fake token
with open(os.path.join(metadata_dir, "latest", "api", "token"), "w") as f:
f.write("test-token-12345")
# IMDSv2 token endpoint - return a fake token
with open(os.path.join(metadata_dir, "latest", "api", "token"), "w") as f:
f.write("test-token-12345")
return metadata_dir
return metadata_dir
def generate_client_ssh_key():
"""Generate SSH key pair on VM host for client authentication"""
# Use temporary directory for key generation
import tempfile
with tempfile.TemporaryDirectory() as key_dir:
private_key = os.path.join(key_dir, "id_ed25519")
public_key = os.path.join(key_dir, "id_ed25519.pub")
def generate_client_ssh_key():
"""Generate SSH key pair on VM host for client authentication"""
# Use temporary directory for key generation
import tempfile
with tempfile.TemporaryDirectory() as key_dir:
private_key = os.path.join(key_dir, "id_ed25519")
public_key = os.path.join(key_dir, "id_ed25519.pub")
# Generate key pair using host SSH tools
ret = os.system(f"${hostPkgs.openssh}/bin/ssh-keygen -t ed25519 -f {private_key} -N \"\"")
if ret != 0:
raise Exception("Failed to generate SSH key pair")
# Generate key pair using host SSH tools
ret = os.system(f"${hostPkgs.openssh}/bin/ssh-keygen -t ed25519 -f {private_key} -N \"\"")
if ret != 0:
raise Exception("Failed to generate SSH key pair")
# Read the generated public key
with open(public_key, "r") as f:
client_pubkey = f.read().strip()
# Read the generated public key
with open(public_key, "r") as f:
client_pubkey = f.read().strip()
# Read the private key
with open(private_key, "r") as f:
client_private_key = f.read()
# Read the private key
with open(private_key, "r") as f:
client_private_key = f.read()
return client_pubkey, client_private_key
return client_pubkey, client_private_key
def setup_client_ssh_key(client, client_private_key):
"""Install the pre-generated SSH private key on client"""
client.succeed("mkdir -p /root/.ssh")
client.succeed(f"cat > /root/.ssh/id_ed25519 << 'EOF'\n{client_private_key}\nEOF")
client.succeed("chmod 600 /root/.ssh/id_ed25519")
def setup_client_ssh_key(client, client_private_key):
"""Install the pre-generated SSH private key on client"""
client.succeed("mkdir -p /root/.ssh")
client.succeed(f"cat > /root/.ssh/id_ed25519 << 'EOF'\n{client_private_key}\nEOF")
client.succeed("chmod 600 /root/.ssh/id_ed25519")
def setup_machine(temp_dir, client_pubkey):
"""Initialize EC2 machine with disk image, metadata server, and networking"""
# Set up disk image
image_dir = os.path.join(
os.environ.get("TMPDIR", tempfile.gettempdir()), "tmp", "vm-state-machine"
)
os.makedirs(image_dir, mode=0o700, exist_ok=True)
disk_image = os.path.join(image_dir, "machine.qcow2")
subprocess.check_call([
"qemu-img", "create", "-f", "qcow2", "-F", "qcow2",
"-o", "backing_file=${image}", disk_image
])
subprocess.check_call(["qemu-img", "resize", disk_image, "10G"])
def setup_machine(temp_dir, client_pubkey):
"""Initialize EC2 machine with disk image, metadata server, and networking"""
# Set up disk image
image_dir = os.path.join(
os.environ.get("TMPDIR", tempfile.gettempdir()), "tmp", "vm-state-machine"
)
os.makedirs(image_dir, mode=0o700, exist_ok=True)
disk_image = os.path.join(image_dir, "machine.qcow2")
QEMU = "${nodes.machine.virtualisation.qemu.package}"
QEMU_IMG = f"{QEMU}/bin/qemu-img"
subprocess.check_call([
QEMU_IMG, "create", "-f", "qcow2", "-F", "qcow2",
"-o", "backing_file=${image}", disk_image
])
subprocess.check_call([QEMU_IMG, "resize", disk_image, "10G"])
# Create fake EC2 metadata in temporary directory with client's public key
metadata_dir = create_ec2_metadata_dir(temp_dir, client_pubkey)
# Create fake EC2 metadata in temporary directory with client's public key
metadata_dir = create_ec2_metadata_dir(temp_dir, client_pubkey)
# Add both VLAN networking (matching test framework) and EC2 metadata server
vlan_net = (
" -device virtio-net-pci,netdev=vlan1,mac=52:54:00:12:01:02"
+ ' -netdev vde,id=vlan1,sock="$QEMU_VDE_SOCKET_1"'
)
metadata_net = (
" -device virtio-net-pci,netdev=ec2meta"
+ f" -netdev 'user,id=ec2meta,net=169.0.0.0/8,guestfwd=tcp:169.254.169.254:80-cmd:${lib.getExe imdsServer} {metadata_dir}'"
)
# Add both VLAN networking (matching test framework) and EC2 metadata server
vlan_net = (
" -device virtio-net-pci,netdev=vlan1,mac=52:54:00:12:01:02"
+ ' -netdev vde,id=vlan1,sock="$QEMU_VDE_SOCKET_1"'
)
metadata_net = (
" -device virtio-net-pci,netdev=ec2meta"
+ f" -netdev 'user,id=ec2meta,net=169.0.0.0/8,guestfwd=tcp:169.254.169.254:80-cmd:${lib.getExe imdsServer} {metadata_dir}'"
)
start_command = (
"qemu-kvm -m 1024"
+ f" -drive file={disk_image},if=virtio,werror=report"
+ vlan_net
+ metadata_net
+ " $QEMU_OPTS"
)
start_command = (
f"{QEMU}/bin/qemu-kvm -m 1024"
+ f" -drive file={disk_image},if=virtio,werror=report"
+ vlan_net
+ metadata_net
+ " $QEMU_OPTS"
)
return create_machine(start_command), metadata_dir
return create_machine(start_command), metadata_dir
def test_userdata_decompression(machine, user_data_path, compressed_data, format_name):
"""Test that compressed user-data is decompressed by fetch-ec2-metadata"""
test_marker = f"{format_name}-decompression-test"
with open(user_data_path, "wb") as f:
f.write(compressed_data)
machine.succeed("systemctl reset-failed fetch-ec2-metadata; systemctl restart fetch-ec2-metadata")
result = machine.succeed("cat /etc/ec2-metadata/user-data")
assert test_marker in result, f"Expected '{test_marker}' in decompressed {format_name} content, got: {result}"
journal = machine.succeed("journalctl -u fetch-ec2-metadata --no-pager -b")
assert "decompressing:" in journal, f"Expected decompression log in journal for {format_name}"
def test_userdata_decompression(machine, user_data_path, compressed_data, format_name):
"""Test that compressed user-data is decompressed by fetch-ec2-metadata"""
test_marker = f"{format_name}-decompression-test"
with open(user_data_path, "wb") as f:
f.write(compressed_data)
machine.succeed("systemctl reset-failed fetch-ec2-metadata; systemctl restart fetch-ec2-metadata")
result = machine.succeed("cat /etc/ec2-metadata/user-data")
assert test_marker in result, f"Expected '{test_marker}' in decompressed {format_name} content, got: {result}"
journal = machine.succeed("journalctl -u fetch-ec2-metadata --no-pager -b")
assert "decompressing:" in journal, f"Expected decompression log in journal for {format_name}"
# Create temporary directory for metadata (scoped for cleanup)
temp_dir = tempfile.TemporaryDirectory()
# Create temporary directory for metadata (scoped for cleanup)
temp_dir = tempfile.TemporaryDirectory()
# Start client first (but don't wait for it to boot)
client.start()
# Start client first (but don't wait for it to boot)
client.start()
# Generate SSH key pair on VM host before starting machine
client_pubkey, client_private_key = generate_client_ssh_key()
# Generate SSH key pair on VM host before starting machine
client_pubkey, client_private_key = generate_client_ssh_key()
# Set up machine with client's public key in metadata service
machine, metadata_dir = setup_machine(temp_dir, client_pubkey)
user_data_path = os.path.join(metadata_dir, "1.0", "user-data")
# Set up machine with client's public key in metadata service
machine, metadata_dir = setup_machine(temp_dir, client_pubkey)
user_data_path = os.path.join(metadata_dir, "1.0", "user-data")
try:
machine.start()
try:
machine.start()
# Wait for services to be ready
machine.wait_for_unit("sshd.service")
machine.wait_for_unit("print-host-key.service")
machine.wait_for_unit("apply-ec2-data.service")
# Wait for services to be ready
machine.wait_for_unit("sshd.service")
machine.wait_for_unit("print-host-key.service")
machine.wait_for_unit("apply-ec2-data.service")
# Extract shared variables outside subtests
machine_ip = "${config.nodes.machine.networking.primaryIPAddress}"
# Extract shared variables outside subtests
machine_ip = "${config.nodes.machine.networking.primaryIPAddress}"
with subtest("EC2 metadata service connectivity"):
# Obtain an IMDSv2 token, then use it to fetch metadata
imds_token = machine.succeed(
"curl -sf -X PUT -H 'X-aws-ec2-metadata-token-ttl-seconds: 600'"
" http://169.254.169.254/latest/api/token"
).strip()
assert imds_token, "Failed to obtain IMDSv2 token"
hostname_response = machine.succeed(
f"curl -sf -H 'X-aws-ec2-metadata-token: {imds_token}'"
" http://169.254.169.254/1.0/meta-data/hostname"
)
assert "test-instance" in hostname_response, f"Expected 'test-instance', got: {hostname_response}"
with subtest("EC2 metadata service connectivity"):
# Obtain an IMDSv2 token, then use it to fetch metadata
imds_token = machine.succeed(
"curl -sf -X PUT -H 'X-aws-ec2-metadata-token-ttl-seconds: 600'"
" http://169.254.169.254/latest/api/token"
).strip()
assert imds_token, "Failed to obtain IMDSv2 token"
hostname_response = machine.succeed(
f"curl -sf -H 'X-aws-ec2-metadata-token: {imds_token}'"
" http://169.254.169.254/1.0/meta-data/hostname"
)
assert "test-instance" in hostname_response, f"Expected 'test-instance', got: {hostname_response}"
with subtest("SSH host key extraction from console"):
console_log = machine.get_console_log()
assert "-----BEGIN SSH HOST KEY FINGERPRINTS-----" in console_log
assert "-----END SSH HOST KEY FINGERPRINTS-----" in console_log
assert "-----BEGIN SSH HOST KEY KEYS-----" in console_log
assert "-----END SSH HOST KEY KEYS-----" in console_log
with subtest("SSH host key extraction from console"):
console_log = machine.get_console_log()
assert "-----BEGIN SSH HOST KEY FINGERPRINTS-----" in console_log
assert "-----END SSH HOST KEY FINGERPRINTS-----" in console_log
assert "-----BEGIN SSH HOST KEY KEYS-----" in console_log
assert "-----END SSH HOST KEY KEYS-----" in console_log
keys_pattern = r"-----BEGIN SSH HOST KEY KEYS-----(.*?)-----END SSH HOST KEY KEYS-----"
keys_match = re.search(keys_pattern, console_log, re.DOTALL)
assert keys_match, "Could not find SSH host keys section"
keys_content = keys_match.group(1).strip()
assert "ssh-" in keys_content, "SSH keys should contain ssh- prefix"
keys_pattern = r"-----BEGIN SSH HOST KEY KEYS-----(.*?)-----END SSH HOST KEY KEYS-----"
keys_match = re.search(keys_pattern, console_log, re.DOTALL)
assert keys_match, "Could not find SSH host keys section"
keys_content = keys_match.group(1).strip()
assert "ssh-" in keys_content, "SSH keys should contain ssh- prefix"
with subtest("Network connectivity"):
client.succeed(f"ping -c 1 {machine_ip}")
with subtest("Network connectivity"):
client.succeed(f"ping -c 1 {machine_ip}")
with subtest("SSH connectivity with strict host key checking"):
# Install the pre-generated private key on client
setup_client_ssh_key(client, client_private_key)
with subtest("SSH connectivity with strict host key checking"):
# Install the pre-generated private key on client
setup_client_ssh_key(client, client_private_key)
# Get console log and extract host keys
console_log = machine.get_console_log()
keys_pattern = r"-----BEGIN SSH HOST KEY KEYS-----(.*?)-----END SSH HOST KEY KEYS-----"
keys_match = re.search(keys_pattern, console_log, re.DOTALL)
assert keys_match, "Could not find SSH host keys section"
# Get console log and extract host keys
console_log = machine.get_console_log()
keys_pattern = r"-----BEGIN SSH HOST KEY KEYS-----(.*?)-----END SSH HOST KEY KEYS-----"
keys_match = re.search(keys_pattern, console_log, re.DOTALL)
assert keys_match, "Could not find SSH host keys section"
# Create known_hosts file from console-extracted host keys
keys_content = keys_match.group(1).strip()
known_hosts_entries = []
for line in keys_content.split('\n'):
if line.strip() and line.startswith('ssh-'):
known_hosts_entries.append(f"{machine_ip} {line.strip()}")
# Create known_hosts file from console-extracted host keys
keys_content = keys_match.group(1).strip()
known_hosts_entries = []
for line in keys_content.split('\n'):
if line.strip() and line.startswith('ssh-'):
known_hosts_entries.append(f"{machine_ip} {line.strip()}")
assert known_hosts_entries, "No SSH host keys found for known_hosts generation"
assert known_hosts_entries, "No SSH host keys found for known_hosts generation"
known_hosts_content = '\n'.join(known_hosts_entries)
client.succeed(f"cat > /root/.ssh/known_hosts << 'EOF'\n{known_hosts_content}\nEOF")
known_hosts_content = '\n'.join(known_hosts_entries)
client.succeed(f"cat > /root/.ssh/known_hosts << 'EOF'\n{known_hosts_content}\nEOF")
# Test SSH connectivity with strict host key checking
ssh_result = client.succeed(f"ssh -o ConnectTimeout=60 -o BatchMode=yes -i /root/.ssh/id_ed25519 root@{machine_ip} 'echo Hello from $(hostname)'")
assert "Hello from test-instance" in ssh_result, f"Unexpected SSH result: {ssh_result}"
# Test SSH connectivity with strict host key checking
ssh_result = client.succeed(f"ssh -o ConnectTimeout=60 -o BatchMode=yes -i /root/.ssh/id_ed25519 root@{machine_ip} 'echo Hello from $(hostname)'")
assert "Hello from test-instance" in ssh_result, f"Unexpected SSH result: {ssh_result}"
with subtest("Basic EC2 functionality"):
machine.succeed("findmnt / -o SIZE -n | grep -E '[0-9]+G'")
with subtest("Basic EC2 functionality"):
machine.succeed("findmnt / -o SIZE -n | grep -E '[0-9]+G'")
with subtest("Decompression of gzip-compressed user-data"):
import gzip as gzip_mod
test_data = b"#!/bin/bash\necho gzip-decompression-test\n"
test_userdata_decompression(machine, user_data_path, gzip_mod.compress(test_data), "gzip")
with subtest("Decompression of gzip-compressed user-data"):
import gzip as gzip_mod
test_data = b"#!/bin/bash\necho gzip-decompression-test\n"
test_userdata_decompression(machine, user_data_path, gzip_mod.compress(test_data), "gzip")
with subtest("Decompression of bzip2-compressed user-data"):
import bz2
test_data = b"#!/bin/bash\necho bzip2-decompression-test\n"
test_userdata_decompression(machine, user_data_path, bz2.compress(test_data), "bzip2")
with subtest("Decompression of bzip2-compressed user-data"):
import bz2
test_data = b"#!/bin/bash\necho bzip2-decompression-test\n"
test_userdata_decompression(machine, user_data_path, bz2.compress(test_data), "bzip2")
with subtest("Decompression of xz-compressed user-data"):
import lzma
test_data = b"#!/bin/bash\necho xz-decompression-test\n"
test_userdata_decompression(machine, user_data_path, lzma.compress(test_data), "xz")
with subtest("Decompression of xz-compressed user-data"):
import lzma
test_data = b"#!/bin/bash\necho xz-decompression-test\n"
test_userdata_decompression(machine, user_data_path, lzma.compress(test_data), "xz")
with subtest("Decompression of zstd-compressed user-data"):
test_data = b"#!/bin/bash\necho zstd-decompression-test\n"
proc = subprocess.run(
["${hostPkgs.zstd}/bin/zstd", "-c"],
input=test_data, capture_output=True, check=True,
)
test_userdata_decompression(machine, user_data_path, proc.stdout, "zstd")
with subtest("Decompression of zstd-compressed user-data"):
test_data = b"#!/bin/bash\necho zstd-decompression-test\n"
proc = subprocess.run(
["${hostPkgs.zstd}/bin/zstd", "-c"],
input=test_data, capture_output=True, check=True,
)
test_userdata_decompression(machine, user_data_path, proc.stdout, "zstd")
with subtest("Decompression of lzip-compressed user-data"):
test_data = b"#!/bin/bash\necho lzip-decompression-test\n"
proc = subprocess.run(
["${hostPkgs.lzip}/bin/lzip", "-c"],
input=test_data, capture_output=True, check=True,
)
test_userdata_decompression(machine, user_data_path, proc.stdout, "lzip")
with subtest("Decompression of lzip-compressed user-data"):
test_data = b"#!/bin/bash\necho lzip-decompression-test\n"
proc = subprocess.run(
["${hostPkgs.lzip}/bin/lzip", "-c"],
input=test_data, capture_output=True, check=True,
)
test_userdata_decompression(machine, user_data_path, proc.stdout, "lzip")
with subtest("IPv6 IMDS fallback"):
# Save hostname fetched via IPv4 for later comparison
original_hostname = machine.succeed("cat /etc/ec2-metadata/hostname").strip()
with subtest("IPv6 IMDS fallback"):
# Save hostname fetched via IPv4 for later comparison
original_hostname = machine.succeed("cat /etc/ec2-metadata/hostname").strip()
# Assign the EC2 IPv6 IMDS address to loopback
machine.succeed("ip -6 addr add fd00:ec2::254/128 dev lo")
# Assign the EC2 IPv6 IMDS address to loopback
machine.succeed("ip -6 addr add fd00:ec2::254/128 dev lo")
# Create metadata directory structure for the IPv6 endpoint
machine.succeed(
"mkdir -p /tmp/ipv6-metadata/1.0/meta-data/public-keys/0"
" && mkdir -p /tmp/ipv6-metadata/latest/api"
" && cp /etc/ec2-metadata/hostname /tmp/ipv6-metadata/1.0/meta-data/hostname"
" && cp /etc/ec2-metadata/ami-manifest-path /tmp/ipv6-metadata/1.0/meta-data/ami-manifest-path"
" && echo i-1234567890abcdef0 > /tmp/ipv6-metadata/1.0/meta-data/instance-id"
" && echo ipv6-test-token > /tmp/ipv6-metadata/latest/api/token"
" && touch /tmp/ipv6-metadata/1.0/user-data"
)
machine.execute(
"test -f /etc/ec2-metadata/public-keys-0-openssh-key"
" && cp /etc/ec2-metadata/public-keys-0-openssh-key"
" /tmp/ipv6-metadata/1.0/meta-data/public-keys/0/openssh-key"
)
# Create metadata directory structure for the IPv6 endpoint
machine.succeed(
"mkdir -p /tmp/ipv6-metadata/1.0/meta-data/public-keys/0"
" && mkdir -p /tmp/ipv6-metadata/latest/api"
" && cp /etc/ec2-metadata/hostname /tmp/ipv6-metadata/1.0/meta-data/hostname"
" && cp /etc/ec2-metadata/ami-manifest-path /tmp/ipv6-metadata/1.0/meta-data/ami-manifest-path"
" && echo i-1234567890abcdef0 > /tmp/ipv6-metadata/1.0/meta-data/instance-id"
" && echo ipv6-test-token > /tmp/ipv6-metadata/latest/api/token"
" && touch /tmp/ipv6-metadata/1.0/user-data"
)
machine.execute(
"test -f /etc/ec2-metadata/public-keys-0-openssh-key"
" && cp /etc/ec2-metadata/public-keys-0-openssh-key"
" /tmp/ipv6-metadata/1.0/meta-data/public-keys/0/openssh-key"
)
# Serve metadata on the IPv6 IMDS address via socat + imds-server (inetd-style)
machine.succeed(
"systemd-run --unit=ipv6-imds --"
" socat TCP6-LISTEN:80,bind=[fd00:ec2::254],fork,reuseaddr"
" SYSTEM:'${lib.getExe imdsServer} /tmp/ipv6-metadata'"
)
# Serve metadata on the IPv6 IMDS address via socat + imds-server (inetd-style)
machine.succeed(
"systemd-run --unit=ipv6-imds --"
" socat TCP6-LISTEN:80,bind=[fd00:ec2::254],fork,reuseaddr"
" SYSTEM:'${lib.getExe imdsServer} /tmp/ipv6-metadata'"
)
# Wait for IPv6 IMDS to become reachable (token endpoint doesn't require auth)
machine.wait_until_succeeds(
"curl -sf -X PUT -H 'X-aws-ec2-metadata-token-ttl-seconds: 600'"
" http://[fd00:ec2::254]/latest/api/token"
)
# Wait for IPv6 IMDS to become reachable (token endpoint doesn't require auth)
machine.wait_until_succeeds(
"curl -sf -X PUT -H 'X-aws-ec2-metadata-token-ttl-seconds: 600'"
" http://[fd00:ec2::254]/latest/api/token"
)
# Block IPv4 IMDS to force fallback to IPv6
machine.succeed(
"iptables -I OUTPUT -d 169.254.169.254 -p tcp --dport 80 -j REJECT"
)
# Block IPv4 IMDS to force fallback to IPv6
machine.succeed(
"iptables -I OUTPUT -d 169.254.169.254 -p tcp --dport 80 -j REJECT"
)
# Verify IPv4 IMDS is now unreachable
machine.fail(
"curl -sf --connect-timeout 2 http://169.254.169.254/1.0/meta-data/hostname"
)
# Verify IPv4 IMDS is now unreachable
machine.fail(
"curl -sf --connect-timeout 2 http://169.254.169.254/1.0/meta-data/hostname"
)
# Clear fetched metadata and re-run the fetcher
machine.succeed("rm -f /etc/ec2-metadata/*")
machine.succeed("systemctl restart fetch-ec2-metadata")
# Clear fetched metadata and re-run the fetcher
machine.succeed("rm -f /etc/ec2-metadata/*")
machine.succeed("systemctl restart fetch-ec2-metadata")
# Verify metadata was successfully re-fetched via IPv6
hostname = machine.succeed("cat /etc/ec2-metadata/hostname").strip()
assert hostname == original_hostname, f"Expected '{original_hostname}', got '{hostname}'"
# Verify metadata was successfully re-fetched via IPv6
hostname = machine.succeed("cat /etc/ec2-metadata/hostname").strip()
assert hostname == original_hostname, f"Expected '{original_hostname}', got '{hostname}'"
# Clean up: restore IPv4 IMDS access
machine.succeed(
"iptables -D OUTPUT -d 169.254.169.254 -p tcp --dport 80 -j REJECT"
)
machine.succeed("systemctl stop ipv6-imds")
# Clean up: restore IPv4 IMDS access
machine.succeed(
"iptables -D OUTPUT -d 169.254.169.254 -p tcp --dport 80 -j REJECT"
)
machine.succeed("systemctl stop ipv6-imds")
finally:
machine.shutdown()
temp_dir.cleanup()
'';
finally:
machine.shutdown()
temp_dir.cleanup()
'';
}

View file

@ -1,83 +0,0 @@
{
lib,
pkgs,
mechanism,
...
}:
let
secret = ''
foo
bar
baz
'';
secret-file = "bar";
in
{
name = "qemu-vm-credentials-${mechanism}";
meta.maintainers = with lib.maintainers; [ arianvp ];
nodes = {
machine = {
virtualisation.credentials = {
secret = {
inherit mechanism;
text = secret;
};
secret-default-mechanism = {
text = "default-mechanism";
};
secret-file-nix-store = {
inherit mechanism;
source = pkgs.writeText "secret-file-nix-store" secret-file;
};
secret-file-host = {
inherit mechanism;
source = "./secret-file-host";
};
secret-file-host-binary = {
inherit mechanism;
source = "./secret-file-host-binary";
};
};
};
};
testScript = ''
import base64
secret_file_host = "baz"
# Binary data with null bytes, high bytes, and all sorts of problematic characters
secret_file_host_binary = bytes([
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, # null and control chars
0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
0xDE, 0xAD, 0xBE, 0xEF, # classic binary pattern
0xFF, 0xFE, 0xFD, 0xFC, # high bytes
0x00, 0x00, 0x00, 0x00, # multiple nulls
0x80, 0x81, 0x82, 0x83, # more high bytes
])
with open(machine.state_dir / "secret-file-host", "w") as f:
f.write(secret_file_host)
with open(machine.state_dir / "secret-file-host-binary", "wb") as f2:
f2.write(secret_file_host_binary)
# Test text credential
t.assertEqual(machine.succeed("systemd-creds --system cat secret").strip(), "foo\nbar\nbaz")
t.assertEqual(machine.succeed("systemd-creds --system cat secret-default-mechanism").strip(), "default-mechanism")
# Test credential from nix store
t.assertEqual(machine.succeed("systemd-creds --system cat secret-file-nix-store").strip(), "${secret-file}")
# Test credential from host file
t.assertEqual(machine.succeed("systemd-creds --system cat secret-file-host").strip(), secret_file_host)
# Test binary credential - verify exact binary content
result = machine.succeed("systemd-creds --system cat secret-file-host-binary --transcode=base64").strip()
expected = base64.b64encode(secret_file_host_binary).decode('ascii')
t.assertEqual(result, expected, f"Binary credential mismatch: got {result}, expected {expected}")
'';
}

View file

@ -1,15 +1,15 @@
{ pkgs, ... }:
{
name = "systemd-initrd-simple";
nodes.machine =
{ pkgs, ... }:
{
testing.initrdBackdoor = true;
boot.initrd.systemd.enable = true;
virtualisation.fileSystems."/".autoResize = true;
};
nodes.machine = {
testing.initrdBackdoor = true;
boot.initrd.systemd.enable = true;
virtualisation.fileSystems."/".autoResize = true;
};
testScript =
{ nodes, ... }:
# python
''
import subprocess
@ -43,7 +43,7 @@
oldAvail = machine.succeed("df --output=avail / | sed 1d")
machine.shutdown()
subprocess.check_call(["qemu-img", "resize", "vm-state-machine/machine.qcow2", "+1G"])
subprocess.check_call(["${nodes.machine.virtualisation.qemu.package}/bin/qemu-img", "resize", "vm-state-machine/machine.qcow2", "+1G"])
machine.start()
machine.switch_root()

View file

@ -0,0 +1,46 @@
{ lib, ... }:
{
name = "systemd-varlink";
meta.maintainers = [ lib.maintainers.raitobezarius ];
nodes.machine =
{ config, pkgs, ... }:
{
networking.useNetworkd = true;
services.resolved.enable = true;
systemd.network.enable = true;
};
testScript = ''
def list_interfaces(intf_path: str) -> list[str]:
return machine.succeed(f"varlinkctl list-interfaces {intf_path}").split('\n')
expected_reg_sd_interfaces = [
("BootControl", "bootctl"),
("Credentials", "creds"),
("Hostname", "hostnamed"),
("JournalAccess", "journald"),
("Import", "importd"),
("Machine", "machined"),
("Resolve", "resolved-varlink"),
("Resolve.Monitor", "resolved-monitor"),
("Udev", "udevd-varlink"),
("MuteConsole", "mute-console"),
("FactoryReset", "factory-reset"),
("AskPassword", "ask-password"),
("Network", "networkd-varlink"),
("Repart", "repart"),
]
expected_priv_sd_interfaces = [
("Login", None), # systemd-logind-varlink.socket exist but is not necessary.
]
expected_interfaces = [
(f"io.systemd.{intf}", f"systemd-{socket_name}", f"/run/varlink/registry/io.systemd.{intf}") for intf, socket_name in expected_reg_sd_interfaces
] + [
(f"io.systemd.{intf}", f"systemd-{socket_name}" if socket_name is not None else None, f"/run/systemd/io.systemd.{intf}") for intf, socket_name in expected_priv_sd_interfaces
]
for intf, socket_name, intf_path in expected_interfaces:
if socket_name is not None:
machine.wait_for_unit(f"{socket_name}.socket")
assert intf in list_interfaces(intf_path), f"Interface '{intf}' not found in the Varlink registry"
'';
}

View file

@ -38,21 +38,23 @@
services.journald.extraConfig = "Storage=volatile";
test-support.displayManager.auto.user = "alice";
systemd.shutdown.test = pkgs.writeScript "test.shutdown" ''
#!${pkgs.runtimeShell}
PATH=${
lib.makeBinPath (
with pkgs;
[
util-linux
coreutils
]
)
}
mount -t 9p shared -o trans=virtio,version=9p2000.L /tmp/shared
touch /tmp/shared/shutdown-test
umount /tmp/shared
'';
systemd.shutdownRamfs.contents."/etc/systemd/system-shutdown/test".source =
pkgs.writeShellScript "test.shutdown" ''
PATH=${
lib.makeBinPath (
with pkgs;
[
util-linux
coreutils
]
)
}
mkdir -p /tmp/shared
mount -t 9p shared -o trans=virtio,version=9p2000.L /tmp/shared
touch /tmp/shared/shutdown-test
umount /tmp/shared
'';
systemd.shutdownRamfs.storePaths = [ "${pkgs.util-linux}/bin" ];
systemd.services.oncalendar-test = {
description = "calendar test";
@ -147,7 +149,7 @@
subprocess.check_call(
[
"qemu-img",
"${nodes.machine.virtualisation.qemu.package}/bin/qemu-img",
"convert",
"-O",
"raw",

View file

@ -204,23 +204,23 @@ pkgs.lib.recurseIntoAttrs rec {
${nvim_with_plug}/bin/nvim -V3log.txt -i NONE -c 'color base16-tomorrow-night' +quit! -e
'';
nvim_with_autoconfigure = pkgs.neovim.overrideAttrs {
plugins = [
vimPlugins.unicode-vim
vimPlugins.fzf-hoogle-vim
];
nvim_with_autoconfigure = pkgs.neovim.override {
configure = {
packages.myPlugins.start = [
vimPlugins.unicode-vim
vimPlugins.fzf-hoogle-vim
];
};
autoconfigure = true;
# legacy wrapper sets it to false
wrapRc = true;
};
nvim_with_runtimeDeps = pkgs.neovim.overrideAttrs {
plugins = [
pkgs.vimPlugins.hex-nvim
];
nvim_with_runtimeDeps = pkgs.neovim.override {
configure = {
packages.myPlugins.start = [
pkgs.vimPlugins.hex-nvim
];
};
autowrapRuntimeDeps = true;
# legacy wrapper sets it to false
wrapRc = true;
};
nvim_with_ftplugin =

View file

@ -249,6 +249,9 @@ stdenv.mkDerivation (
})
];
strictDeps = true;
__structuredAttrs = true;
buildInputs = [
libsecret
]

View file

@ -209,13 +209,13 @@
"vendorHash": "sha256-rCWeetM6nhNb1I1PmB66E5K1ku9ODRqN87MU9y6W/dc="
},
"cloudflare_cloudflare": {
"hash": "sha256-y3GAU5wLLETSrmYqGZs2I0qg8jnGcu32Xt/UHGS1NTA=",
"hash": "sha256-SHEK/NJrs1ZkyDc8jSnb39dT/wX7ixSsHc//cwhTfz8=",
"homepage": "https://registry.terraform.io/providers/cloudflare/cloudflare",
"owner": "cloudflare",
"repo": "terraform-provider-cloudflare",
"rev": "v5.20.0",
"rev": "v5.21.1",
"spdx": "Apache-2.0",
"vendorHash": "sha256-LGibxg94dOiMfNynQfBoxQ6zR8A7xDfGNTujmEJcu14="
"vendorHash": "sha256-YLgIcohvOYBVt/GOkiqxdJVThhcphG2l8Lha1MwU9L4="
},
"cloudfoundry-community_cloudfoundry": {
"hash": "sha256-1nYncJLVU/f9WD6Quh9IieIXgixPzbPk4zbtI1zmf9g=",

View file

@ -15,6 +15,7 @@ let
baseAttrs = {
strictDeps = true;
enableParallelBuilding = true;
__structuredAttrs = true;
doCheck = true;
configurePhase = ''
runHook preConfigure

View file

@ -21,13 +21,13 @@ in
rustPlatform.buildRustPackage {
pname = "attic";
version = "0-unstable-2026-06-14";
version = "0-unstable-2026-06-26";
src = fetchFromGitHub {
owner = "zhaofengli";
repo = "attic";
rev = "6b22d76ca351c5a07a5e5a60b95bc23320f7e791";
hash = "sha256-sboz+gG8z0KX+q0kkvLloNcogXYLwiY5iw2xwN36rFo=";
rev = "b7c905657cb81b8ec9c26b0d9f53aa2e4f231810";
hash = "sha256-//gQFVLVFhwHyI9yrpPqX0MQJGYqS6nE/iLV872K+PU=";
};
nativeBuildInputs = [
@ -38,7 +38,7 @@ rustPlatform.buildRustPackage {
buildInputs = lib.optional needNixInclude nix ++ [ boost ];
cargoBuildFlags = lib.concatMapStrings (c: "-p ${c} ") crates;
cargoHash = "sha256-LqE4jOIasxIG4DAhgZJMlTSyt/a900QR06wBFtRNRO8=";
cargoHash = "sha256-fYWRlgP3uwntULe6o2MC1yB/ea2x+27m1Op7o2wUd+U=";
env = {
ATTIC_DISTRIBUTOR = "nixpkgs";

View file

@ -54,6 +54,8 @@ buildNimPackage rec {
# buildNimPackage hack
substituteInPlace ae.nimble \
--replace-fail '"main=auto-editor"' '"main"'
mv tests/unit.nim tests/tunit.nim # buildNimPackage expects tests to start with t
'';
nativeCheckInputs = [
@ -64,7 +66,7 @@ buildNimPackage rec {
checkPhase = ''
runHook preCheck
eval "nim r --nimcache:$NIX_BUILD_TOP/nimcache $nimFlags $src/tests/unit.nim"
nim_builder --phase:check
substituteInPlace tests/test.py \
--replace-fail '"./auto-editor"' "\"$out/bin/main\""

View file

@ -10,14 +10,14 @@
stdenvNoCC.mkDerivation (finalAttrs: {
pname = "blesh";
version = "0.4.0-devel3-unstable-2026-06-21";
version = "0.4.0-devel3-unstable-2026-06-27";
src = fetchFromGitHub {
owner = "akinomyoga";
repo = "ble.sh";
rev = "6cffa910eccce252fa391875c7c03c94fb6f1b09";
rev = "5d39ebe6db67a46de4195f8ce8186e34cd2618d1";
fetchSubmodules = true;
hash = "sha256-CUIHfK1m00p6rBBNp/XqXifeRcG7BKpkdF7kl4+2tZY=";
hash = "sha256-12aSZl0qx0CwaIq/U77pCFz9Ij2CrzhojQuBngc7oag=";
};
nativeBuildInputs = [
@ -28,10 +28,6 @@ stdenvNoCC.mkDerivation (finalAttrs: {
# Fix the cache invalidation not working; see
# https://github.com/NixOS/nixpkgs/pull/521218#issuecomment-4641313131
./fix-cache-invalidation.patch
# ble.sh reaches a runtime-dir fallback under the install base when the
# others are unusable (always on WSL); see
# https://github.com/NixOS/nixpkgs/pull/521218#issuecomment-4686973408
./skip-readonly-runtime-dir.patch
];
# ble.sh embeds the commit id, normally read from .git, which fetchFromGitHub omits.
@ -41,6 +37,10 @@ stdenvNoCC.mkDerivation (finalAttrs: {
"BLE_GIT_BRANCH=master"
];
postPatch = ''
patchShebangs --build make_command.sh make
'';
doCheck = true;
# auto-detection runs `make -n check` without makeFlags, which fails without BLE_GIT_COMMIT_ID
checkTarget = "check";

View file

@ -1,10 +0,0 @@
--- a/ble.pp
+++ b/ble.pp
@@ -1934,6 +1934,7 @@
function ble/base/initialize-runtime-directory/.base {
local tmp_dir=$_ble_base/run
if [[ ! -d $tmp_dir ]]; then
+ [[ -w $_ble_base ]] || return 1
ble/bin/mkdir -p "$tmp_dir" || return 1
ble/bin/chmod a+rwxt "$tmp_dir" || return 1
fi

View file

@ -0,0 +1,131 @@
{
lib,
python3Packages,
fetchFromGitHub,
nix-update-script,
writableTmpDirAsHomeHook,
}:
python3Packages.buildPythonApplication (finalAttrs: {
pname = "cai";
version = "1.1.5-unstable-2026-06-05";
pyproject = true;
__structuredAttrs = true;
src = fetchFromGitHub {
owner = "aliasrobotics";
repo = "cai";
rev = "1c79507140845d0c57455e3b623e489680fd80e8";
hash = "sha256-LcU9GoUulpeAaaBZr2Mg/C+UmjZ74UL+SGqdB0P9JtA=";
};
pythonRemoveDeps = [
"cryptography"
"dotenv"
"openinference-instrumentation-openai"
"pypdf2"
];
pythonRelaxDeps = [ "openai" ];
build-system = with python3Packages; [ hatchling ];
dependencies = with python3Packages; [
cryptography
curl-cffi
dnspython
docker
fastapi
flask
folium
graphviz
griffe
litellm
mako
matplotlib
mcp
mkdocs
mkdocs-material
nest-asyncio
networkx
numpy
numpy
openai
openinference-instrumentation-openai
pandas
paramiko
prompt-toolkit
pydantic
pypdf
python-dotenv
questionary
requests
rich
textual
trafilatura
types-requests
typing-extensions
wasabi
websockets
];
nativeInstallCheckInputs = with python3Packages; [
inline-snapshot
litellm
pytest-asyncio
pytestCheckHook
writableTmpDirAsHomeHook
];
pythonImportsCheck = [ "cai" ];
disabledTestPaths = [
# Exclude examples
"examples/"
# API key is required
"tests/agents/test_agent_inference.py"
"tests/agents/test_agent_one_tool.py"
"tests/agents/test_blue_teamer_gctr.py"
"tests/api/test_api.py"
"tests/cli/test_cli_headless_cancellation.py"
"tests/commands/"
"tests/integration/"
"tests/refusals/"
"tests/test_unified_pattern.py"
"tools/tpm_test.py"
# openai 2.x API changes
"tests/cli/test_cli_streaming.py"
"tests/core/test_openai_chatcompletions.py"
"tests/core/test_openai_chatcompletions_stream.py"
"tests/mcp/test_runner_calls_mcp.py"
"tests/tracing/test_agent_tracing.py"
"tests/tracing/test_responses_tracing.py"
"tests/tracing/test_tracing.py"
"tests/tracing/test_tracing_errors.py"
"tests/tracing/test_tracing_errors_streamed.py"
"tests/voice/test_workflow.py"
# Missing symbols (version mismatch)
"tests/core/test_auto_compact.py"
"tests/core/test_context_optimization.py"
# Probing the live interpreter outside sandbox
"tests/continuous_ops/test_wizard_worker_python_bin.py"
# Tests requires live CTF infrastructure
"tests/ctfs/test_ctf.py"
# Other error
"tests/test_cli_print_deduplication.py"
"tests/tools/test_output_tool.py"
"tests/util/test_wait_hints_compact.py"
];
passthru.updateScript = nix-update-script { };
meta = {
description = "Framework for AI Security";
homepage = "https://github.com/aliasrobotics/cai";
changelog = "https://github.com/aliasrobotics/cai/releases/tag/${finalAttrs.src.rev}";
license = lib.licenses.mit;
maintainers = with lib.maintainers; [ fab ];
mainProgram = "cai";
};
})

View file

@ -10,14 +10,14 @@
rustPlatform.buildRustPackage (finalAttrs: {
pname = "cargo-show-asm";
version = "0.2.59";
version = "0.2.62";
src = fetchCrate {
inherit (finalAttrs) pname version;
hash = "sha256-5RNfokTD86OFGzWRUyY29+d5P3sWWHmzGCGdIkzIK/g=";
hash = "sha256-gR1+Daz3EY6HtijWqbaCg6nD2B8gi6EYMYFspW39nlw=";
};
cargoHash = "sha256-EcnxozYMjxFHwLpeYwh5dP18+1tiPsY6uQBie3SCg18=";
cargoHash = "sha256-QpitYFYRkzntVW15PJimVIX6AaIU+qVY7g3Y88GnKkA=";
nativeBuildInputs = [
installShellFiles

View file

@ -18,13 +18,13 @@ let
in
stdenv.mkDerivation (finalAttrs: {
pname = "context7-mcp";
version = "3.2.1";
version = "3.2.2";
src = fetchFromGitHub {
owner = "upstash";
repo = "context7";
tag = "${tag-prefix}@${finalAttrs.version}";
hash = "sha256-Gf3GnVOceAMzsc1SYGQVriDzDD/dQYSoBSrCuQ5M4UI=";
hash = "sha256-v3zKMnZsc0gWVAdgZwFTskWcFVlOU6sG2i+qDwjx+dw=";
};
nativeBuildInputs = [

View file

@ -10,11 +10,11 @@
}:
stdenvNoCC.mkDerivation (finalAttrs: {
pname = "copilot-language-server";
version = "1.509.0";
version = "1.513.0";
src = fetchzip {
url = "https://github.com/github/copilot-language-server-release/releases/download/${finalAttrs.version}/copilot-language-server-js-${finalAttrs.version}.zip";
hash = "sha256-PY4pr9FHKHSJjNctq7bGlsZ1yvDM6IqbmfobI1WsDP0=";
hash = "sha256-wVibxZjUW6BX4YhdYlyE0/zp0fst2H/XmmqZLqxGXH8=";
stripRoot = false;
};

View file

@ -19,7 +19,7 @@
stdenvNoCC.mkDerivation (finalAttrs: {
pname = "dbeaver-bin";
version = "26.1.0";
version = "26.1.1";
src =
let
@ -32,10 +32,10 @@ stdenvNoCC.mkDerivation (finalAttrs: {
aarch64-darwin = "macos-aarch64.dmg";
};
hash = selectSystem {
x86_64-linux = "sha256-zAkHddh5xm9SHMV6OcJpl2A3+lS4GMJDbZ/+zg/5PzE=";
aarch64-linux = "sha256-0Tv45N+nZ2lRgn/Lo5HpPjuGigI0X2CJIIV96UO0bs8=";
x86_64-darwin = "sha256-INfXvR9FJZcruC8KeRtc0SIHUUHc0p3jjDNk4eBk7Lo=";
aarch64-darwin = "sha256-s+NQ5hp3NiQpJ/b3mp7Fdjh5rEmf1UnSz/Ai5Z43qEg=";
x86_64-linux = "sha256-atbQ00lq589FlNem85NgzTKGyhTRpFII8OSfVfYQuD0=";
aarch64-linux = "sha256-Sde0q31hXMqX2oxfhgj5EcpeUYYFZJy61usaJVpZkLM=";
x86_64-darwin = "sha256-EmTHuzEc4beM52hC2T7poZ1SOKa9kO2Rp3NnctlsBYo=";
aarch64-darwin = "sha256-PwuFwEE+aBEG/ykwNrEBl20yfrade8BdUUHdLJGBkwc=";
};
in
fetchurl {

View file

@ -5,13 +5,13 @@
}:
buildDubPackage (finalAttrs: {
pname = "ddhx";
version = "0.9.3";
version = "0.10.0";
src = fetchFromGitHub {
owner = "dd86k";
repo = "ddhx";
tag = "v${finalAttrs.version}";
hash = "sha256-7sXXkn/B9iN8Iq4X/Rj7BufdHKDBS1aG3pXcInG+UaI=";
hash = "sha256-1dbY7xUOpwihrppuB+tyHuV2b12E4Yv2J69LXULxmg0=";
};
dubLock = ./dub-lock.json;

View file

@ -7,16 +7,16 @@
buildNpmPackage rec {
pname = "defuddle";
version = "0.18.1";
version = "0.19.1";
src = fetchFromGitHub {
owner = "kepano";
repo = "defuddle";
tag = version;
hash = "sha256-e/+eigIzpP0g+ZqTeyZnF6mloaY6UeKcMWfqryCcLbM=";
hash = "sha256-Fn203XKjZ2qbM1o0zs6mgxCdjWLOwz9Na+s1WSQG9XM=";
};
npmDepsHash = "sha256-1NFwhYEGTKpjzCdK/eHK0TWtOEpn67FA+B3QZ11w1Rs=";
npmDepsHash = "sha256-quqWhbcaSNj4Bk++4N4LYq3Y8U5nQqnwc+MqU0LLgso=";
# jsdom is both a peerDependency and devDependency; pruning
# devDependencies removes it, but the CLI needs it at runtime.

View file

@ -0,0 +1,14 @@
{
"aarch64-darwin": {
"version": "3.3.18",
"vscodeVersion": "1.110.1",
"url": "https://windsurf-stable.codeiumdata.com/darwin-arm64/stable/16737566f57f3b53bde136375fe0544eca12fac4/Devin-darwin-arm64-3.3.18.zip",
"sha256": "7ac789baa5d818b09f6a62315d34b55dde02b0a409a22903d0228a819ea734e7"
},
"x86_64-linux": {
"version": "3.3.18",
"vscodeVersion": "1.110.1",
"url": "https://windsurf-stable.codeiumdata.com/linux-x64/stable/16737566f57f3b53bde136375fe0544eca12fac4/Devin-linux-x64-3.3.18.tar.gz",
"sha256": "05c7fa988c324a1633038ebe90e217d17a7f188197a5070f397460864ef41292"
}
}

View file

@ -16,15 +16,16 @@ buildVscode {
inherit commandLineArgs useVSCodeRipgrep;
inherit (info) version vscodeVersion;
pname = "windsurf";
executableName = "windsurf";
longName = "Windsurf";
shortName = "windsurf";
libraryName = "windsurf";
iconName = "windsurf";
pname = "devin-desktop";
sourceRoot = if stdenv.hostPlatform.isDarwin then "Windsurf.app" else "Windsurf";
executableName = "devin-desktop";
longName = "devin-desktop";
shortName = "devin-desktop";
libraryName = "devin-desktop";
iconName = "devin-desktop";
sourceRoot = if stdenv.hostPlatform.isDarwin then "Devin.app" else "Devin";
src = fetchurl { inherit (info) url sha256; };
@ -41,9 +42,9 @@ buildVscode {
description = "Agentic IDE powered by AI Flow paradigm";
longDescription = ''
The first agentic IDE, and then some.
The Windsurf Editor is where the work of developers and AI truly flow together, allowing for a coding experience that feels like literal magic.
Devin Desktop is where the work of developers and AI truly flow together, allowing for a coding experience that feels like literal magic.
'';
homepage = "https://codeium.com/windsurf";
homepage = "https://devin.ai/desktop";
license = lib.licenses.unfree;
maintainers = with lib.maintainers; [
sarahec
@ -51,7 +52,6 @@ buildVscode {
];
platforms = [
"aarch64-darwin"
"x86_64-darwin"
"x86_64-linux"
];
sourceProvenance = [ lib.sourceTypes.binaryBytecode ];

View file

@ -17,7 +17,7 @@ interface LatestInfo {
readonly productVersion: string;
}
const platforms = ["aarch64-darwin", "x86_64-darwin", "x86_64-linux"] as const;
const platforms = ["aarch64-darwin", "x86_64-linux"] as const;
type Platform = (typeof platforms)[number];
type InfoMap = Record<
Platform,
@ -29,7 +29,7 @@ type InfoMap = Record<
}
>;
async function getInfo(targetSystem: "darwin-arm64" | "darwin-x64" | "linux-x64") {
async function getInfo(targetSystem: "darwin-arm64" | "linux-x64") {
const url =
`https://windsurf-stable.codeium.com/api/update/${targetSystem}/stable/latest` as const;
@ -57,7 +57,6 @@ async function main() {
const info: InfoMap = {
"aarch64-darwin": await getInfo("darwin-arm64"),
"x86_64-darwin": await getInfo("darwin-x64"),
"x86_64-linux": await getInfo("linux-x64"),
};
if (JSON.stringify(oldInfo) === JSON.stringify(info)) {
@ -66,7 +65,7 @@ async function main() {
}
for (const platform of platforms) {
console.log(
`[update] Updating Windsurf ${platform} ${oldInfo[platform].version} -> ${info[platform].version}`,
`[update] Updating Devin Desktop ${platform} ${oldInfo[platform].version} -> ${info[platform].version}`,
);
}
await fsPromises.writeFile(
@ -74,7 +73,7 @@ async function main() {
JSON.stringify(info, null, 2) + "\n",
"utf-8",
);
console.log("[update] Updating Windsurf complete");
console.log("[update] Updating Devin Desktop complete");
}
if (process.argv[1] === __filename) {

View file

@ -9,7 +9,7 @@
installShellFiles,
makeWrapper,
esbuild,
wasm-bindgen-cli_0_2_118,
wasm-bindgen-cli_0_2_126,
testers,
dioxus-cli,
withTelemetry ? false,
@ -81,7 +81,7 @@ rustPlatform.buildRustPackage (finalAttrs: {
--suffix PATH : ${
lib.makeBinPath [
esbuild
wasm-bindgen-cli_0_2_118
wasm-bindgen-cli_0_2_126
]
}
'';

View file

@ -8,7 +8,7 @@
mpv-unwrapped,
fetchPnpmDeps,
pnpmConfigHook,
pnpm_10_29_2,
pnpm_10,
darwin,
actool,
copyDesktopItems,
@ -42,7 +42,7 @@ buildNpmPackage {
version
src
;
pnpm = pnpm_10_29_2;
pnpm = pnpm_10;
fetcherVersion = 3;
hash = "sha256-zNOGJ24G0xcgsGK4DmbBm7d1PHTp7IJS+RTALGRtfDg=";
};
@ -50,7 +50,7 @@ buildNpmPackage {
env.ELECTRON_SKIP_BINARY_DOWNLOAD = "1";
nativeBuildInputs = [
pnpm_10_29_2
pnpm_10
]
++ lib.optionals (stdenv.hostPlatform.isLinux) [ copyDesktopItems ]
++ lib.optionals stdenv.hostPlatform.isDarwin [

View file

@ -13,13 +13,13 @@
buildGoModule (finalAttrs: {
pname = "glab";
version = "1.101.0";
version = "1.105.0";
src = fetchFromGitLab {
owner = "gitlab-org";
repo = "cli";
tag = "v${finalAttrs.version}";
hash = "sha256-K8QL9Ff5FHmiXyBEdsUE8kwhSF0camSFh08LbfJb3wo=";
hash = "sha256-MKb46PHgm+jfHGf2rEh0o7ghtb6JR4UE3Mam9z+2gw8=";
leaveDotGit = true;
postFetch = ''
cd "$out"
@ -28,7 +28,7 @@ buildGoModule (finalAttrs: {
'';
};
vendorHash = "sha256-u1zvzMrQGyTVcl/lnIGK3dfisxGYRa2LGpDMBDq6rJk=";
vendorHash = "sha256-aFrTCqvxVaiEJFKa4zY0kFW1P6QDDD4UG5x+yHK6vZ8=";
ldflags = [
"-s"

View file

@ -9,13 +9,13 @@
}:
buildGoModule (finalAttrs: {
pname = "immich-go";
version = "0.31.0";
version = "0.32.0";
src = fetchFromGitHub {
owner = "simulot";
repo = "immich-go";
tag = "v${finalAttrs.version}";
hash = "sha256-u+laNZ0/UncwH+3Ylk7g40DB99dAbQRrBNOVk80FrMc=";
hash = "sha256-bMbLMlLZpzFP7Zh9kqWzEELt3MdOR8HMkH0gTU8qD9U=";
# Inspired by: https://github.com/NixOS/nixpkgs/blob/f2d7a289c5a5ece8521dd082b81ac7e4a57c2c5c/pkgs/applications/graphics/pdfcpu/default.nix#L20-L32
# The intention here is to write the information into files in the `src`'s
@ -32,7 +32,7 @@ buildGoModule (finalAttrs: {
'';
};
vendorHash = "sha256-C6IQ6g5vdGqv8mzdTzLicZqP5lh3l2uNH2gIZELNAHg=";
vendorHash = "sha256-BwrP+eG+XPcTAbSKhJk0BOrfBlNeLHEeRhq49ZkQhwY=";
# options used by upstream:
# https://github.com/simulot/immich-go/blob/v0.25.0/.goreleaser.yaml

View file

@ -5,6 +5,7 @@
fetchurl,
extraCommandLineArgs ? "",
useVSCodeRipgrep ? stdenv.hostPlatform.isDarwin,
_7zz,
}:
let
@ -31,7 +32,16 @@ in
url = sources.url;
hash = sources.hash;
};
sourceRoot = "Kiro";
# Kiro.dmg is APFS formatted, unpack with 7zz
extraNativeBuildInputs = lib.optionals stdenv.hostPlatform.isDarwin [ _7zz ];
sourceRoot = if stdenv.hostPlatform.isDarwin then "Kiro.app" else "Kiro";
sourceExecutableName = if stdenv.hostPlatform.isDarwin then "code" else "kiro";
dontFixup = stdenv.hostPlatform.isDarwin;
patchVSCodePath = true;
tests = { };

View file

@ -13,13 +13,13 @@
stdenv.mkDerivation (finalAttrs: {
pname = "linyaps-box";
version = "2.2.0";
version = "2.2.1";
src = fetchFromGitHub {
owner = "OpenAtom-Linyaps";
repo = "linyaps-box";
rev = finalAttrs.version;
hash = "sha256-s17BI5nftQFrDZQVKBJjQYSOJHDPlkA2VLG4Hd61xSY=";
hash = "sha256-KULNPztaDeO6Dih98KcnawMz2rDjQd6AYT9FgAADhIg=";
};
nativeBuildInputs = [

View file

@ -7,11 +7,11 @@
appimageTools.wrapType2 rec {
pname = "lunarclient";
version = "3.7.6";
version = "3.7.9";
src = fetchurl {
url = "https://launcherupdates.lunarclientcdn.com/Lunar%20Client-${version}-ow.AppImage";
hash = "sha512-+xC7hvpQfmXkZ+FndNAWIxgfWjodfdcCrHmPe5XqEC+3cBkT6KpOxvuw7o0qAebxo6VNN5tKuAPfibfZfeH+RQ==";
hash = "sha512-7rVPN/CmnaA91mnNQkuK4/pmPtHeLvsLeuzBlEBbRT2RrYtSxF3eEnHiFndlMzmRor8FWuFITz43QFPgFVMJpQ==";
};
nativeBuildInputs = [ makeWrapper ];

View file

@ -11,13 +11,13 @@
stdenv.mkDerivation (finalAttrs: {
pname = "manifold";
version = "3.5.1";
version = "3.5.2";
src = fetchFromGitHub {
owner = "elalish";
repo = "manifold";
tag = "v${finalAttrs.version}";
hash = "sha256-ZsTGokNpWDT0EgA3VaU/aMh8WtUygIqcSxzLikeyQ9c=";
hash = "sha256-jzVIQ90H90szzZSUWvqgBB+5UMgZ9I/uYhYJbexCifk=";
};
nativeBuildInputs = [ cmake ];

View file

@ -14,16 +14,16 @@ buildGoLatestModule (finalAttrs: {
__structuredAttrs = true;
pname = "matcha";
version = "0.40.1";
version = "0.43.0";
src = fetchFromGitHub {
owner = "floatpane";
repo = "matcha";
tag = "v${finalAttrs.version}";
hash = "sha256-4GbuiFFHQ14O+S2TtWiP1UWg3h6J9Cys6A8k5+0Ww/I=";
hash = "sha256-x+k1/k7pwJ0MW0t31ieaOkbP8LtqDSmHOBrNEGA0K6Q=";
};
vendorHash = "sha256-TFc7e7gNtFNiCJHARngWSBKGqGhH7PiX48VkU9kD9Bs=";
vendorHash = "sha256-5smWIw8ofG61ugHxFbmQ9r9vcxi098/UmxUE15lx4wE=";
proxyVendor = true;
nativeBuildInputs = lib.optionals stdenv.hostPlatform.isLinux [

View file

@ -12,16 +12,16 @@
}:
buildGoModule (finalAttrs: {
pname = "mgmt";
version = "1.0.2";
version = "1.1.0";
src = fetchFromGitHub {
owner = "purpleidea";
repo = "mgmt";
tag = finalAttrs.version;
hash = "sha256-nLk497gGrZ664VG9/yV6tqTtwAsN8EmuAEh5Vmq95hQ=";
hash = "sha256-jVFIVlytDvfTrAzWkX+pedAq/AcLrCDFtLPx0Wc+XjM=";
};
vendorHash = "sha256-w4j9cJwW2tnjXSnd3w3v81TwHI8tGYiImjG3LZ+Pjuc=";
vendorHash = "sha256-mMRAlqySy6dpRG86p0BHSpYn2gzE8N4sZ3qHiyuttBA=";
proxyVendor = true;

View file

@ -17,7 +17,9 @@
stdenv.mkDerivation (finalAttrs: {
pname = "mongodb-ce";
version = "8.2.7";
version = "8.2.11";
__structuredAttrs = true;
strictDeps = true;
src =
finalAttrs.passthru.sources.${stdenv.hostPlatform.system}
@ -49,23 +51,28 @@ stdenv.mkDerivation (finalAttrs: {
nativeInstallCheckInputs = [ versionCheckHook ];
versionCheckProgram = "${placeholder "out"}/bin/mongod";
# Apple's LibreSSL tries to read this while running `mongod --version`
sandboxProfile = lib.optionalString stdenv.hostPlatform.isDarwin ''
(allow file-read* (literal "/private/etc/ssl/openssl.cnf"))
'';
passthru = {
sources = {
"x86_64-linux" = fetchurl {
url = "https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-ubuntu2404-${finalAttrs.version}.tgz";
hash = "sha256-GYyWeVSoRXgrlQqx7R2chxH3+5S4ewbTefWJR9S2Frs=";
hash = "sha256-sqFkZ19eYZHQFwVX2zwaKaYXisvoqN25+8DFbyGU2H4=";
};
"aarch64-linux" = fetchurl {
url = "https://fastdl.mongodb.org/linux/mongodb-linux-aarch64-ubuntu2404-${finalAttrs.version}.tgz";
hash = "sha256-HTErVesWEWDjheedELdDOwlMrDvhV3JdVGtV3RuSeBI=";
hash = "sha256-5AX8pb1jInbQTuE0RqpqqcRXon6wKwdvoDCNDF70krE=";
};
"x86_64-darwin" = fetchurl {
url = "https://fastdl.mongodb.org/osx/mongodb-macos-x86_64-${finalAttrs.version}.tgz";
hash = "sha256-DeD/v+NP2b8BTReV80+Lz0O9t6e3O9+52sJmTK5NtVY=";
hash = "sha256-BLIFrmToU8tFHdjAD+0q827cyeDHoYiXwtsds6e7NMA=";
};
"aarch64-darwin" = fetchurl {
url = "https://fastdl.mongodb.org/osx/mongodb-macos-arm64-${finalAttrs.version}.tgz";
hash = "sha256-d8uulXczpq7ZEDmDsbb3o9kaZJ1IYzZ6MkgBLkNU4Mo=";
hash = "sha256-M3/x/d2rVKUmIZBQ9hVuT6W9ajZy/Ut5+8aDeXF+HwY=";
};
};
updateScript =

View file

@ -26,20 +26,20 @@ let
in
stdenv.mkDerivation (finalAttrs: {
pname = "n8n";
version = "2.25.7";
version = "2.27.4";
src = fetchFromGitHub {
owner = "n8n-io";
repo = "n8n";
tag = "n8n@${finalAttrs.version}";
hash = "sha256-V8CqEzCw4DcLPCao4HRXrJXFeID2+Ef8fNW1xd1b8Vs=";
hash = "sha256-Z8oAetoSJLTCO7UO+DrlSDFAIjLSLND9bQzrcLz0hYg=";
};
pnpmDeps = fetchPnpmDeps {
inherit (finalAttrs) pname version src;
pnpm = pnpm_10;
fetcherVersion = 3;
hash = "sha256-JS4OY6CmihsbJRyPszSlNUEViFKfLm2vu+G2upIoLW8=";
hash = "sha256-xTZlv8YZC8u9pzD/WroduyO2MVtRvZ7ajKTphsHfObs=";
};
nativeBuildInputs = [

View file

@ -31,11 +31,11 @@ let
in
stdenv.mkDerivation rec {
pname = "nano";
version = "9.0";
version = "9.1";
src = fetchurl {
url = "mirror://gnu/nano/${pname}-${version}.tar.xz";
hash = "sha256-nzhDdLSWEQoltzrVpf67OEeDxuMYizcGP2d6yQgBP94=";
url = "mirror://gnu/nano/nano-${version}.tar.xz";
hash = "sha256-X0d2QnTLdTI0nOCqIOwQ8ejoUabp+j62aBLEPRltsEI=";
};
nativeBuildInputs = [ texinfo ] ++ lib.optional enableNls gettext;

View file

@ -6,16 +6,16 @@
}:
buildGoModule (finalAttrs: {
pname = "oh-my-posh";
version = "29.18.0";
version = "29.19.0";
src = fetchFromGitHub {
owner = "jandedobbeleer";
repo = "oh-my-posh";
tag = "v${finalAttrs.version}";
hash = "sha256-A01LX+UvPlnQy/GoRoLVIBl8TrIB6XGjvpr3fCB5Jsg=";
hash = "sha256-KhE0JWOY9j4rSmVZOmUxC9pQbjSpISph+6RyntlryFs=";
};
vendorHash = "sha256-cuVkJjaeLBECeEBPSB1hyRcBs4AhXkG4br0ehjZ0pjI=";
vendorHash = "sha256-SI2FjnRlWSsS9Uju8R+FW6/IpqewXsiOwKXfueZ7KPY=";
sourceRoot = "${finalAttrs.src.name}/src";

View file

@ -1,14 +1,14 @@
{
version = "1.81.0";
version = "1.82.1";
hashes = {
linux-aarch_64 = "sha256-BhO92wlj0L3M8H4CGuB4NRZkjN9zPuFM/E2NAkn6d1o=";
linux-ppcle_64 = "sha256-Y1YC+C/AxdYiB7gcaerVhE383+8rPOiEI8+r/BxkeXk=";
linux-s390_64 = "sha256-cVjZl+ju8e+yroYOttrgIBGSBWDPw1jz1dOLdr58Bmc=";
linux-x86_32 = "sha256-I10buzyicR0aVI3BKDvtly6NwfjSP2hLOD1eY5NJFZc=";
linux-x86_64 = "sha256-T3WWxgoTdSS1TysR2Vb6IA8/6XZ43hzd2CfRCVQlD30=";
osx-aarch_64 = "sha256-c359UvEa+J85KV6KFOXMuUWCYmyB5VkTfmLfj8J81qQ=";
osx-x86_64 = "sha256-c359UvEa+J85KV6KFOXMuUWCYmyB5VkTfmLfj8J81qQ=";
windows-x86_32 = "sha256-mMRY0dLrPpLcQUeK5GqeOrBFqlghBC7FgqqoRWHdjYs=";
windows-x86_64 = "sha256-18mnbuYxoqnQLYHPWC2m2+TW5pJmX/O2OkQLG5xyND0=";
linux-aarch_64 = "sha256-VTDKjBMzFj5CocdqK1EEIOBsdTIckXMrNGOlRyByCc8=";
linux-ppcle_64 = "sha256-/NCzmrhbTDaYhJBntW6n6yA5tvtsvdVldMlK7WfV6RY=";
linux-s390_64 = "sha256-Bk83rw8iGsniyNcivgQRjx/GOWB0kv4Wo01b4YTG0Pk=";
linux-x86_32 = "sha256-Ai7h2w1ZGWlS/tAdiT/dpd6wt3VM4rpPiQuv5rDbfCY=";
linux-x86_64 = "sha256-OnXRqIuP5E9KHVy48ixz+PzI1WOu2QV/9epISyLNry8=";
osx-aarch_64 = "sha256-hm3WySlSQu/J5rg8pWlpOStcPnODqn1b7pKL1N5CkSQ=";
osx-x86_64 = "sha256-hm3WySlSQu/J5rg8pWlpOStcPnODqn1b7pKL1N5CkSQ=";
windows-x86_32 = "sha256-CWZAubE98Aftf7Mjd2caROxsWSxS+JQGf4YB+FEwiwo=";
windows-x86_64 = "sha256-XmhjMhJ/djRizOkSh+i7PtZn2RL9jVV5PcBkgwpYw0o=";
};
}

View file

@ -14,12 +14,12 @@
}:
buildGo126Module (finalAttrs: {
pname = "qui";
version = "1.20.0";
version = "1.21.0";
src = fetchFromGitHub {
owner = "autobrr";
repo = "qui";
tag = "v${finalAttrs.version}";
hash = "sha256-h1OIz+4oVuHg7bKWSKgkEwouX1oJKJmOC1VI+nrPwmI=";
hash = "sha256-3LExp17AGxZjAXXF0GoiTW7I1wluZf3uoZnXNF6WNYg=";
};
qui-web = stdenvNoCC.mkDerivation (finalAttrs': {
@ -44,7 +44,7 @@ buildGo126Module (finalAttrs: {
;
pnpm = pnpm_11;
fetcherVersion = 4;
hash = "sha256-nSlW06//r/olVgSBgHc8LGWWfNXewAF5cZXfoZemC+w=";
hash = "sha256-53bj1QlfihIyKsQK5o3FsA9qWZJrNPWEJ441UK9nWR0=";
};
postBuild = ''
@ -56,7 +56,7 @@ buildGo126Module (finalAttrs: {
'';
});
vendorHash = "sha256-4HQOoBDjV3Pt4O/KMu8c3aeUB5evceIdlAnsixO1Pjs=";
vendorHash = "sha256-n+CCRQk46j/ljAfFap3mgwxs4JF9Qr/TLqZILghgbU4=";
preBuild = ''
cp -r ${finalAttrs.qui-web}/* web/dist

View file

@ -8,16 +8,16 @@
buildNpmPackage rec {
pname = "repomix";
version = "1.14.0";
version = "1.15.0";
src = fetchFromGitHub {
owner = "yamadashy";
repo = "repomix";
tag = "v${version}";
hash = "sha256-xvRCblm7WRvxFBjsxe3AjvLt8AvL4Q9F6SQuOv39ADA=";
hash = "sha256-M96q1oJ2ipDMfeos5P0FBbngjStC86qBlQcRFXitkt4=";
};
npmDepsHash = "sha256-Pw2/w0rn5UloUqPZrze2l1Qi7JEdAXxlpPm7dxEHzWU=";
npmDepsHash = "sha256-3AP+mMFipVUfO7vLY7ZjaJ8FG4uwpxC2+jYtaHz49YI=";
nativeInstallCheckInputs = [ versionCheckHook ];
doInstallCheck = true;

View file

@ -0,0 +1,39 @@
{
lib,
buildGoModule,
fetchFromGitHub,
versionCheckHook,
nix-update-script,
}:
buildGoModule (finalAttrs: {
pname = "reticulum-group-chat";
version = "1.11.0";
__structuredAttrs = true;
__darwinAllowLocalNetworking = true;
src = fetchFromGitHub {
owner = "thatSFguy";
repo = "reticulum-group-chat";
tag = "v${finalAttrs.version}";
hash = "sha256-LWHYIKnkEPrlDIEruP2ctuMQGnrL1uofOWAsZ4E5guw=";
};
vendorHash = "sha256-qMmEi7OYv2xzYOoeBWQ0omeIrcTyhxylw2qvv9kd9dk=";
ldflags = [ "-s" ];
doInstallCheck = true;
nativeInstallCheckInputs = [ versionCheckHook ];
passthru.updateScript = nix-update-script { };
meta = {
description = "Pure-Go LXMF group-chat hub for the Reticulum network a single static binary that relays many-to-many encrypted text chat over LoRa, TCP/IP, and mixed meshes. No Python, no third-party RNS library";
homepage = "https://github.com/thatSFguy/reticulum-group-chat";
changelog = "https://github.com/thatSFguy/reticulum-group-chat/releases/tag/${finalAttrs.src.tag}";
license = lib.licenses.mit;
maintainers = with lib.maintainers; [ drupol ];
mainProgram = "fwdsvc";
};
})

View file

@ -16,7 +16,7 @@
rustPlatform.buildRustPackage (finalAttrs: {
pname = "ruff";
version = "0.15.18";
version = "0.15.20";
__structuredAttrs = true;
@ -24,12 +24,12 @@ rustPlatform.buildRustPackage (finalAttrs: {
owner = "astral-sh";
repo = "ruff";
tag = finalAttrs.version;
hash = "sha256-DH00tENXdCdNcGPXPGzZsU3RVYQ0VBe1QLvbgEg/G6k=";
hash = "sha256-8PFMGKG15kWBpG4YXg37940WtSe/e5pQDqIe3iJRh5A=";
};
cargoBuildFlags = [ "--package=ruff" ];
cargoHash = "sha256-RmK14NMPbhoRVLwIF5GXdGQg2AnMH20JGx7XF4HO+wY=";
cargoHash = "sha256-Bf6nsUnNMYapP0YN0SBkTPoP1czmj35tPwN1awyKhUw=";
nativeBuildInputs = [ installShellFiles ];

View file

@ -65,7 +65,12 @@ stdenv.mkDerivation (finalAttrs: {
./node_modules/.bin/electron-builder --dir \
--c.electronDist=electron-dist \
--c.electronVersion=${electron.version}
--c.electronVersion=${electron.version} \
${lib.optionalString stdenv.hostPlatform.isDarwin ''
--c.npmRebuild=false \
--c.mac.identity=null \
--c.mac.notarize=false \
''}
runHook postBuild
'';
@ -73,6 +78,8 @@ stdenv.mkDerivation (finalAttrs: {
installPhase = ''
runHook preInstall
''
+ lib.optionalString (!stdenv.hostPlatform.isDarwin) ''
mkdir -p "$out/share/lib/shiru"
cp -r dist/*-unpacked/{locales,resources{,.pak}} "$out/share/lib/shiru"
@ -82,7 +89,18 @@ stdenv.mkDerivation (finalAttrs: {
--add-flags "$out/share/lib/shiru/resources/app.asar" \
--prefix LD_LIBRARY_PATH : "${lib.makeLibraryPath [ stdenv.cc.cc.lib ]}" \
--inherit-argv0
''
+ lib.optionalString stdenv.hostPlatform.isDarwin ''
mkdir -p "$out/Applications"
cp -r dist/mac*/Shiru.app "$out/Applications/"
mkdir -p "$out/bin"
makeWrapper \
"$out/Applications/Shiru.app/Contents/MacOS/Shiru" \
"$out/bin/shiru" \
--set-default ELECTRON_IS_DEV 0
''
+ ''
runHook postInstall
'';
@ -116,7 +134,10 @@ stdenv.mkDerivation (finalAttrs: {
maintainers = with lib.maintainers; [
naomieow
];
platforms = [ "x86_64-linux" ];
platforms = [
"x86_64-linux"
"aarch64-darwin"
];
mainProgram = "shiru";
};
})

View file

@ -8,16 +8,16 @@
buildGoModule (finalAttrs: {
pname = "sif";
version = "0-unstable-2026-06-11";
version = "0-unstable-2026-06-23";
src = fetchFromGitHub {
owner = "vmfunc";
repo = "sif";
rev = "d62919523abfecd06e07ba6528b15e9861bd747c";
hash = "sha256-T/HIvcXG3OpSK7xhZpYnCWv4KsRn0bnLhyouPjgwUoE=";
rev = "39b333320eab64f22392b2494a7cd18462d42b29";
hash = "sha256-1WdjmCxhd37gkb/HbgUfFZkcFumCMDQKAyG5nvfGAMU=";
};
vendorHash = "sha256-rOAubGbeDPl0LJovksKRfYJmUvU6hmx3Ht12M7eLiOA=";
vendorHash = "sha256-R47Qz5tty+qvJKcWYMGZKYyRvpxN+mOdudT+cpUCT4s=";
subPackages = [ "cmd/sif" ];

View file

@ -15,7 +15,6 @@ buildNimPackage (finalAttrs: {
hash = "sha256-Qgvq4CkGvNppYFpITCCifOHtVQYRQJPEK3rTJXQkTvI=";
};
strictDeps = true;
lockFile = ./lock.json;
nimFlags = [ "-d:nimraylib_now_shared" ];

View file

@ -8,13 +8,13 @@
buildGoModule (finalAttrs: {
pname = "syft";
version = "1.45.1";
version = "1.46.0";
src = fetchFromGitHub {
owner = "anchore";
repo = "syft";
tag = "v${finalAttrs.version}";
hash = "sha256-JYMauarf2GB6ZJXB5pDZAcYZFJXWqEkULF3KIE8WvJQ=";
hash = "sha256-gjVfsJQoE//u0i6lVQCEF2dSUvoepIOaqqCazOUgSwI=";
# populate values that require us to use git. By doing this in postFetch we
# can delete .git afterwards and maintain better reproducibility of the src.
leaveDotGit = true;
@ -29,7 +29,7 @@ buildGoModule (finalAttrs: {
# hash mismatch with darwin
proxyVendor = true;
vendorHash = "sha256-KjbxAhjIb8h4F6kXfa38qUwWloK/3Rh6YU8G7rMIOtw=";
vendorHash = "sha256-t4L+Q82ohwBEXVh1Yy7OOrNhinnAXzOHO7mmFJQUZYM=";
nativeBuildInputs = [ installShellFiles ];

View file

@ -7,14 +7,14 @@
}:
python3Packages.buildPythonApplication {
pname = "tabbyapi";
version = "0-unstable-2026-06-13";
version = "0-unstable-2026-06-27";
pyproject = true;
src = fetchFromGitHub {
owner = "theroyallab";
repo = "tabbyAPI";
rev = "54850882315d509c984f9fe07fb8f5d04a0b4ba9";
hash = "sha256-rIpI3pCJtfU1AEHBwQCIwuOh4c14N/z8VlX0hdxOC60=";
rev = "3cf468c28362c28be1c8fc731ce1ccaf7b2206d0";
hash = "sha256-s97YFyij2/oYlClmV2laDrCkkoK4uVZgRsn5WwftLag=";
};
build-system = with python3Packages; [

View file

@ -5,16 +5,16 @@
}:
rustPlatform.buildRustPackage rec {
pname = "telemt";
version = "3.4.18";
version = "3.4.19";
src = fetchFromGitHub {
owner = "telemt";
repo = "telemt";
tag = version;
hash = "sha256-++EO+gkr6q+y8e0uwYyD04cFGyhwS2DW4JON4LOx0s0=";
hash = "sha256-3Vpz61/mEQ43zOEUtUBQw16D/LBvWymreJp4q1uDydM=";
};
cargoHash = "sha256-n25cjncocDv5gNftqv4TO0HRCoZEakiGzfLZqvT1ya4=";
cargoHash = "sha256-uQVL4k+/6L2vUTWbpTC9RvWQHC84P5fuCSrBLtoDdz8=";
checkFlags = [
# flaky: races between MiddleClientWriterCancelled and TrafficBudgetWaitCancelled observation paths

View file

@ -4,7 +4,7 @@
fetchFromGitHub,
makeWrapper,
nodejs-slim,
pnpm_9,
pnpm_10,
fetchPnpmDeps,
pnpmConfigHook,
versionCheckHook,
@ -29,13 +29,13 @@
}:
stdenv.mkDerivation (finalAttrs: {
pname = "textlint";
version = "15.2.1";
version = "15.7.1";
src = fetchFromGitHub {
owner = "textlint";
repo = "textlint";
tag = "v${finalAttrs.version}";
hash = "sha256-xjtmYz+O+Sn697OrBkPddv1Ma5UsOkO5v4SGlhsaYWA=";
hash = "sha256-Dt0AprnI/ixezMwU6JG6WhfJTU1xTRu2M4xwbY4uOko=";
};
patches = [
@ -57,16 +57,16 @@ stdenv.mkDerivation (finalAttrs: {
src
patches
;
pnpm = pnpm_9;
fetcherVersion = 3;
hash = "sha256-TYMhAcmfWHbj/0yLNYiJXWd1GiYb+zqBLj2/83cGbzg=";
pnpm = pnpm_10;
fetcherVersion = 4;
hash = "sha256-dWcLm8cTo8LC6IqMEe1zDxVJ7ioytKigEwYna6hiO8A=";
};
nativeBuildInputs = [
makeWrapper
nodejs-slim
pnpmConfigHook
pnpm_9
pnpm_10
];
buildPhase = ''

View file

@ -1,10 +1,10 @@
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 1f0e8f8b..68a9c06a 100644
index 9ee6370f6..552beed1b 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -4,9 +4,6 @@ settings:
autoInstallPeers: true
excludeLinksFromLockfile: false
@@ -295,9 +295,6 @@ catalogs:
specifier: ^3.25.76
version: 3.25.76
-overrides:
- '@textlint/ast-node-types': workspace:*
@ -12,3 +12,15 @@ index 1f0e8f8b..68a9c06a 100644
importers:
.:
diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml
index 300a519e0..bf41d5370 100644
--- a/pnpm-workspace.yaml
+++ b/pnpm-workspace.yaml
@@ -130,7 +130,5 @@ minimumReleaseAgeExclude:
# Force all @textlint/ast-node-types references to use the workspace version
# This prevents version conflicts where some packages might reference old versions (e.g., 13.4.1)
# that cause TypeScript type incompatibility errors in monorepo
-overrides:
- "@textlint/ast-node-types": "workspace:*"
# https://pnpm.io/settings#verifydepsbeforerun
verifyDepsBeforeRun: "install"

View file

@ -17,7 +17,7 @@
rustPlatform.buildRustPackage (finalAttrs: {
pname = "ty";
version = "0.0.52";
version = "0.0.54";
__structuredAttrs = true;
src = fetchFromGitHub {
@ -25,7 +25,7 @@ rustPlatform.buildRustPackage (finalAttrs: {
repo = "ty";
tag = finalAttrs.version;
fetchSubmodules = true;
hash = "sha256-p9fTzQ4DYvnwrtLdpSTekBV4ZbR1KETR8dfsbp8CDpo=";
hash = "sha256-hbVH0dCUHkWKD9IG/CYhYI4TfLgpk++tPOkCD36eVSg=";
};
# For Darwin platforms, remove the integration test for file notifications,
@ -39,7 +39,7 @@ rustPlatform.buildRustPackage (finalAttrs: {
cargoBuildFlags = [ "--package=ty" ];
cargoHash = "sha256-NUIdYOeyRsR/ZQueEXshYdWTnSeQiRjZRRi2ag8Dm48=";
cargoHash = "sha256-Bf6nsUnNMYapP0YN0SBkTPoP1czmj35tPwN1awyKhUw=";
nativeBuildInputs = [ installShellFiles ];
buildInputs = [ rust-jemalloc-sys ];

View file

@ -0,0 +1,19 @@
{
buildWasmBindgenCli,
fetchCrate,
rustPlatform,
}:
buildWasmBindgenCli rec {
src = fetchCrate {
pname = "wasm-bindgen-cli";
version = "0.2.126";
hash = "sha256-H6Is3fiZVxZCfOMWK5dWMSrtn50VGv0sfdnsT+cTtyk=";
};
cargoDeps = rustPlatform.fetchCargoVendor {
inherit src;
inherit (src) pname version;
hash = "sha256-VucqkXbCi4qtQzY/HrXiDnbSURsagPsdNVMn1Tw3UiY=";
};
}

View file

@ -21,6 +21,7 @@
libxml2,
systemd,
unzip,
vte-gtk4,
nix-update-script,
fetchpatch,
}:
@ -83,6 +84,7 @@ python3Packages.buildPythonApplication {
libadwaita
libxml2
systemd
vte-gtk4
];
dontUseCmakeConfigure = true;

View file

@ -1,20 +0,0 @@
{
"aarch64-darwin": {
"version": "2.3.9",
"vscodeVersion": "1.110.1",
"url": "https://windsurf-stable.codeiumdata.com/darwin-arm64/stable/a5d3f1ff990cabc0e8001cce6642bdb7ad429e73/Windsurf-darwin-arm64-2.3.9.zip",
"sha256": "35b11cd7307588fa11d4ec4690c2a5da8639e37659d68939e3a1dd46d9a105e3"
},
"x86_64-darwin": {
"version": "2.3.9",
"vscodeVersion": "1.110.1",
"url": "https://windsurf-stable.codeiumdata.com/darwin-x64/stable/a5d3f1ff990cabc0e8001cce6642bdb7ad429e73/Windsurf-darwin-x64-2.3.9.zip",
"sha256": "63a515c68f322653b901f1472184ca688102f9b8c0b598dec590eb648ead4211"
},
"x86_64-linux": {
"version": "2.3.9",
"vscodeVersion": "1.110.1",
"url": "https://windsurf-stable.codeiumdata.com/linux-x64/stable/a5d3f1ff990cabc0e8001cce6642bdb7ad429e73/Windsurf-linux-x64-2.3.9.tar.gz",
"sha256": "874024744cd853b7c350fe514be19b0060fac39586253c3b7602d6869473eadc"
}
}

View file

@ -8,11 +8,11 @@
stdenv.mkDerivation (finalAttrs: {
pname = "workcraft";
version = "3.5.4";
version = "3.5.5";
src = fetchurl {
url = "https://github.com/workcraft/workcraft/releases/download/v${finalAttrs.version}/workcraft-v${finalAttrs.version}-linux.tar.gz";
hash = "sha256-+G4Z9GfyfdBL3qb8RqtmRPq6wC6et4P3S6Owy/L5sSU=";
hash = "sha256-zpuwNwVu9iH7JSHsSyGt3gl6swOHa2b9uDC8Ck2Mtno=";
};
nativeBuildInputs = [ makeWrapper ];

View file

@ -5,13 +5,13 @@
}:
mkYaziPlugin {
pname = "toggle-pane.yazi";
version = "0-unstable-2026-05-07";
version = "0-unstable-2026-06-26";
src = fetchFromGitHub {
owner = "yazi-rs";
repo = "plugins";
rev = "4ffa48f33465c22cce48c5d506295a3eb27c1979";
hash = "sha256-wr5QL493A175dRjYSyYpMMJax1RKWaZ3jAdFdL3XXTw=";
rev = "39aaf6dc77e546fe7f7836f102a6c57f96d15365";
hash = "sha256-rl8EA8aymVQU1296IVsEZ2WR9xBxQTYBK+VUCic/K3k=";
};
meta = {

View file

@ -1040,15 +1040,15 @@ final: prev: {
}:
buildLuarocksPackage {
pname = "fzf-lua";
version = "0.0.2658-1";
version = "0.0.2661-1";
knownRockspec =
(fetchurl {
url = "mirror://luarocks/fzf-lua-0.0.2658-1.rockspec";
sha256 = "1dibv791x3yvw4ib56661r4g1v0lmfbwssj0x0jbwsjwnrnqis14";
url = "mirror://luarocks/fzf-lua-0.0.2661-1.rockspec";
sha256 = "0gw3q50zxawk81bnaxpj9n9n6fvv9qmyykvnxlha33bz0wvc13cq";
}).outPath;
src = fetchzip {
url = "https://github.com/ibhagwan/fzf-lua/archive/267f5db2aa2202b9f6cc7a50783f0ccd2121766c.zip";
sha256 = "1a4yy3wj0xq0jyrx8qnj6i29v5c8vvi52sbrk8112xy66qlysmm8";
url = "https://github.com/ibhagwan/fzf-lua/archive/b6f0392fe1645973c795b5bbbd8d6db466a5a25a.zip";
sha256 = "17mr5nnsx86isk8zqknpc172hpg86nxvmplcwwnk67qg1y8a8jwa";
};
disabled = luaOlder "5.1";
@ -1137,15 +1137,15 @@ final: prev: {
}:
buildLuarocksPackage {
pname = "grug-far.nvim";
version = "1.6.71-1";
version = "1.6.72-1";
knownRockspec =
(fetchurl {
url = "mirror://luarocks/grug-far.nvim-1.6.71-1.rockspec";
sha256 = "1gvwjg617qimb8i737hvdr423py7ry8c0lsna9chpxaks3j0cf4n";
url = "mirror://luarocks/grug-far.nvim-1.6.72-1.rockspec";
sha256 = "1ky24vksn0wvv058pvv03r163ba07s8b051mwi99qna2y77js2ds";
}).outPath;
src = fetchzip {
url = "https://github.com/MagicDuck/grug-far.nvim/archive/c995bbacf8229dc096ec1c3d60f8531059c86c1b.zip";
sha256 = "15wv6hvkiqi0rdg59y7dgaz7g6nz3141fdmkdggrc1h8aadky9zr";
url = "https://github.com/MagicDuck/grug-far.nvim/archive/c69859c1d5427ab5fc7ed12380ab521b4e336691.zip";
sha256 = "0yp64zp64zk5skf3blx359dmchy9wwfv4nf30hhdagvm8phbkkpx";
};
disabled = luaOlder "5.1";
@ -1322,15 +1322,15 @@ final: prev: {
}:
buildLuarocksPackage {
pname = "kulala.nvim";
version = "6.15.3-1";
version = "6.17.0-1";
knownRockspec =
(fetchurl {
url = "mirror://luarocks/kulala.nvim-6.15.3-1.rockspec";
sha256 = "00ghq3ph0vykphhiilj2k8643hdm5glz3h9iwpnsbahpgwpwppzy";
url = "mirror://luarocks/kulala.nvim-6.17.0-1.rockspec";
sha256 = "1m2i088p9gdkvh2s1pgzwq7j2wi2n97k2qdwggi5g22c20ph9370";
}).outPath;
src = fetchzip {
url = "https://github.com/mistweaverco/kulala.nvim/archive/v6.15.3.zip";
sha256 = "1friyckh8bxsixsql1r3h1ljfr3a13w061hnw5z7rj92inyx5536";
url = "https://github.com/mistweaverco/kulala.nvim/archive/v6.17.0.zip";
sha256 = "03iilwmi10v6d849nxi47rgfg65qzir4h7h28iw2ga3l3f33h2gy";
};
disabled = luaOlder "5.1";
@ -4712,21 +4712,21 @@ final: prev: {
}:
buildLuarocksPackage {
pname = "mini.test";
version = "0.17.0-1";
version = "0.18.0-1";
knownRockspec =
(fetchurl {
url = "mirror://luarocks/mini.test-0.17.0-1.rockspec";
sha256 = "0k9qvizfb3if0r20zid8had91ckkfy061lznvmi4r9hyy421dwfw";
url = "mirror://luarocks/mini.test-0.18.0-1.rockspec";
sha256 = "0k0pdp5qalfhcmdaqi0mz3s0p7rwq88bjcs6b7s5z80rqrhji67k";
}).outPath;
src = fetchzip {
url = "https://github.com/echasnovski/mini.test/archive/v0.17.0.zip";
sha256 = "0hffg59cn8dlhnjnkcfs9vannf10n2j33lna2d8zbaxajxaa8jks";
url = "https://github.com/nvim-mini/mini.test/archive/v0.18.0.zip";
sha256 = "1q1qy3f0mxrqx96gq4q3h4w2qip40lqkyd9vs65zc76wj9wx37hw";
};
disabled = luaOlder "5.1";
meta = {
homepage = "https://github.com/echasnovski/mini.test";
homepage = "https://github.com/nvim-mini/mini.test";
license = lib.licenses.mit;
description = "Test neovim plugins. Part of the mini.nvim suite.";
};
@ -5937,7 +5937,6 @@ final: prev: {
buildLuarocksPackage,
fetchFromGitHub,
fetchurl,
inspect,
ltreesitter,
lua-cjson,
luafilesystem,
@ -5947,22 +5946,21 @@ final: prev: {
}:
buildLuarocksPackage {
pname = "teal-language-server";
version = "0.1.3-1";
version = "0.1.4-1";
knownRockspec =
(fetchurl {
url = "mirror://luarocks/teal-language-server-0.1.3-1.rockspec";
sha256 = "1mqg294rgzcfbfam0qdab3z93j7gsx250hs9f271337gqki34848";
url = "mirror://luarocks/teal-language-server-0.1.4-1.rockspec";
sha256 = "0hgjlpyc90r3m4n4y6k8vjf5cdkv1q5b1mrfc31pssrhfwplq5hq";
}).outPath;
src = fetchFromGitHub {
owner = "teal-language";
repo = "teal-language-server";
tag = "0.1.3";
hash = "sha256-XuHm6AbcBmv0fyQjlJlBMWqJlGYoveW7BEEN+axMRhw=";
tag = "0.1.4";
hash = "sha256-5SdKjE690zxLAl2Kwcy2Bk49KUrpkYBPviK+mrQnMec=";
};
propagatedBuildInputs = [
argparse
inspect
ltreesitter
lua-cjson
luafilesystem
@ -6034,8 +6032,8 @@ final: prev: {
src = fetchFromGitHub {
owner = "nvim-telescope";
repo = "telescope.nvim";
rev = "9377230aa5305d9e9aca4ed8dadf1070fb4aa9fc";
hash = "sha256-iFHYx+5Rf3ol7CjVLjqVu+VNjdGfeC8V8nS/1THO+cQ=";
rev = "427b576c16792edad01a92b89721d923c19ad60f";
hash = "sha256-/GycCrepwDer0UvBN/f84pJUSvNp+ZfTIUPv0psl+IQ=";
};
disabled = lua.luaversion != "5.1";

View file

@ -1178,9 +1178,9 @@ in
'';
postConfigure = (old.postConfigure or "") + ''
substituteInPlace ''${rockspecFilename} \
--replace-fail '"ltreesitter == 0.1.0",' '"ltreesitter >= 0.2.0",' \
--replace-fail '"luv == 1.51.0",' '"luv >= 1.51.0",' \
--replace-fail '"tl == 0.24.5",' '"tl >= 0.24.5",'
--replace-fail '"ltreesitter == 0.3.0",' '"ltreesitter >= 0.3.0",' \
--replace-fail '"luv == 1.52.1",' '"luv >= 1.52.1",' \
--replace-fail '"tl == 0.24.8",' '"tl >= 0.24.8",'
'';
});

View file

@ -11,7 +11,7 @@
buildPythonPackage (finalAttrs: {
pname = "alibabacloud-ram20150501";
version = "1.2.0";
version = "1.2.1";
pyproject = true;
__structuredAttrs = true;
@ -19,7 +19,7 @@ buildPythonPackage (finalAttrs: {
src = fetchPypi {
pname = "alibabacloud_ram20150501";
inherit (finalAttrs) version;
hash = "sha256-YlNRPIiAdp9P1bNv7d2zYqnKYorZrpwFwO6s9fvJW0I=";
hash = "sha256-dzFVfjw5oPAVm59dEMksDeZZXCf0VT3EWeA8zZpMIqU=";
};
build-system = [ setuptools ];

View file

@ -21,7 +21,7 @@
buildPythonPackage (finalAttrs: {
pname = "flash-linear-attention";
version = "0.5.0";
version = "0.5.1";
pyproject = true;
disabled = pythonOlder "3.10";
@ -30,7 +30,7 @@ buildPythonPackage (finalAttrs: {
owner = "fla-org";
repo = "flash-linear-attention";
tag = "v${finalAttrs.version}";
hash = "sha256-g66yGHaBwEyjb+of76tKTtV/7as/2xQuqcjbGs4E3rU=";
hash = "sha256-vxNbZ+FkxJh2E0TF09Z7ghkm8eas7Q96heeSXwgV4uU=";
};
build-system = [ setuptools ];

View file

@ -14,13 +14,13 @@
buildPythonPackage (finalAttrs: {
pname = "google-cloud-vpc-access";
version = "1.16.0";
version = "1.17.0";
pyproject = true;
src = fetchPypi {
pname = "google_cloud_vpc_access";
inherit (finalAttrs) version;
hash = "sha256-cVJ8Ok3K1dKGuTsBhDJUqhYEimNTEqOjfVSTqxke0NQ=";
hash = "sha256-c5HvaQIykWRNAuDSBhv72kHZs8qgMY8cyvn5N7mahY4=";
};
build-system = [ setuptools ];

View file

@ -14,13 +14,13 @@
buildPythonPackage (finalAttrs: {
pname = "google-cloud-webrisk";
version = "1.21.0";
version = "1.22.0";
pyproject = true;
src = fetchPypi {
pname = "google_cloud_webrisk";
inherit (finalAttrs) version;
hash = "sha256-/PcV2opz3zaGerJk6rCOQNwZbxV2FqY/3BLMNQzO8Pc=";
hash = "sha256-OjJcQDXpbtq4RB8Cev6UgCqvDByOXmoJ306oFlQtryQ=";
};
build-system = [ setuptools ];

View file

@ -13,13 +13,13 @@
buildPythonPackage (finalAttrs: {
pname = "google-cloud-workflows";
version = "1.22.0";
version = "1.23.0";
pyproject = true;
src = fetchPypi {
pname = "google_cloud_workflows";
inherit (finalAttrs) version;
hash = "sha256-9+uHMI2CPzwNWcn9Kci7ze+Oi5E4MhgHTIMf2Sfr4y0=";
hash = "sha256-vo4IpdE0GG2834Z8BbFZrYrH3jtkJbIb76q39PJY1Kg=";
};
build-system = [ setuptools ];

View file

@ -13,14 +13,14 @@
buildPythonPackage (finalAttrs: {
pname = "govee-ble";
version = "1.2.0";
version = "1.4.0";
pyproject = true;
src = fetchFromGitHub {
owner = "Bluetooth-Devices";
repo = "govee-ble";
tag = "v${finalAttrs.version}";
hash = "sha256-+qzSNwV+2h75LVly7kZaaulKQp5Hp0N8k05BauN1TXo=";
hash = "sha256-Y1iSU6G/+0qSLgFQNKeCuhpVv6mJYXivk0wNGNMBd6U=";
};
build-system = [ poetry-core ];

View file

@ -8,14 +8,14 @@
buildPythonPackage (finalAttrs: {
pname = "iamdata";
version = "0.1.202606261";
version = "0.1.202606271";
pyproject = true;
src = fetchFromGitHub {
owner = "cloud-copilot";
repo = "iam-data-python";
tag = "v${finalAttrs.version}";
hash = "sha256-gxtJMcDyez94n1JVc0KZo2ygtskcPgudSLdUzgfCJjw=";
hash = "sha256-EdU6fcNXufK/GK7tz43+SDox/Cms4uVT5DEzyIv93OQ=";
};
__darwinAllowLocalNetworking = true;

View file

@ -2,31 +2,31 @@
lib,
buildPythonPackage,
fetchFromGitHub,
poetry-core,
flit-core,
gitUpdater,
opentelemetry-api,
opentelemetry-sdk,
pytest-asyncio,
pytest-mock,
pytestCheckHook,
std-uritemplate,
gitUpdater,
}:
buildPythonPackage (finalAttrs: {
pname = "microsoft-kiota-abstractions";
version = "1.10.3";
version = "1.11.6";
pyproject = true;
src = fetchFromGitHub {
owner = "microsoft";
repo = "kiota-python";
tag = "microsoft-kiota-abstractions-v${finalAttrs.version}";
hash = "sha256-r0u+erTSKBWzLV7VfwWUYh7lyJS1hDh5A0Tzk3pFzo4=";
hash = "sha256-hhYQsNcy+jVVmKiDuB1nGpx+aA7toM6WDFoU5Vnu5Vs=";
};
sourceRoot = "${finalAttrs.src.name}/packages/abstractions/";
build-system = [ poetry-core ];
build-system = [ flit-core ];
dependencies = [
opentelemetry-api

View file

@ -4,7 +4,7 @@
azure-core,
buildPythonPackage,
fetchFromGitHub,
poetry-core,
flit-core,
microsoft-kiota-abstractions,
opentelemetry-api,
opentelemetry-sdk,
@ -16,19 +16,19 @@
buildPythonPackage (finalAttrs: {
pname = "microsoft-kiota-authentication-azure";
version = "1.10.3";
version = "1.11.6";
pyproject = true;
src = fetchFromGitHub {
owner = "microsoft";
repo = "kiota-python";
tag = "microsoft-kiota-authentication-azure-v${finalAttrs.version}";
hash = "sha256-r0u+erTSKBWzLV7VfwWUYh7lyJS1hDh5A0Tzk3pFzo4=";
hash = "sha256-hhYQsNcy+jVVmKiDuB1nGpx+aA7toM6WDFoU5Vnu5Vs=";
};
sourceRoot = "${finalAttrs.src.name}/packages/authentication/azure/";
build-system = [ poetry-core ];
build-system = [ flit-core ];
dependencies = [
aiohttp

View file

@ -2,7 +2,7 @@
lib,
buildPythonPackage,
fetchFromGitHub,
poetry-core,
flit-core,
httpx,
microsoft-kiota-abstractions,
opentelemetry-api,
@ -16,19 +16,19 @@
buildPythonPackage (finalAttrs: {
pname = "microsoft-kiota-http";
version = "1.10.3";
version = "1.11.6";
pyproject = true;
src = fetchFromGitHub {
owner = "microsoft";
repo = "kiota-python";
tag = "microsoft-kiota-http-v${finalAttrs.version}";
hash = "sha256-r0u+erTSKBWzLV7VfwWUYh7lyJS1hDh5A0Tzk3pFzo4=";
hash = "sha256-hhYQsNcy+jVVmKiDuB1nGpx+aA7toM6WDFoU5Vnu5Vs=";
};
sourceRoot = "${finalAttrs.src.name}/packages/http/httpx/";
build-system = [ poetry-core ];
build-system = [ flit-core ];
dependencies = [
httpx

View file

@ -2,7 +2,7 @@
lib,
buildPythonPackage,
fetchFromGitHub,
poetry-core,
flit-core,
microsoft-kiota-abstractions,
pendulum,
pytest-asyncio,
@ -13,19 +13,19 @@
buildPythonPackage (finalAttrs: {
pname = "microsoft-kiota-serialization-json";
version = "1.10.3";
version = "1.11.6";
pyproject = true;
src = fetchFromGitHub {
owner = "microsoft";
repo = "kiota-python";
tag = "microsoft-kiota-serialization-json-v${finalAttrs.version}";
hash = "sha256-r0u+erTSKBWzLV7VfwWUYh7lyJS1hDh5A0Tzk3pFzo4=";
hash = "sha256-hhYQsNcy+jVVmKiDuB1nGpx+aA7toM6WDFoU5Vnu5Vs=";
};
sourceRoot = "${finalAttrs.src.name}/packages/serialization/json/";
build-system = [ poetry-core ];
build-system = [ flit-core ];
dependencies = [
microsoft-kiota-abstractions

View file

@ -2,7 +2,7 @@
lib,
buildPythonPackage,
fetchFromGitHub,
poetry-core,
flit-core,
microsoft-kiota-abstractions,
microsoft-kiota-serialization-json,
pytest-asyncio,
@ -13,19 +13,19 @@
buildPythonPackage rec {
pname = "microsoft-kiota-serialization-multipart";
version = "1.10.3";
version = "1.11.6";
pyproject = true;
src = fetchFromGitHub {
owner = "microsoft";
repo = "kiota-python";
tag = "microsoft-kiota-serialization-multipart-v${version}";
hash = "sha256-r0u+erTSKBWzLV7VfwWUYh7lyJS1hDh5A0Tzk3pFzo4=";
hash = "sha256-hhYQsNcy+jVVmKiDuB1nGpx+aA7toM6WDFoU5Vnu5Vs=";
};
sourceRoot = "${src.name}/packages/serialization/multipart/";
build-system = [ poetry-core ];
build-system = [ flit-core ];
dependencies = [ microsoft-kiota-abstractions ];

View file

@ -2,7 +2,7 @@
lib,
buildPythonPackage,
fetchFromGitHub,
poetry-core,
flit-core,
microsoft-kiota-abstractions,
pytest-asyncio,
pytest-mock,
@ -13,19 +13,19 @@
buildPythonPackage rec {
pname = "microsoft-kiota-serialization-text";
version = "1.10.3";
version = "1.11.6";
pyproject = true;
src = fetchFromGitHub {
owner = "microsoft";
repo = "kiota-python";
tag = "microsoft-kiota-serialization-text-v${version}";
hash = "sha256-r0u+erTSKBWzLV7VfwWUYh7lyJS1hDh5A0Tzk3pFzo4=";
hash = "sha256-hhYQsNcy+jVVmKiDuB1nGpx+aA7toM6WDFoU5Vnu5Vs=";
};
sourceRoot = "${src.name}/packages/serialization/text/";
build-system = [ poetry-core ];
build-system = [ flit-core ];
dependencies = [
microsoft-kiota-abstractions

View file

@ -0,0 +1,74 @@
{
lib,
buildPythonPackage,
claude-agent-sdk,
fetchFromGitHub,
hatchling,
nix-update-script,
openinference-instrumentation,
openinference-semantic-conventions,
opentelemetry-api,
opentelemetry-instrumentation,
opentelemetry-semantic-conventions,
pytest-asyncio,
pytest-timeout,
pytestCheckHook,
pyyaml,
sniffio,
typing-extensions,
wrapt,
}:
buildPythonPackage (finalAttrs: {
pname = "openinference-instrumentation-claude-agent-sdk";
version = "0.1.6";
pyproject = true;
__structuredAttrs = true;
src = fetchFromGitHub {
owner = "Arize-ai";
repo = "openinference";
tag = "python-openinference-instrumentation-claude-agent-sdk-v${finalAttrs.version}";
hash = "sha256-wmwqmN/rN521TaXVZfkaRzHPVhANSgKaBVc4rhXgIII=";
};
sourceRoot = "${finalAttrs.src.name}/python/instrumentation/${finalAttrs.pname}";
build-system = [ hatchling ];
dependencies = [
opentelemetry-api
opentelemetry-instrumentation
opentelemetry-semantic-conventions
openinference-semantic-conventions
openinference-instrumentation
typing-extensions
wrapt
];
optional-dependencies = {
instruments = [ claude-agent-sdk ];
};
nativeCheckInputs = [
pytest-asyncio
pytest-timeout
pytestCheckHook
pyyaml
sniffio
]
++ lib.flatten (builtins.attrValues finalAttrs.passthru.optional-dependencies);
pythonImportsCheck = [ "openinference.instrumentation.claude_agent_sdk" ];
passthru.updateScript = nix-update-script { };
meta = {
description = "OpenInference Claude Agent SDK Instrumentation";
homepage = "https://github.com/Arize-ai/openinference";
changelog = "https://github.com/Arize-ai/openinference/releases/tag/${finalAttrs.src.tag}";
license = lib.licenses.asl20;
maintainers = with lib.maintainers; [ fab ];
};
})

View file

@ -0,0 +1,84 @@
{
lib,
buildPythonPackage,
fetchFromGitHub,
hatchling,
httpx,
nix-update-script,
openai,
openinference-instrumentation,
openinference-semantic-conventions,
opentelemetry-api,
opentelemetry-instrumentation-httpx,
opentelemetry-instrumentation,
opentelemetry-semantic-conventions,
pytest-asyncio,
pytest-vcr,
pytestCheckHook,
respx,
typing-extensions,
wrapt,
}:
buildPythonPackage (finalAttrs: {
pname = "openinference-instrumentation-openai";
version = "0.1.52";
pyproject = true;
__structuredAttrs = true;
src = fetchFromGitHub {
owner = "Arize-ai";
repo = "openinference";
tag = "python-openinference-instrumentation-openai-v${finalAttrs.version}";
hash = "sha256-wmwqmN/rN521TaXVZfkaRzHPVhANSgKaBVc4rhXgIII=";
};
sourceRoot = "${finalAttrs.src.name}/python/instrumentation/${finalAttrs.pname}";
build-system = [ hatchling ];
dependencies = [
opentelemetry-api
opentelemetry-instrumentation
opentelemetry-semantic-conventions
openinference-semantic-conventions
openinference-instrumentation
typing-extensions
wrapt
];
optional-dependencies = {
instruments = [ openai ];
};
nativeCheckInputs = [
httpx
opentelemetry-instrumentation-httpx
pytest-asyncio
pytest-vcr
pytestCheckHook
respx
]
++ lib.flatten (builtins.attrValues finalAttrs.passthru.optional-dependencies);
pythonImportsCheck = [ "openinference.instrumentation.openai" ];
disabledTests = [
# Tests want to connect to OpenAI's API
"test_cached_tokens"
"test_input_value"
"test_openai"
"test_tool_calls"
];
passthru.updateScript = nix-update-script { };
meta = {
description = "OpenInference OpenAI SDK Instrumentation";
homepage = "https://github.com/Arize-ai/openinference";
changelog = "https://github.com/Arize-ai/openinference/releases/tag/${finalAttrs.src.tag}";
license = lib.licenses.asl20;
maintainers = with lib.maintainers; [ fab ];
};
})

View file

@ -0,0 +1,69 @@
{
lib,
buildPythonPackage,
fetchFromGitHub,
hatchling,
jsonschema,
nix-update-script,
openai,
openinference-semantic-conventions,
opentelemetry-api,
opentelemetry-sdk,
pytest-asyncio,
pytest-vcr,
pytestCheckHook,
typing-extensions,
wrapt,
}:
buildPythonPackage (finalAttrs: {
pname = "openinference-instrumentation";
version = "0.1.53";
pyproject = true;
__structuredAttrs = true;
src = fetchFromGitHub {
owner = "Arize-ai";
repo = "openinference";
tag = "python-openinference-instrumentation-v${finalAttrs.version}";
hash = "sha256-1FzAiO3Vxt2o9YCzwPfHOn4hwvOLDt9Luv3zQTJ6J2Q=";
};
sourceRoot = "${finalAttrs.src.name}/python/${finalAttrs.pname}";
build-system = [ hatchling ];
dependencies = [
opentelemetry-api
opentelemetry-sdk
openinference-semantic-conventions
typing-extensions
wrapt
];
nativeCheckInputs = [
jsonschema
openai
pytest-asyncio
pytest-vcr
pytestCheckHook
];
pythonImportsCheck = [ "openinference.instrumentation" ];
disabledTests = [
# Tests want to connect to OpenAI's API
"TestTracerLLMDecorator"
];
passthru.updateScript = nix-update-script { };
meta = {
description = "OpenTelemetry Instrumentation for AI Observability";
homepage = "https://github.com/Arize-ai/openinference";
changelog = "https://github.com/Arize-ai/openinference/releases/tag/${finalAttrs.src.tag}";
license = lib.licenses.asl20;
maintainers = with lib.maintainers; [ fab ];
};
})

Some files were not shown because too many files have changed in this diff Show more