treewide: reformat

This commit is contained in:
Michael Hoang
2025-08-08 15:27:00 +10:00
parent 6b137f21de
commit a71a5880c1
40 changed files with 738 additions and 740 deletions

View File

@@ -19,11 +19,10 @@
...
}:
let
dependencies =
[
pkgs.stdenv.drvPath
]
++ builtins.map (i: i.outPath) (builtins.attrValues (builtins.removeAttrs self.inputs [ "self" ]));
dependencies = [
pkgs.stdenv.drvPath
]
++ builtins.map (i: i.outPath) (builtins.attrValues (builtins.removeAttrs self.inputs [ "self" ]));
closureInfo = pkgs.closureInfo { rootPaths = dependencies; };
in
{
@@ -154,13 +153,12 @@
nixos-test-backups = self.clanLib.test.containerTest {
name = "nixos-test-backups";
nodes.machine = {
imports =
[
self.nixosModules.clanCore
# Some custom overrides for the backup tests
self.nixosModules.test-backup
]
++
imports = [
self.nixosModules.clanCore
# Some custom overrides for the backup tests
self.nixosModules.test-backup
]
++
# import the inventory generated nixosModules
self.clan.clanInternals.inventoryClass.machines.test-backup.machineImports;
clan.core.settings.directory = ./.;

View File

@@ -50,7 +50,8 @@
self.nixosConfigurations."test-flash-machine-${pkgs.hostPlatform.system}".config.system.build.toplevel
self.nixosConfigurations."test-flash-machine-${pkgs.hostPlatform.system}".config.system.build.diskoScript
self.nixosConfigurations."test-flash-machine-${pkgs.hostPlatform.system}".config.system.build.diskoScript.drvPath
] ++ builtins.map (i: i.outPath) (builtins.attrValues self.inputs);
]
++ builtins.map (i: i.outPath) (builtins.attrValues self.inputs);
closureInfo = pkgs.closureInfo { rootPaths = dependencies; };
in
{

View File

@@ -158,7 +158,8 @@
pkgs.stdenv.drvPath
pkgs.bash.drvPath
pkgs.buildPackages.xorg.lndir
] ++ builtins.map (i: i.outPath) (builtins.attrValues self.inputs);
]
++ builtins.map (i: i.outPath) (builtins.attrValues self.inputs);
};
in
pkgs.lib.mkIf (pkgs.stdenv.isLinux && !pkgs.stdenv.isAarch64) {

View File

@@ -159,7 +159,8 @@ let
pkgs.stdenv.drvPath
pkgs.bash.drvPath
pkgs.buildPackages.xorg.lndir
] ++ builtins.map (i: i.outPath) (builtins.attrValues self.inputs);
]
++ builtins.map (i: i.outPath) (builtins.attrValues self.inputs);
};
in

View File

@@ -35,7 +35,8 @@
pkgs.stdenv.drvPath
pkgs.stdenvNoCC
self.nixosConfigurations.test-morph-machine.config.system.build.toplevel
] ++ builtins.map (i: i.outPath) (builtins.attrValues self.inputs);
]
++ builtins.map (i: i.outPath) (builtins.attrValues self.inputs);
closureInfo = pkgs.closureInfo { rootPaths = dependencies; };
in

View File

@@ -112,7 +112,8 @@
pkgs.stdenv.drvPath
pkgs.bash.drvPath
pkgs.buildPackages.xorg.lndir
] ++ builtins.map (i: i.outPath) (builtins.attrValues self.inputs);
]
++ builtins.map (i: i.outPath) (builtins.attrValues self.inputs);
};
in
self.clanLib.test.containerTest {

View File

@@ -112,125 +112,124 @@ in
'';
in
lib.mkIf (cfg.targets != { }) {
environment.systemPackages =
[
(pkgs.writeShellScriptBin "localbackup-create" ''
set -efu -o pipefail
export PATH=${
lib.makeBinPath [
pkgs.rsnapshot
pkgs.coreutils
pkgs.util-linux
]
}
${lib.concatMapStringsSep "\n" (target: ''
${mountHook target}
echo "Creating backup '${target.name}'"
environment.systemPackages = [
(pkgs.writeShellScriptBin "localbackup-create" ''
set -efu -o pipefail
export PATH=${
lib.makeBinPath [
pkgs.rsnapshot
pkgs.coreutils
pkgs.util-linux
]
}
${lib.concatMapStringsSep "\n" (target: ''
${mountHook target}
echo "Creating backup '${target.name}'"
${lib.optionalString (target.preBackupHook != null) ''
(
${target.preBackupHook}
)
''}
declare -A preCommandErrors
${lib.concatMapStringsSep "\n" (
state:
lib.optionalString (state.preBackupCommand != null) ''
echo "Running pre-backup command for ${state.name}"
if ! /run/current-system/sw/bin/${state.preBackupCommand}; then
preCommandErrors["${state.name}"]=1
fi
''
) (builtins.attrValues config.clan.core.state)}
rsnapshot -c "${pkgs.writeText "rsnapshot.conf" (rsnapshotConfig target)}" sync
rsnapshot -c "${pkgs.writeText "rsnapshot.conf" (rsnapshotConfig target)}" snapshot
'') (builtins.attrValues cfg.targets)}'')
(pkgs.writeShellScriptBin "localbackup-list" ''
set -efu -o pipefail
export PATH=${
lib.makeBinPath [
pkgs.jq
pkgs.findutils
pkgs.coreutils
pkgs.util-linux
]
}
(${
lib.concatMapStringsSep "\n" (target: ''
(
${mountHook target}
find ${lib.escapeShellArg target.directory} -mindepth 1 -maxdepth 1 -name "snapshot.*" -print0 -type d \
| jq -Rs 'split("\u0000") | .[] | select(. != "") | { "name": ("${target.name}::" + .)}'
)
'') (builtins.attrValues cfg.targets)
}) | jq -s .
'')
(pkgs.writeShellScriptBin "localbackup-restore" ''
set -efu -o pipefail
export PATH=${
lib.makeBinPath [
pkgs.rsync
pkgs.coreutils
pkgs.util-linux
pkgs.gawk
]
}
if [[ "''${NAME:-}" == "" ]]; then
echo "No backup name given via NAME environment variable"
exit 1
fi
if [[ "''${FOLDERS:-}" == "" ]]; then
echo "No folders given via FOLDERS environment variable"
exit 1
fi
name=$(awk -F'::' '{print $1}' <<< $NAME)
backupname=''${NAME#$name::}
if command -v localbackup-mount-$name; then
localbackup-mount-$name
fi
if command -v localbackup-unmount-$name; then
trap "localbackup-unmount-$name" EXIT
fi
if [[ ! -d $backupname ]]; then
echo "No backup found $backupname"
exit 1
fi
IFS=':' read -ra FOLDER <<< "''$FOLDERS"
for folder in "''${FOLDER[@]}"; do
mkdir -p "$folder"
rsync -a "$backupname/${config.networking.hostName}$folder/" "$folder"
done
'')
]
++ (lib.mapAttrsToList (
name: target:
pkgs.writeShellScriptBin ("localbackup-mount-" + name) ''
set -efu -o pipefail
${lib.optionalString (target.preMountHook != null) target.preMountHook}
${lib.optionalString (target.mountpoint != null) ''
if ! ${pkgs.util-linux}/bin/mountpoint -q ${lib.escapeShellArg target.mountpoint}; then
${pkgs.util-linux}/bin/mount -o X-mount.mkdir ${lib.escapeShellArg target.mountpoint}
fi
${lib.optionalString (target.preBackupHook != null) ''
(
${target.preBackupHook}
)
''}
${lib.optionalString (target.postMountHook != null) target.postMountHook}
''
) cfg.targets)
++ lib.mapAttrsToList (
name: target:
pkgs.writeShellScriptBin ("localbackup-unmount-" + name) ''
set -efu -o pipefail
${lib.optionalString (target.preUnmountHook != null) target.preUnmountHook}
${lib.optionalString (
target.mountpoint != null
) "${pkgs.util-linux}/bin/umount ${lib.escapeShellArg target.mountpoint}"}
${lib.optionalString (target.postUnmountHook != null) target.postUnmountHook}
''
) cfg.targets;
declare -A preCommandErrors
${lib.concatMapStringsSep "\n" (
state:
lib.optionalString (state.preBackupCommand != null) ''
echo "Running pre-backup command for ${state.name}"
if ! /run/current-system/sw/bin/${state.preBackupCommand}; then
preCommandErrors["${state.name}"]=1
fi
''
) (builtins.attrValues config.clan.core.state)}
rsnapshot -c "${pkgs.writeText "rsnapshot.conf" (rsnapshotConfig target)}" sync
rsnapshot -c "${pkgs.writeText "rsnapshot.conf" (rsnapshotConfig target)}" snapshot
'') (builtins.attrValues cfg.targets)}'')
(pkgs.writeShellScriptBin "localbackup-list" ''
set -efu -o pipefail
export PATH=${
lib.makeBinPath [
pkgs.jq
pkgs.findutils
pkgs.coreutils
pkgs.util-linux
]
}
(${
lib.concatMapStringsSep "\n" (target: ''
(
${mountHook target}
find ${lib.escapeShellArg target.directory} -mindepth 1 -maxdepth 1 -name "snapshot.*" -print0 -type d \
| jq -Rs 'split("\u0000") | .[] | select(. != "") | { "name": ("${target.name}::" + .)}'
)
'') (builtins.attrValues cfg.targets)
}) | jq -s .
'')
(pkgs.writeShellScriptBin "localbackup-restore" ''
set -efu -o pipefail
export PATH=${
lib.makeBinPath [
pkgs.rsync
pkgs.coreutils
pkgs.util-linux
pkgs.gawk
]
}
if [[ "''${NAME:-}" == "" ]]; then
echo "No backup name given via NAME environment variable"
exit 1
fi
if [[ "''${FOLDERS:-}" == "" ]]; then
echo "No folders given via FOLDERS environment variable"
exit 1
fi
name=$(awk -F'::' '{print $1}' <<< $NAME)
backupname=''${NAME#$name::}
if command -v localbackup-mount-$name; then
localbackup-mount-$name
fi
if command -v localbackup-unmount-$name; then
trap "localbackup-unmount-$name" EXIT
fi
if [[ ! -d $backupname ]]; then
echo "No backup found $backupname"
exit 1
fi
IFS=':' read -ra FOLDER <<< "''$FOLDERS"
for folder in "''${FOLDER[@]}"; do
mkdir -p "$folder"
rsync -a "$backupname/${config.networking.hostName}$folder/" "$folder"
done
'')
]
++ (lib.mapAttrsToList (
name: target:
pkgs.writeShellScriptBin ("localbackup-mount-" + name) ''
set -efu -o pipefail
${lib.optionalString (target.preMountHook != null) target.preMountHook}
${lib.optionalString (target.mountpoint != null) ''
if ! ${pkgs.util-linux}/bin/mountpoint -q ${lib.escapeShellArg target.mountpoint}; then
${pkgs.util-linux}/bin/mount -o X-mount.mkdir ${lib.escapeShellArg target.mountpoint}
fi
''}
${lib.optionalString (target.postMountHook != null) target.postMountHook}
''
) cfg.targets)
++ lib.mapAttrsToList (
name: target:
pkgs.writeShellScriptBin ("localbackup-unmount-" + name) ''
set -efu -o pipefail
${lib.optionalString (target.preUnmountHook != null) target.preUnmountHook}
${lib.optionalString (
target.mountpoint != null
) "${pkgs.util-linux}/bin/umount ${lib.escapeShellArg target.mountpoint}"}
${lib.optionalString (target.postUnmountHook != null) target.postUnmountHook}
''
) cfg.targets;
clan.core.backups.providers.localbackup = {
# TODO list needs to run locally or on the remote machine

View File

@@ -116,47 +116,45 @@ in
};
clan.core.postgresql.databases.matrix-synapse.restore.stopOnRestore = [ "matrix-synapse" ];
clan.core.vars.generators =
{
"matrix-synapse" = {
files."synapse-registration_shared_secret" = { };
runtimeInputs = with pkgs; [
coreutils
pwgen
];
migrateFact = "matrix-synapse";
script = ''
echo -n "$(pwgen -s 32 1)" > "$out"/synapse-registration_shared_secret
'';
};
clan.core.vars.generators = {
"matrix-synapse" = {
files."synapse-registration_shared_secret" = { };
runtimeInputs = with pkgs; [
coreutils
pwgen
];
migrateFact = "matrix-synapse";
script = ''
echo -n "$(pwgen -s 32 1)" > "$out"/synapse-registration_shared_secret
'';
};
}
// lib.mapAttrs' (
name: user:
lib.nameValuePair "matrix-password-${user.name}" {
files."matrix-password-${user.name}" = { };
migrateFact = "matrix-password-${user.name}";
runtimeInputs = with pkgs; [ xkcdpass ];
script = ''
xkcdpass -n 4 -d - > "$out"/${lib.escapeShellArg "matrix-password-${user.name}"}
'';
}
// lib.mapAttrs' (
name: user:
lib.nameValuePair "matrix-password-${user.name}" {
files."matrix-password-${user.name}" = { };
migrateFact = "matrix-password-${user.name}";
runtimeInputs = with pkgs; [ xkcdpass ];
script = ''
xkcdpass -n 4 -d - > "$out"/${lib.escapeShellArg "matrix-password-${user.name}"}
'';
}
) cfg.users;
) cfg.users;
systemd.services.matrix-synapse =
let
usersScript =
''
while ! ${pkgs.netcat}/bin/nc -z -v ::1 8008; do
if ! kill -0 "$MAINPID"; then exit 1; fi
sleep 1;
done
''
+ lib.concatMapStringsSep "\n" (user: ''
# only create user if it doesn't exist
/run/current-system/sw/bin/matrix-synapse-register_new_matrix_user --exists-ok --password-file ${
config.clan.core.vars.generators."matrix-password-${user.name}".files."matrix-password-${user.name}".path
} --user "${user.name}" ${if user.admin then "--admin" else "--no-admin"}
'') (lib.attrValues cfg.users);
usersScript = ''
while ! ${pkgs.netcat}/bin/nc -z -v ::1 8008; do
if ! kill -0 "$MAINPID"; then exit 1; fi
sleep 1;
done
''
+ lib.concatMapStringsSep "\n" (user: ''
# only create user if it doesn't exist
/run/current-system/sw/bin/matrix-synapse-register_new_matrix_user --exists-ok --password-file ${
config.clan.core.vars.generators."matrix-password-${user.name}".files."matrix-password-${user.name}".path
} --user "${user.name}" ${if user.admin then "--admin" else "--no-admin"}
'') (lib.attrValues cfg.users);
in
{
path = [ pkgs.curl ];

View File

@@ -18,13 +18,12 @@
config.clan.core.vars.generators.root-password.files.password-hash.path;
clan.core.vars.generators.root-password = {
files.password-hash =
{
neededFor = "users";
}
// (lib.optionalAttrs (_class == "nixos") {
restartUnits = lib.optional (config.services.userborn.enable) "userborn.service";
});
files.password-hash = {
neededFor = "users";
}
// (lib.optionalAttrs (_class == "nixos") {
restartUnits = lib.optional (config.services.userborn.enable) "userborn.service";
});
files.password = {
deploy = false;
};

View File

@@ -32,17 +32,16 @@ in
cfg.certificate.searchDomains != [ ]
) config.clan.core.vars.generators.openssh-cert.files."ssh.id_ed25519-cert.pub".path;
hostKeys =
[
{
path = config.clan.core.vars.generators.openssh.files."ssh.id_ed25519".path;
type = "ed25519";
}
]
++ lib.optional cfg.hostKeys.rsa.enable {
path = config.clan.core.vars.generators.openssh-rsa.files."ssh.id_rsa".path;
type = "rsa";
};
hostKeys = [
{
path = config.clan.core.vars.generators.openssh.files."ssh.id_ed25519".path;
type = "ed25519";
}
]
++ lib.optional cfg.hostKeys.rsa.enable {
path = config.clan.core.vars.generators.openssh-rsa.files."ssh.id_rsa".path;
type = "rsa";
};
};
clan.core.vars.generators.openssh = {
@@ -62,7 +61,8 @@ in
hostNames = [
"localhost"
config.networking.hostName
] ++ (lib.optional (config.networking.domain != null) config.networking.fqdn);
]
++ (lib.optional (config.networking.domain != null) config.networking.fqdn);
publicKey = config.clan.core.vars.generators.openssh.files."ssh.id_ed25519.pub".value;
};

View File

@@ -34,14 +34,15 @@ let
value = {
name = machine;
id = (lib.removeSuffix "\n" (builtins.readFile (syncthingPublicKeyPath machine)));
addresses =
[ "dynamic" ]
++ (
if (lib.elem machine networkIpMachines) then
[ "tcp://[${(lib.removeSuffix "\n" (builtins.readFile (zerotierIpMachinePath machine)))}]:22000" ]
else
[ ]
);
addresses = [
"dynamic"
]
++ (
if (lib.elem machine networkIpMachines) then
[ "tcp://[${(lib.removeSuffix "\n" (builtins.readFile (zerotierIpMachinePath machine)))}]:22000" ]
else
[ ]
);
};
}) syncthingPublicKeyMachines;
in

View File

@@ -21,17 +21,16 @@ in
settings.certificateSearchDomains != [ ]
) config.clan.core.vars.generators.openssh-cert.files."ssh.id_ed25519-cert.pub".path;
hostKeys =
[
{
path = config.clan.core.vars.generators.openssh.files."ssh.id_ed25519".path;
type = "ed25519";
}
]
++ lib.optional settings.rsaHostKey.enable {
path = config.clan.core.vars.generators.openssh-rsa.files."ssh.id_rsa".path;
type = "rsa";
};
hostKeys = [
{
path = config.clan.core.vars.generators.openssh.files."ssh.id_ed25519".path;
type = "ed25519";
}
]
++ lib.optional settings.rsaHostKey.enable {
path = config.clan.core.vars.generators.openssh-rsa.files."ssh.id_rsa".path;
type = "rsa";
};
};
clan.core.vars.generators.openssh = {
@@ -51,7 +50,8 @@ in
hostNames = [
"localhost"
config.networking.hostName
] ++ (lib.optional (config.networking.domain != null) config.networking.fqdn);
]
++ (lib.optional (config.networking.domain != null) config.networking.fqdn);
publicKey = config.clan.core.vars.generators.openssh.files."ssh.id_ed25519.pub".value;
};

View File

@@ -184,24 +184,24 @@
settings.certificate.searchDomains != [ ]
) config.clan.core.vars.generators.openssh-cert.files."ssh.id_ed25519-cert.pub".path;
hostKeys =
[
{
path = config.clan.core.vars.generators.openssh.files."ssh.id_ed25519".path;
type = "ed25519";
}
]
++ lib.optional settings.hostKeys.rsa.enable {
path = config.clan.core.vars.generators.openssh-rsa.files."ssh.id_rsa".path;
type = "rsa";
};
hostKeys = [
{
path = config.clan.core.vars.generators.openssh.files."ssh.id_ed25519".path;
type = "ed25519";
}
]
++ lib.optional settings.hostKeys.rsa.enable {
path = config.clan.core.vars.generators.openssh-rsa.files."ssh.id_rsa".path;
type = "rsa";
};
};
programs.ssh.knownHosts.clan-sshd-self-ed25519 = {
hostNames = [
"localhost"
config.networking.hostName
] ++ (lib.optional (config.networking.domain != null) config.networking.fqdn);
]
++ (lib.optional (config.networking.domain != null) config.networking.fqdn);
publicKey = config.clan.core.vars.generators.openssh.files."ssh.id_ed25519.pub".value;
};
};

View File

@@ -157,11 +157,11 @@
value = {
name = machine;
id = readMachineVar machine "syncthing/id/value" "";
addresses =
[
"dynamic"
]
++ lib.optional (readMachineVar machine "zerotier/zerotier-ip/value" null != null)
addresses = [
"dynamic"
]
++
lib.optional (readMachineVar machine "zerotier/zerotier-ip/value" null != null)
"tcp://[${readMachineVar machine "zerotier/zerotier-ip/value" ""}]:22000";
};
})

View File

@@ -30,18 +30,17 @@ pkgs.stdenv.mkDerivation {
];
};
nativeBuildInputs =
[
pkgs.python3
uml-c4
]
++ (with pkgs.python3Packages; [
mkdocs
mkdocs-material
mkdocs-macros
mkdocs-redoc-tag
mkdocs-redirects
]);
nativeBuildInputs = [
pkgs.python3
uml-c4
]
++ (with pkgs.python3Packages; [
mkdocs
mkdocs-material
mkdocs-macros
mkdocs-redoc-tag
mkdocs-redirects
]);
configurePhase = ''
pushd docs

View File

@@ -156,7 +156,8 @@
type = types.submoduleWith {
modules = [
{ noInstanceOptions = true; }
] ++ mapAttrsToList fakeInstanceOptions serviceModules;
]
++ mapAttrsToList fakeInstanceOptions serviceModules;
};
};
}

View File

@@ -87,34 +87,35 @@
};
};
systems = import systems;
imports =
[ flake-parts.flakeModules.modules ]
++
# only importing existing paths allows to minimize the flake for test
# by removing files
filter pathExists [
./checks/flake-module.nix
./clanModules/flake-module.nix
./clanServices/flake-module.nix
./devShell.nix
./docs/nix/flake-module.nix
./flakeModules/flake-module.nix
./flakeModules/demo_iso.nix
./lib/filter-clan-core/flake-module.nix
./lib/flake-module.nix
./lib/flake-parts/clan-nixos-test.nix
./nixosModules/clanCore/vars/flake-module.nix
./nixosModules/flake-module.nix
./pkgs/flake-module.nix
./templates/flake-module.nix
]
++ [
(if pathExists ./flakeModules/clan.nix then import ./flakeModules/clan.nix inputs.self else { })
imports = [
flake-parts.flakeModules.modules
]
++
# only importing existing paths allows to minimize the flake for test
# by removing files
filter pathExists [
./checks/flake-module.nix
./clanModules/flake-module.nix
./clanServices/flake-module.nix
./devShell.nix
./docs/nix/flake-module.nix
./flakeModules/flake-module.nix
./flakeModules/demo_iso.nix
./lib/filter-clan-core/flake-module.nix
./lib/flake-module.nix
./lib/flake-parts/clan-nixos-test.nix
./nixosModules/clanCore/vars/flake-module.nix
./nixosModules/flake-module.nix
./pkgs/flake-module.nix
./templates/flake-module.nix
]
# Make treefmt-nix optional
# This only works if you set inputs.clan-core.inputs.treefmt-nix.follows
# to a non-empty input that doesn't export a flakeModule
++ optional (pathExists ./formatter.nix && inputs.treefmt-nix ? flakeModule) ./formatter.nix;
++ [
(if pathExists ./flakeModules/clan.nix then import ./flakeModules/clan.nix inputs.self else { })
]
# Make treefmt-nix optional
# This only works if you set inputs.clan-core.inputs.treefmt-nix.follows
# to a non-empty input that doesn't export a flakeModule
++ optional (pathExists ./formatter.nix && inputs.treefmt-nix ? flakeModule) ./formatter.nix;
}
);
}

View File

@@ -95,39 +95,38 @@
"*/asciinema-player/*"
];
};
treefmt.programs.mypy.directories =
{
"clan-cli" = {
directory = "pkgs/clan-cli";
extraPythonPackages = (self'.packages.clan-cli.devshellPyDeps pkgs.python3Packages);
};
"clan-app" = {
directory = "pkgs/ui/clan-app";
extraPythonPackages = (self'.packages.clan-app.devshellPyDeps pkgs.python3Packages);
extraPythonPaths = [ "../../clan-cli" ];
};
"generate-test-vars" = {
directory = "pkgs/generate-test-vars";
extraPythonPackages = [
(pkgs.python3.withPackages (ps: self'.packages.clan-cli.devshellPyDeps ps))
];
extraPythonPaths = [ "../clan-cli" ];
};
}
// (
if pkgs.stdenv.isLinux then
{
"clan-vm-manager" = {
directory = "pkgs/clan-vm-manager";
extraPythonPackages = self'.packages.clan-vm-manager.externalTestDeps ++ [
(pkgs.python3.withPackages (ps: self'.packages.clan-cli.devshellPyDeps ps))
];
extraPythonPaths = [ "../clan-cli" ];
};
}
else
{ }
);
treefmt.programs.mypy.directories = {
"clan-cli" = {
directory = "pkgs/clan-cli";
extraPythonPackages = (self'.packages.clan-cli.devshellPyDeps pkgs.python3Packages);
};
"clan-app" = {
directory = "pkgs/ui/clan-app";
extraPythonPackages = (self'.packages.clan-app.devshellPyDeps pkgs.python3Packages);
extraPythonPaths = [ "../../clan-cli" ];
};
"generate-test-vars" = {
directory = "pkgs/generate-test-vars";
extraPythonPackages = [
(pkgs.python3.withPackages (ps: self'.packages.clan-cli.devshellPyDeps ps))
];
extraPythonPaths = [ "../clan-cli" ];
};
}
// (
if pkgs.stdenv.isLinux then
{
"clan-vm-manager" = {
directory = "pkgs/clan-vm-manager";
extraPythonPackages = self'.packages.clan-vm-manager.externalTestDeps ++ [
(pkgs.python3.withPackages (ps: self'.packages.clan-cli.devshellPyDeps ps))
];
extraPythonPaths = [ "../clan-cli" ];
};
}
else
{ }
);
treefmt.programs.ruff.check = true;
treefmt.programs.ruff.format = true;
};

View File

@@ -252,7 +252,8 @@ rec {
// {
oneOf = [
{ type = "null"; }
] ++ (lib.optional (!isExcludedOption nestedOption) (parseOption nestedOption));
]
++ (lib.optional (!isExcludedOption nestedOption) (parseOption nestedOption));
}
# parse bool
else if

View File

@@ -61,7 +61,8 @@ let
modules = [ (config.outputs.moduleForMachine.${name} or { }) ];
specialArgs = {
inherit clan-core;
} // specialArgs;
}
// specialArgs;
}
) allMachines;
@@ -193,7 +194,8 @@ in
# - nixosModules (_class = nixos)
# - darwinModules (_class = darwin)
(lib.optionalAttrs (clan-core ? "${_class}Modules") clan-core."${_class}Modules".clanCore)
] ++ lib.optionals (_class == "nixos") (v.machineImports or [ ]);
]
++ lib.optionals (_class == "nixos") (v.machineImports or [ ]);
# default hostname
networking.hostName = lib.mkDefault name;

View File

@@ -73,7 +73,8 @@ in
};
};
}
] ++ lib.mapAttrsToList (_: service: service.exports) config.mappedServices;
]
++ lib.mapAttrsToList (_: service: service.exports) config.mappedServices;
};
default = { };
};

View File

@@ -15,16 +15,15 @@
lib.evalModules {
class = "clan.service";
specialArgs._ctx = prefix;
modules =
[
# Base module
./service-module.nix
# Feature modules
(lib.modules.importApply ./api-feature.nix {
inherit clanLib prefix;
})
]
++
modules = [
# Base module
./service-module.nix
# Feature modules
(lib.modules.importApply ./api-feature.nix {
inherit clanLib prefix;
})
]
++
# Modules of caller
modules;
}

View File

@@ -130,7 +130,8 @@ in
};
modules = [
(import ./all-services-wrapper.nix { inherit directory; })
] ++ modules;
]
++ modules;
};
servicesEval = evalServices {
@@ -139,15 +140,14 @@ in
{
inherit exportsModule;
mappedServices = lib.mapAttrs (_module_ident: instances: {
imports =
[
# Import the resolved module.
# i.e. clan.modules.admin
(builtins.head instances).instance.resolvedModule
] # Include all the instances that correlate to the resolved module
++ (builtins.map (v: {
instances.${v.instanceName}.roles = v.instance.instanceRoles;
}) instances);
imports = [
# Import the resolved module.
# i.e. clan.modules.admin
(builtins.head instances).instance.resolvedModule
] # Include all the instances that correlate to the resolved module
++ (builtins.map (v: {
instances.${v.instanceName}.roles = v.instance.instanceRoles;
}) instances);
}) grouped;
}
];

View File

@@ -756,14 +756,13 @@ in
instanceRes
// {
nixosModule = {
imports =
[
# Result of the applied 'perInstance = {...}: { nixosModule = { ... }; }'
instanceRes.nixosModule
]
++ (map (
s: if builtins.typeOf s == "string" then "${directory}/${s}" else s
) instanceCfg.roles.${roleName}.extraModules);
imports = [
# Result of the applied 'perInstance = {...}: { nixosModule = { ... }; }'
instanceRes.nixosModule
]
++ (map (
s: if builtins.typeOf s == "string" then "${directory}/${s}" else s
) instanceCfg.roles.${roleName}.extraModules);
};
}
@@ -877,7 +876,8 @@ in
}
)
(lib.setDefaultModuleLocation "Via ${config.manifest.name}.perMachine - machine='${machineName}';" machineResult.nixosModule)
] ++ instanceResults.nixosModules;
]
++ instanceResults.nixosModules;
};
}
) config.result.allMachines;

View File

@@ -35,7 +35,8 @@ let
clan.core.settings.directory = clan-core;
}
clan-core.nixosModules.clanCore
] ++ modules;
]
++ modules;
};
in
# lib.warn ''

View File

@@ -45,7 +45,8 @@ lib.mkIf (config.clan.test.useContainers or true) {
{
nativeBuildInputs = [
hostPkgs.makeWrapper
] ++ lib.optionals (!config.skipTypeCheck) [ hostPkgs.mypy ];
]
++ lib.optionals (!config.skipTypeCheck) [ hostPkgs.mypy ];
buildInputs = [ testDriver ];
testScript = config.testScriptString;
preferLocalBuild = true;

View File

@@ -21,7 +21,8 @@ let
colorama
junit-xml
nix
] ++ extraPythonPackages python3Packages;
]
++ extraPythonPackages python3Packages;
nativeBuildInputs = [ setuptools ];
format = "pyproject";
src = ./.;

View File

@@ -1,28 +1,27 @@
{ _class, lib, ... }:
{
imports =
[
./backups.nix
./defaults.nix
./facts
./inventory
./meta/interface.nix
./metadata.nix
./networking.nix
./nix-settings.nix
./options.nix
./outputs.nix
./sops.nix
./vars
]
++ lib.optionals (_class == "nixos") [
./nixos-facter.nix
./vm.nix
./postgresql
./machine-id
./state-version
./wayland-proxy-virtwl.nix
./zerotier
./zfs.nix
];
imports = [
./backups.nix
./defaults.nix
./facts
./inventory
./meta/interface.nix
./metadata.nix
./networking.nix
./nix-settings.nix
./options.nix
./outputs.nix
./sops.nix
./vars
]
++ lib.optionals (_class == "nixos") [
./nixos-facter.nix
./vm.nix
./postgresql
./machine-id
./state-version
./wayland-proxy-virtwl.nix
./zerotier
./zfs.nix
];
}

View File

@@ -90,35 +90,34 @@
default = { };
type = lib.types.attrsOf (
lib.types.submodule (secret: {
options =
{
name = lib.mkOption {
type = lib.types.str;
description = ''
name of the secret
'';
default = secret.config._module.args.name;
defaultText = "attribute name of the secret";
};
path = lib.mkOption {
type = lib.types.path;
description = ''
path to a secret which is generated by the generator
'';
default = config.clan.core.facts.secretPathFunction secret;
defaultText = lib.literalExpression "config.clan.core.facts.secretPathFunction secret";
};
}
// lib.optionalAttrs (config.clan.core.facts.secretStore == "sops") {
groups = lib.mkOption {
type = lib.types.listOf lib.types.str;
default = config.clan.core.sops.defaultGroups;
defaultText = lib.literalExpression "config.clan.core.sops.defaultGroups";
description = ''
Groups to decrypt the secret for. By default we always use the user's key.
'';
};
options = {
name = lib.mkOption {
type = lib.types.str;
description = ''
name of the secret
'';
default = secret.config._module.args.name;
defaultText = "attribute name of the secret";
};
path = lib.mkOption {
type = lib.types.path;
description = ''
path to a secret which is generated by the generator
'';
default = config.clan.core.facts.secretPathFunction secret;
defaultText = lib.literalExpression "config.clan.core.facts.secretPathFunction secret";
};
}
// lib.optionalAttrs (config.clan.core.facts.secretStore == "sops") {
groups = lib.mkOption {
type = lib.types.listOf lib.types.str;
default = config.clan.core.sops.defaultGroups;
defaultText = lib.literalExpression "config.clan.core.sops.defaultGroups";
description = ''
Groups to decrypt the secret for. By default we always use the user's key.
'';
};
};
})
);
description = ''

View File

@@ -175,35 +175,34 @@
default = { };
type = lib.types.attrsOf (
lib.types.submodule (secret: {
options =
{
name = lib.mkOption {
type = lib.types.str;
description = ''
name of the secret
'';
default = secret.config._module.args.name;
defaultText = "attribute name of the secret";
};
path = lib.mkOption {
type = lib.types.str;
description = ''
path to a secret which is generated by the generator
'';
default = config.clan.core.facts.secretPathFunction secret;
defaultText = lib.literalExpression "config.clan.core.facts.secretPathFunction secret";
};
}
// lib.optionalAttrs (config.clan.core.facts.secretModule == "clan_cli.facts.secret_modules.sops") {
groups = lib.mkOption {
type = lib.types.listOf lib.types.str;
default = config.clan.core.sops.defaultGroups;
defaultText = lib.literalExpression "config.clan.core.sops.defaultGroups";
description = ''
Groups to decrypt the secret for. By default we always use the user's key.
'';
};
options = {
name = lib.mkOption {
type = lib.types.str;
description = ''
name of the secret
'';
default = secret.config._module.args.name;
defaultText = "attribute name of the secret";
};
path = lib.mkOption {
type = lib.types.str;
description = ''
path to a secret which is generated by the generator
'';
default = config.clan.core.facts.secretPathFunction secret;
defaultText = lib.literalExpression "config.clan.core.facts.secretPathFunction secret";
};
}
// lib.optionalAttrs (config.clan.core.facts.secretModule == "clan_cli.facts.secret_modules.sops") {
groups = lib.mkOption {
type = lib.types.listOf lib.types.str;
default = config.clan.core.sops.defaultGroups;
defaultText = lib.literalExpression "config.clan.core.sops.defaultGroups";
description = ''
Groups to decrypt the secret for. By default we always use the user's key.
'';
};
};
})
);
};

View File

@@ -16,16 +16,15 @@ let
};
in
{
imports =
[
./public/in_repo.nix
./secret/fs.nix
./secret/sops
./secret/vm.nix
]
++ lib.optionals (_class == "nixos") [
./secret/password-store.nix
];
imports = [
./public/in_repo.nix
./secret/fs.nix
./secret/sops
./secret/vm.nix
]
++ lib.optionals (_class == "nixos") [
./secret/password-store.nix
];
options.clan.core.vars = lib.mkOption {
description = ''

View File

@@ -198,136 +198,135 @@ in
]
)
];
options =
{
name = mkOption {
type = str;
description = ''
name of the public fact
'';
readOnly = true;
default = file.config._module.args.name;
defaultText = "Name of the file";
};
generatorName = mkOption {
type = str;
description = ''
name of the generator
'';
readOnly = true;
default = generator.config._module.args.name;
defaultText = "Name of the generator that generates this file";
};
share = mkOption {
type = bool;
description = ''
Whether the generated vars should be shared between machines.
Shared vars are only generated once, when the first machine using it is deployed.
Subsequent machines will re-use the already generated values.
'';
readOnly = true;
internal = true;
default = generator.config.share;
defaultText = "Mirror of the share flag of the generator";
};
deploy = mkOption {
description = ''
Whether the file should be deployed to the target machine.
options = {
name = mkOption {
type = str;
description = ''
name of the public fact
'';
readOnly = true;
default = file.config._module.args.name;
defaultText = "Name of the file";
};
generatorName = mkOption {
type = str;
description = ''
name of the generator
'';
readOnly = true;
default = generator.config._module.args.name;
defaultText = "Name of the generator that generates this file";
};
share = mkOption {
type = bool;
description = ''
Whether the generated vars should be shared between machines.
Shared vars are only generated once, when the first machine using it is deployed.
Subsequent machines will re-use the already generated values.
'';
readOnly = true;
internal = true;
default = generator.config.share;
defaultText = "Mirror of the share flag of the generator";
};
deploy = mkOption {
description = ''
Whether the file should be deployed to the target machine.
Disable this if the generated file is only used as an input to other generators.
'';
type = bool;
default = true;
};
secret = mkOption {
description = ''
Whether the file should be treated as a secret.
'';
type = bool;
default = true;
};
flakePath = mkOption {
description = ''
The path to the file containing the content of the generated value.
This will be set automatically
'';
type = nullOr path;
default = null;
};
path = mkOption {
description = ''
The path to the file containing the content of the generated value.
This will be set automatically
'';
type = str;
defaultText = ''
builtins.path {
name = "$${generator.config._module.args.name}_$${file.config._module.args.name}";
path = file.config.flakePath;
}
'';
default = builtins.path {
name = "${generator.config._module.args.name}_${file.config._module.args.name}";
Disable this if the generated file is only used as an input to other generators.
'';
type = bool;
default = true;
};
secret = mkOption {
description = ''
Whether the file should be treated as a secret.
'';
type = bool;
default = true;
};
flakePath = mkOption {
description = ''
The path to the file containing the content of the generated value.
This will be set automatically
'';
type = nullOr path;
default = null;
};
path = mkOption {
description = ''
The path to the file containing the content of the generated value.
This will be set automatically
'';
type = str;
defaultText = ''
builtins.path {
name = "$${generator.config._module.args.name}_$${file.config._module.args.name}";
path = file.config.flakePath;
};
};
neededFor = mkOption {
description = ''
This option determines when the secret will be decrypted and deployed to the target machine.
By setting this to `partitioning`, the secret will be deployed prior to running `disko` allowing
you to manage filesystem encryption keys. These will only be deployed when installing the system.
By setting this to `activation`, the secret will be deployed prior to running `nixos-rebuild` or `nixos-install`.
By setting this to `user`, the secret will be deployed prior to users and groups are created, allowing
users' passwords to be managed by vars. The secret will be stored in `/run/secrets-for-users` and `owner` and `group` must be `root`.
'';
type = enum [
"partitioning"
"activation"
"users"
"services"
];
default = "services";
};
owner = mkOption {
description = "The user name or id that will own the file.";
default = "root";
};
group = mkOption {
description = "The group name or id that will own the file.";
default = if _class == "darwin" then "wheel" else "root";
defaultText = lib.literalExpression ''if _class == "darwin" then "wheel" else "root"'';
};
mode = mkOption {
type = strMatching "^[0-7]{4}$";
description = "The unix file mode of the file. Must be a 4-digit octal number.";
default = "0400";
};
value =
mkOption {
description = ''
The content of the generated value.
Only available if the file is not secret.
'';
type = str;
defaultText = "Throws error because the value of a secret file is not accessible";
}
// lib.optionalAttrs file.config.secret {
default = throw "Cannot access value of secret file";
};
}
// (lib.optionalAttrs (_class == "nixos") {
restartUnits = mkOption {
description = ''
A list of systemd units that should be restarted after the file is deployed.
This is useful for services that need to reload their configuration after the file is updated.
WARNING: currently only sops-nix implements this option.
'';
type = listOf str;
default = [ ];
'';
default = builtins.path {
name = "${generator.config._module.args.name}_${file.config._module.args.name}";
path = file.config.flakePath;
};
});
};
neededFor = mkOption {
description = ''
This option determines when the secret will be decrypted and deployed to the target machine.
By setting this to `partitioning`, the secret will be deployed prior to running `disko` allowing
you to manage filesystem encryption keys. These will only be deployed when installing the system.
By setting this to `activation`, the secret will be deployed prior to running `nixos-rebuild` or `nixos-install`.
By setting this to `user`, the secret will be deployed prior to users and groups are created, allowing
users' passwords to be managed by vars. The secret will be stored in `/run/secrets-for-users` and `owner` and `group` must be `root`.
'';
type = enum [
"partitioning"
"activation"
"users"
"services"
];
default = "services";
};
owner = mkOption {
description = "The user name or id that will own the file.";
default = "root";
};
group = mkOption {
description = "The group name or id that will own the file.";
default = if _class == "darwin" then "wheel" else "root";
defaultText = lib.literalExpression ''if _class == "darwin" then "wheel" else "root"'';
};
mode = mkOption {
type = strMatching "^[0-7]{4}$";
description = "The unix file mode of the file. Must be a 4-digit octal number.";
default = "0400";
};
value =
mkOption {
description = ''
The content of the generated value.
Only available if the file is not secret.
'';
type = str;
defaultText = "Throws error because the value of a secret file is not accessible";
}
// lib.optionalAttrs file.config.secret {
default = throw "Cannot access value of secret file";
};
}
// (lib.optionalAttrs (_class == "nixos") {
restartUnits = mkOption {
description = ''
A list of systemd units that should be restarted after the file is deployed.
This is useful for services that need to reload their configuration after the file is updated.
WARNING: currently only sops-nix implements this option.
'';
type = listOf str;
default = [ ];
};
});
})
);
};

View File

@@ -43,23 +43,22 @@ in
secrets = lib.listToAttrs (
map (secret: {
name = "vars/${secret.generator}/${secret.name}";
value =
{
inherit (secret)
owner
group
mode
neededForUsers
;
sopsFile = builtins.path {
name = "${secret.generator}_${secret.name}";
path = secretPath secret;
};
format = "binary";
}
// (lib.optionalAttrs (_class == "nixos") {
inherit (secret) restartUnits;
});
value = {
inherit (secret)
owner
group
mode
neededForUsers
;
sopsFile = builtins.path {
name = "${secret.generator}_${secret.name}";
path = secretPath secret;
};
format = "binary";
}
// (lib.optionalAttrs (_class == "nixos") {
inherit (secret) restartUnits;
});
}) (builtins.filter (x: builtins.pathExists (secretPath x)) vars)
);

View File

@@ -8,16 +8,15 @@ let
...
}:
{
imports =
[
./clanCore
inputs.sops-nix."${_class}Modules".sops
]
++ lib.optionals (_class == "nixos") [
inputs.nixos-facter-modules.nixosModules.facter
inputs.disko.nixosModules.default
inputs.data-mesher.nixosModules.data-mesher
];
imports = [
./clanCore
inputs.sops-nix."${_class}Modules".sops
]
++ lib.optionals (_class == "nixos") [
inputs.nixos-facter-modules.nixosModules.facter
inputs.disko.nixosModules.default
inputs.data-mesher.nixosModules.data-mesher
];
config = {
clan.core.clanPkgs = lib.mkDefault self.packages.${pkgs.hostPlatform.system};
};

View File

@@ -90,7 +90,8 @@ pythonRuntime.pkgs.buildPythonApplication {
# gtk4 deps
wrapGAppsHook4
] ++ runtimeDependencies;
]
++ runtimeDependencies;
# The necessity of setting buildInputs and propagatedBuildInputs to the
# same values for your Python package within Nix largely stems from ensuring
@@ -98,7 +99,8 @@ pythonRuntime.pkgs.buildPythonApplication {
# at build time and runtime,
propagatedBuildInputs = [
(pythonRuntime.withPackages (ps: clan-cli-module ++ (pyDeps ps)))
] ++ runtimeDependencies;
]
++ runtimeDependencies;
# also re-expose dependencies so we test them in CI
passthru = {

View File

@@ -35,15 +35,14 @@ mkShell {
clan-app-ui
];
packages =
[
# required for reload-python-api.sh script
json2ts
]
++ (lib.optionals stdenv.hostPlatform.isLinux [
# for viewing the storybook in a webkit-based browser to match webview
luakit
]);
packages = [
# required for reload-python-api.sh script
json2ts
]
++ (lib.optionals stdenv.hostPlatform.isLinux [
# for viewing the storybook in a webkit-based browser to match webview
luakit
]);
inherit (clan-app) propagatedBuildInputs;
@@ -63,64 +62,64 @@ mkShell {
++ (clan-app.devshellPyDeps ps)
))
ruff
] ++ clan-app.runtimeDeps;
]
++ clan-app.runtimeDeps;
shellHook =
''
export CLAN_CORE_PATH=$(git rev-parse --show-toplevel)
shellHook = ''
export CLAN_CORE_PATH=$(git rev-parse --show-toplevel)
## Clan app
pushd "$CLAN_CORE_PATH/pkgs/clan-app"
## Clan app
pushd "$CLAN_CORE_PATH/pkgs/clan-app"
# Add clan-app command to PATH
export PATH="$(pwd)/bin":"$PATH"
# Add clan-app command to PATH
export PATH="$(pwd)/bin":"$PATH"
# Add current package to PYTHONPATH
export PYTHONPATH="$(pwd)''${PYTHONPATH:+:$PYTHONPATH:}"
popd
# Add current package to PYTHONPATH
export PYTHONPATH="$(pwd)''${PYTHONPATH:+:$PYTHONPATH:}"
popd
# Add clan-cli to the python path so that we can import it without building it in nix first
export PYTHONPATH="$CLAN_CORE_PATH/pkgs/clan-cli":"$PYTHONPATH"
# Add clan-cli to the python path so that we can import it without building it in nix first
export PYTHONPATH="$CLAN_CORE_PATH/pkgs/clan-cli":"$PYTHONPATH"
export XDG_DATA_DIRS=$GSETTINGS_SCHEMAS_PATH:$XDG_DATA_DIRS
export WEBVIEW_LIB_DIR=${webview-lib}/lib
export OPENAPI_FILE="${clan-lib-openapi}"
export SWAGGER_UI_DIST="${swagger-ui-dist}/dist"
export XDG_DATA_DIRS=$GSETTINGS_SCHEMAS_PATH:$XDG_DATA_DIRS
export WEBVIEW_LIB_DIR=${webview-lib}/lib
export OPENAPI_FILE="${clan-lib-openapi}"
export SWAGGER_UI_DIST="${swagger-ui-dist}/dist"
## Webview UI
# Add clan-app-ui scripts to PATH
pushd "$CLAN_CORE_PATH/pkgs/clan-app/ui"
export NODE_PATH="$(pwd)/node_modules"
export PATH="$NODE_PATH/.bin:$(pwd)/bin:$PATH"
cp -r ${self'.packages.fonts} .fonts
chmod -R +w .fonts
mkdir -p api
cp -r ${clan-ts-api}/* api
chmod -R +w api
popd
## Webview UI
# Add clan-app-ui scripts to PATH
pushd "$CLAN_CORE_PATH/pkgs/clan-app/ui"
export NODE_PATH="$(pwd)/node_modules"
export PATH="$NODE_PATH/.bin:$(pwd)/bin:$PATH"
cp -r ${self'.packages.fonts} .fonts
chmod -R +w .fonts
mkdir -p api
cp -r ${clan-ts-api}/* api
chmod -R +w api
popd
# configure process-compose
if test -f "$CLAN_CORE_PATH/pkgs/clan-app/.local.env"; then
source "$CLAN_CORE_PATH/pkgs/clan-app/.local.env"
fi
# configure process-compose
if test -f "$CLAN_CORE_PATH/pkgs/clan-app/.local.env"; then
source "$CLAN_CORE_PATH/pkgs/clan-app/.local.env"
fi
export PC_CONFIG_FILES="$CLAN_CORE_PATH/pkgs/clan-app/process-compose.yaml"
export PC_CONFIG_FILES="$CLAN_CORE_PATH/pkgs/clan-app/process-compose.yaml"
echo -e "${GREEN}To launch a qemu VM for testing, run:\n start-vm <number of VMs>${NC}"
''
+
# todo darwin support needs some work
(lib.optionalString stdenv.hostPlatform.isLinux ''
# configure playwright for storybook snapshot testing
export PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=1
export PLAYWRIGHT_BROWSERS_PATH=${
playwright-driver.browsers.override {
withFfmpeg = false;
withFirefox = false;
withChromium = false;
withChromiumHeadlessShell = true;
}
echo -e "${GREEN}To launch a qemu VM for testing, run:\n start-vm <number of VMs>${NC}"
''
+
# todo darwin support needs some work
(lib.optionalString stdenv.hostPlatform.isLinux ''
# configure playwright for storybook snapshot testing
export PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=1
export PLAYWRIGHT_BROWSERS_PATH=${
playwright-driver.browsers.override {
withFfmpeg = false;
withFirefox = false;
withChromium = false;
withChromiumHeadlessShell = true;
}
export PLAYWRIGHT_HOST_PLATFORM_OVERRIDE="ubuntu-24.04"
'');
}
export PLAYWRIGHT_HOST_PLATFORM_OVERRIDE="ubuntu-24.04"
'');
}

View File

@@ -156,93 +156,92 @@ pythonRuntime.pkgs.buildPythonApplication {
propagatedBuildInputs = [ pythonRuntimeWithDeps ] ++ bundledRuntimeDependencies;
passthru.tests =
{
clan-deps = pkgs.runCommand "clan-deps" { } ''
# ${builtins.toString (builtins.attrValues testRuntimeDependenciesMap)}
touch $out
'';
clan-pytest-without-core =
runCommand "clan-pytest-without-core"
{
nativeBuildInputs = testDependencies;
closureInfo = pkgs.closureInfo {
rootPaths = [
templateDerivation
];
};
}
''
set -euo pipefail
cp -r ${sourceWithTests} ./src
chmod +w -R ./src
cd ./src
passthru.tests = {
clan-deps = pkgs.runCommand "clan-deps" { } ''
# ${builtins.toString (builtins.attrValues testRuntimeDependenciesMap)}
touch $out
'';
clan-pytest-without-core =
runCommand "clan-pytest-without-core"
{
nativeBuildInputs = testDependencies;
closureInfo = pkgs.closureInfo {
rootPaths = [
templateDerivation
];
};
}
''
set -euo pipefail
cp -r ${sourceWithTests} ./src
chmod +w -R ./src
cd ./src
export NIX_STATE_DIR=$TMPDIR/nix IN_NIX_SANDBOX=1 PYTHONWARNINGS=error
export NIX_STATE_DIR=$TMPDIR/nix IN_NIX_SANDBOX=1 PYTHONWARNINGS=error
# required to prevent concurrent 'nix flake lock' operations
export CLAN_TEST_STORE=$TMPDIR/store
export LOCK_NIX=$TMPDIR/nix_lock
mkdir -p "$CLAN_TEST_STORE/nix/store"
# required to prevent concurrent 'nix flake lock' operations
export CLAN_TEST_STORE=$TMPDIR/store
export LOCK_NIX=$TMPDIR/nix_lock
mkdir -p "$CLAN_TEST_STORE/nix/store"
# limit build cores to 16
jobs="$((NIX_BUILD_CORES>16 ? 16 : NIX_BUILD_CORES))"
# limit build cores to 16
jobs="$((NIX_BUILD_CORES>16 ? 16 : NIX_BUILD_CORES))"
python -m pytest -m "not impure and not with_core" -n $jobs ./clan_cli ./clan_lib
touch $out
'';
}
// lib.optionalAttrs (!stdenv.isDarwin) {
# disabled on macOS until we fix all remaining issues
clan-pytest-with-core =
runCommand "clan-pytest-with-core"
{
nativeBuildInputs = testDependencies;
buildInputs = [
python -m pytest -m "not impure and not with_core" -n $jobs ./clan_cli ./clan_lib
touch $out
'';
}
// lib.optionalAttrs (!stdenv.isDarwin) {
# disabled on macOS until we fix all remaining issues
clan-pytest-with-core =
runCommand "clan-pytest-with-core"
{
nativeBuildInputs = testDependencies;
buildInputs = [
pkgs.bash
pkgs.coreutils
pkgs.nix
];
closureInfo = pkgs.closureInfo {
rootPaths = [
templateDerivation
pkgs.bash
pkgs.coreutils
pkgs.nix
pkgs.jq.dev
pkgs.stdenv
pkgs.stdenvNoCC
pkgs.openssh
pkgs.shellcheck-minimal
pkgs.mkpasswd
pkgs.xkcdpass
pkgs.pass
nix-select
];
closureInfo = pkgs.closureInfo {
rootPaths = [
templateDerivation
pkgs.bash
pkgs.coreutils
pkgs.jq.dev
pkgs.stdenv
pkgs.stdenvNoCC
pkgs.openssh
pkgs.shellcheck-minimal
pkgs.mkpasswd
pkgs.xkcdpass
pkgs.pass
nix-select
];
};
}
''
set -euo pipefail
cp -r ${sourceWithTests} ./src
chmod +w -R ./src
cd ./src
};
}
''
set -euo pipefail
cp -r ${sourceWithTests} ./src
chmod +w -R ./src
cd ./src
${setupNixInNix}
${setupNixInNix}
export CLAN_CORE_PATH=${clan-core-path}
export PYTHONWARNINGS=error
export CLAN_CORE_PATH=${clan-core-path}
export PYTHONWARNINGS=error
# used for tests without flakes
export NIXPKGS=${nixpkgs}
export NIX_SELECT=${nix-select}
# used for tests without flakes
export NIXPKGS=${nixpkgs}
export NIX_SELECT=${nix-select}
# limit build cores to 16
jobs="$((NIX_BUILD_CORES>16 ? 16 : NIX_BUILD_CORES))"
# limit build cores to 16
jobs="$((NIX_BUILD_CORES>16 ? 16 : NIX_BUILD_CORES))"
# Run all tests with core marker
python -m pytest -m "not impure and with_core" -n $jobs ./clan_cli ./clan_lib
touch $out
'';
};
# Run all tests with core marker
python -m pytest -m "not impure and with_core" -n $jobs ./clan_cli ./clan_lib
touch $out
'';
};
passthru.nixpkgs = nixpkgs';
passthru.devshellPyDeps = ps: (pyTestDeps ps) ++ (pyDeps ps) ++ (devDeps ps);

View File

@@ -22,7 +22,8 @@ mkShell {
))
ruff
nix-unit
] ++ clan-cli.runtimeDependencies;
]
++ clan-cli.runtimeDependencies;
inputsFrom = [ self'.devShells.default ];

View File

@@ -34,18 +34,17 @@ let
};
# Dependencies that are directly used in the project but nor from internal python packages
externalPythonDeps =
[
pygobject3
pygobject-stubs
gtk4
libadwaita
adwaita-icon-theme
]
++ clan-cli.propagatedBuildInputs
++ lib.optionals (!stdenv.isDarwin) [
webkitgtk_6_0
];
externalPythonDeps = [
pygobject3
pygobject-stubs
gtk4
libadwaita
adwaita-icon-theme
]
++ clan-cli.propagatedBuildInputs
++ lib.optionals (!stdenv.isDarwin) [
webkitgtk_6_0
];
# Deps including python packages from the local project
allPythonDeps = [ (python.pkgs.toPythonModule clan-cli) ] ++ externalPythonDeps;

View File

@@ -27,19 +27,18 @@ in
mkShell {
inherit (clan-vm-manager) nativeBuildInputs;
name = "clan-vm-manager";
buildInputs =
[
ruff
gtk4.dev # has the demo called 'gtk4-widget-factory'
libadwaita.devdoc # has the demo called 'adwaita-1-demo'
]
++ devshellTestDeps
buildInputs = [
ruff
gtk4.dev # has the demo called 'gtk4-widget-factory'
libadwaita.devdoc # has the demo called 'adwaita-1-demo'
]
++ devshellTestDeps
# Dependencies for testing for linux hosts
++ (lib.optionals stdenv.isLinux [
xdg-utils # install desktop files
desktop-file-utils # verify desktop files
]);
# Dependencies for testing for linux hosts
++ (lib.optionals stdenv.isLinux [
xdg-utils # install desktop files
desktop-file-utils # verify desktop files
]);
shellHook = ''
export GIT_ROOT=$(git rev-parse --show-toplevel)