Files
clan-core/pkgs/clan-cli/flake-module.nix
DavHau 61576649ff vars: make all python tests work in nix sandbox
- generate a flake.lock file for each template by copying the clan-core flake.lock and modifying it

- call nix build with --store for tests inside the sandbox
2024-11-27 14:32:02 +07:00

202 lines
7.1 KiB
Nix

{
inputs,
self,
lib,
...
}:
{
perSystem =
{
self',
pkgs,
...
}:
let
flakeLock = lib.importJSON (self + /flake.lock);
flakeInputs = builtins.removeAttrs inputs [ "self" ];
flakeLockVendoredDeps =
flakeLock:
flakeLock
// {
nodes =
flakeLock.nodes
// (lib.flip lib.mapAttrs flakeInputs (
name: _:
# remove follows and let 'nix flake lock' re-compute it later
# (lib.removeAttrs flakeLock.nodes.${name} ["inputs"])
flakeLock.nodes.${name}
// {
locked = {
inherit (flakeLock.nodes.${name}.locked) narHash;
lastModified =
# lol, nixpkgs has a different timestamp on the fs???
if name == "nixpkgs" then 0 else 1;
path = "${inputs.${name}}";
type = "path";
};
}
));
};
clanCoreLock = flakeLockVendoredDeps flakeLock;
clanCoreLockFile = builtins.toFile "clan-core-flake.lock" (builtins.toJSON clanCoreLock);
clanCoreNode = {
inputs = lib.mapAttrs (name: _input: name) flakeInputs;
locked = {
lastModified = 1;
path = "${self}";
type = "path";
};
original = {
type = "tarball";
url = "https://git.clan.lol/clan/clan-core/archive/main.tar.gz";
};
};
# generate a lock file that nix will accept for our flake templates,
# in order to not require internet access during tests.
templateLock = clanCoreLock // {
nodes = clanCoreLock.nodes // {
clan-core = clanCoreNode;
nixpkgs-lib = clanCoreLock.nodes.nixpkgs; # required by flake-parts
root = clanCoreLock.nodes.root // {
inputs = clanCoreLock.nodes.root.inputs // {
clan-core = "clan-core";
nixpkgs = "nixpkgs";
nixpkgs-lib = "nixpkgs-lib";
};
};
};
};
templateLockFile = builtins.toFile "template-flake.lock" (builtins.toJSON templateLock);
clanCoreWithVendoredDeps =
pkgs.runCommand "clan-core-with-vendored-deps"
{
buildInputs = [
pkgs.findutils
pkgs.git
pkgs.jq
pkgs.nix
];
}
''
set -e
export HOME=$(realpath .)
export NIX_STATE_DIR=$HOME
cp -r ${self} $out
chmod +w -R $out
cp ${clanCoreLockFile} $out/flake.lock
nix flake lock $out --extra-experimental-features 'nix-command flakes'
clanCoreHash=$(nix hash path ${self} --extra-experimental-features 'nix-command')
for templateDir in $(find $out/templates -mindepth 1 -maxdepth 1 -type d); do
if ! [ -e "$templateDir/flake.nix" ]; then
continue
fi
cp ${templateLockFile} $templateDir/flake.lock
cat $templateDir/flake.lock | jq ".nodes.\"clan-core\".locked.narHash = \"$clanCoreHash\"" > $templateDir/flake.lock.final
mv $templateDir/flake.lock.final $templateDir/flake.lock
nix flake lock $templateDir --extra-experimental-features 'nix-command flakes'
done
'';
in
{
devShells.clan-cli = pkgs.callPackage ./shell.nix {
inherit (self'.packages) clan-cli clan-cli-full;
inherit self';
};
packages = {
clan-cli = pkgs.python3.pkgs.callPackage ./default.nix {
inherit (inputs) nixpkgs;
inherit (self'.packages) classgen;
inherit (self'.legacyPackages.schemas) inventory-schema-abstract;
clan-core-path = clanCoreWithVendoredDeps;
includedRuntimeDeps = [
"age"
"git"
];
};
clan-cli-full = pkgs.python3.pkgs.callPackage ./default.nix {
inherit (inputs) nixpkgs;
inherit (self'.packages) classgen;
inherit (self'.legacyPackages.schemas) inventory-schema-abstract;
clan-core-path = clanCoreWithVendoredDeps;
includedRuntimeDeps = lib.importJSON ./clan_cli/nix/allowed-programs.json;
};
clan-cli-docs = pkgs.stdenv.mkDerivation {
name = "clan-cli-docs";
src = ./.;
buildInputs = [
# TODO: see postFixup clan-cli/default.nix:L188
pkgs.python3
self'.packages.clan-cli.propagatedBuildInputs
];
installPhase = ''
${self'.packages.classgen}/bin/classgen ${self'.legacyPackages.schemas.inventory-schema-abstract}/schema.json ./clan_cli/inventory/classes.py --stop-at "Service"
python docs.py reference
mkdir -p $out
cp -r out/* $out
ls -lah $out
'';
};
clan-ts-api = pkgs.stdenv.mkDerivation {
name = "clan-ts-api";
src = ./.;
buildInputs = [
pkgs.python3
pkgs.json2ts
pkgs.jq
];
installPhase = ''
${self'.packages.classgen}/bin/classgen ${self'.legacyPackages.schemas.inventory-schema-abstract}/schema.json ./clan_cli/inventory/classes.py --stop-at "Service"
mkdir -p $out
# Retrieve python API Typescript types
python api.py > $out/API.json
json2ts --input $out/API.json > $out/API.ts
# Retrieve python API Typescript types
# delete the reserved tags from typechecking because the conversion library doesn't support them
jq 'del(.properties.tags.properties)' ${self'.legacyPackages.schemas.inventory}/schema.json > schema.json
json2ts --input schema.json > $out/Inventory.ts
cp ${self'.legacyPackages.schemas.inventory}/* $out
'';
};
default = self'.packages.clan-cli;
};
checks = self'.packages.clan-cli.tests // {
inventory-classes-up-to-date = pkgs.stdenv.mkDerivation {
name = "inventory-classes-up-to-date";
src = ./clan_cli/inventory;
env = {
classFile = "classes.py";
};
installPhase = ''
${self'.packages.classgen}/bin/classgen ${self'.legacyPackages.schemas.inventory-schema-abstract}/schema.json b_classes.py --stop-at "Service"
file1=$classFile
file2=b_classes.py
echo "Comparing $file1 and $file2"
if cmp -s "$file1" "$file2"; then
echo "Files are identical"
echo "Classes file is up to date"
else
echo "Classes file is out of date or has been modified"
echo "run 'direnv reload' in the pkgs/clan-cli directory to refresh the classes file"
echo "--------------------------------\n"
diff "$file1" "$file2"
echo "--------------------------------\n\n"
exit 1
fi
touch $out
'';
};
};
};
}