{ # callPackage args argcomplete, gitMinimal, gnupg, installShellFiles, lib, nix, pkgs, pytest-cov, pytest-subprocess, pytest-timeout, pytest-xdist, pytest, python3, runCommand, setuptools, stdenv, # custom args clan-core-path, nixpkgs, includedRuntimeDeps, inventory-schema, classgen, }: let pythonDependencies = [ argcomplete # Enables shell completions ]; # load nixpkgs runtime dependencies from a json file # This file represents an allow list at the same time that is checked by the run_cmd # implementation in nix.py runtimeDependenciesAsSet = lib.filterAttrs (_name: pkg: !pkg.meta.unsupported or false) ( lib.genAttrs (lib.importJSON ./clan_cli/nix/allowed-programs.json) (name: pkgs.${name}) ); runtimeDependencies = lib.attrValues runtimeDependenciesAsSet; testDependencies = runtimeDependencies ++ [ gnupg stdenv.cc # Compiler used for certain native extensions ] ++ pythonDependencies ++ [ pytest pytest-cov # Generate coverage reports pytest-subprocess # fake the real subprocess behavior to make your tests more independent. pytest-xdist # Run tests in parallel on multiple cores pytest-timeout # Add timeouts to your tests ]; # Setup Python environment with all dependencies for running tests pythonWithTestDeps = python3.withPackages (_ps: testDependencies); source = runCommand "clan-cli-source" { } '' cp -r ${./.} $out chmod -R +w $out ln -sf ${nixpkgs'} $out/clan_cli/nixpkgs ${classgen}/bin/classgen ${inventory-schema}/schema.json $out/clan_cli/inventory/classes.py ''; # Create a custom nixpkgs for use within the project nixpkgs' = runCommand "nixpkgs" { nativeBuildInputs = [ nix ]; } '' mkdir $out cat > $out/flake.nix << EOF { description = "dependencies for the clan-cli"; inputs = { nixpkgs.url = "path://${nixpkgs}"; }; outputs = _inputs: { }; } EOF ln -sf ${nixpkgs} $out/path nix flake update $out \ --store ./. \ --extra-experimental-features 'nix-command flakes' ''; in python3.pkgs.buildPythonApplication { name = "clan-cli"; src = source; format = "pyproject"; # Arguments for the wrapper to unset LD_LIBRARY_PATH to avoid glibc version issues makeWrapperArgs = [ "--unset LD_LIBRARY_PATH" # TODO: remove gitMinimal here and use the one from runtimeDependencies "--suffix" "PATH" ":" "${gitMinimal}/bin/git" ] # include selected runtime dependencies in the PATH ++ lib.concatMap (p: [ "--prefix" "PATH" ":" p ]) includedRuntimeDeps ++ [ "--set" "CLAN_STATIC_PROGRAMS" (lib.concatStringsSep ":" includedRuntimeDeps) ]; nativeBuildInputs = [ setuptools installShellFiles ]; propagatedBuildInputs = pythonDependencies; # Define and expose the tests and checks to run in CI passthru.tests = (lib.mapAttrs' (n: lib.nameValuePair "clan-dep-${n}") runtimeDependenciesAsSet) // { clan-pytest-without-core = runCommand "clan-pytest-without-core" { nativeBuildInputs = [ pythonWithTestDeps ] ++ testDependencies; } '' cp -r ${source} ./src chmod +w -R ./src cd ./src export NIX_STATE_DIR=$TMPDIR/nix IN_NIX_SANDBOX=1 ${pythonWithTestDeps}/bin/python -m pytest -m "not impure and not with_core" ./tests touch $out ''; clan-pytest-with-core = runCommand "clan-pytest-with-core" { nativeBuildInputs = [ pythonWithTestDeps ] ++ testDependencies; } '' cp -r ${source} ./src chmod +w -R ./src cd ./src export CLAN_CORE=${clan-core-path} export NIX_STATE_DIR=$TMPDIR/nix IN_NIX_SANDBOX=1 ${pythonWithTestDeps}/bin/python -m pytest -m "not impure and with_core" ./tests touch $out ''; check-for-breakpoints = runCommand "breakpoints" { } '' if grep --include \*.py -Rq "breakpoint()" ${source}; then echo "breakpoint() found in ${source}:" grep --include \*.py -Rn "breakpoint()" ${source} exit 1 fi touch $out ''; }; passthru.nixpkgs = nixpkgs'; passthru.testDependencies = testDependencies; passthru.pythonWithTestDeps = pythonWithTestDeps; passthru.runtimeDependencies = runtimeDependencies; passthru.runtimeDependenciesAsSet = runtimeDependenciesAsSet; postInstall = '' cp -r ${nixpkgs'} $out/${python3.sitePackages}/clan_cli/nixpkgs installShellCompletion --bash --name clan \ <(${argcomplete}/bin/register-python-argcomplete --shell bash clan) installShellCompletion --fish --name clan.fish \ <(${argcomplete}/bin/register-python-argcomplete --shell fish clan) installShellCompletion --zsh --name _clan \ <(${argcomplete}/bin/register-python-argcomplete --shell bash clan) ''; # Clean up after the package to avoid leaking python packages into a devshell # TODO: factor seperate cli / API packages postFixup = '' rm $out/nix-support/propagated-build-inputs ''; checkPhase = '' PYTHONPATH= $out/bin/clan --help ''; meta.mainProgram = "clan"; }