How to share variables between derivations?

I have the following files:

.
├── ansible-collections
│   └── default.nix
├── ansible-environment
│   └── default.nix
├── ansible-wrapper
│   └── default.nix
├── container-image
│   └── default.nix
├── ansible-code
│   └── default.nix
├── read-vault-pass
│   ├── default.nix
│   └── read_vault_pass.py
└── default.nix

pkgs/default.nix

{
  pkgs,
  root,
  python,
  pythonProdEnvironment,
}:
let
  callPackage = pkgs.lib.callPackageWith (pkgs // packages);
  packages = {
    ansible-collections = callPackage ./ansible-collections {
      prodEnv = pythonProdEnvironment;
      inherit root;
    };
    ansible = callPackage ./ansible-code { inherit root; };
    ansible-environment = callPackage ./ansible-environment { };
    ansible-wrapper = callPackage ./ansible-wrapper { };
    container = callPackage ./container-image { };
  };
in
packages

The ansible-environment contains an attribute set with variables that I would like to share between the derivations and the projects mkShellNoCC defined in the flake.nix.

ansible-environment/default.nix

{
  ansible-collections,
  glibcLocales,
  readVaultPass,
}:
{
  ANSIBLE_COLLECTIONS_PATH = ansible-collections;
  ANSIBLE_VAULT_PASSWORD_FILE = "${readVaultPass}/bin/read-vault-pass";
  LOCALE_ARCHIVE = "${glibcLocales}/lib/locale/locale-archive";
}

I was able to make it work like this:

ansible-wrapper/default.nix

{
  ansible-environment,
  ansible,
  bash,
  openssh,
  pythonProdEnvironment,
  rsync,
  sshpass,
  writeShellApplication,
}:
writeShellApplication {
  name = "ansible-wrapper";
  runtimeEnv = {
    inherit (ansible-environment)
      ANSIBLE_COLLECTIONS_PATH
      ANSIBLE_VAULT_PASSWORD_FILE
      LOCALE_ARCHIVE
      ;
  };
  runtimeInputs = [
    ansible
    bash
    openssh
    pythonProdEnvironment
    rsync # required for ansible.posix.synchronize
    sshpass # required to use passwords with SSH
  ];
  text = ''
    if [ $# -eq 0 ]; then
        echo "No input arguments provided."
        exit 1
    fi
    cd "''\${OUR_ANSIBLE_DIRECTORY:-${ansible}}"
    "$@"
  '';
}

However since ansible-environment is an attribute set, shouldn’t it be possible to just set runtimeEnv = ansible-environment?
But when I try that I get the error:

error: cannot coerce a set to a string: { ansible-collections = false; glibcLocales = false; readVaultPass = false; }

Same goes for mkShellNoCC shouldn’t something like the following work?
It builds without error but the variables aren’t available in the shell.

mkShellNoCC { } // ourpackages.ansible-environment;

I believe callPackage makes the returned attrset overrideable, and the .override lambda cannot be converted to a string.

I assume this is the issue:

mkShellNoCC ({ } // ourpackages.ansible-environment);

I can confirm that the first works when I don’t use callPackage as I converted it in the meantime to a plain value inside packages.
Out of curiosity would their be a way to use an overrideable the way I wanted to?

The mkShellNoCC works now as well with you solution, but couldn’t this be as well because I converted it to a plain attribute set?

Current state of pkgs/default.nix

{
  pkgs,
  root,
  python,
  pythonProdEnvironment,
}:
let
  callPackage = pkgs.lib.callPackageWith (pkgs // packages);
  packages = {
    ansible-collections = callPackage ./ansible-collections {
      prodEnv = pythonProdEnvironment;
      inherit root;
    };
    ansible-dependencies = [
      pkgs.openssh # required to connect via SSH
      pkgs.rsync # required for ansible.posix.synchronize
      pkgs.sshpass # required to use passwords with SSH
    ];
    ansible-environment = {
      ANSIBLE_COLLECTIONS_PATH = packages.ansible-collections;
      ANSIBLE_CONFIG = "${packages.our-ansible}/ansible.cfg";
      ANSIBLE_LIBRARY = "${packages.our-ansible}/library";
      ANSIBLE_ROLES_PATH = "${packages.our-ansible}/roles";
      ANSIBLE_VAULT_PASSWORD_FILE = "${packages.readVaultPass}/bin/read-vault-pass";
      OUR_ANSIBLE_DIRECTORY = "${packages.our-ansible}";
      LOCALE_ARCHIVE = "${pkgs.glibcLocales}/lib/locale/locale-archive";
    };
    ansible-wrapper = callPackage ./ansible-wrapper { };
    container = callPackage ./container-image { };
    our-ansible = callPackage ./our-ansible { inherit root; };
    management-server = callPackage ./management-server { };
    readVaultPass = callPackage ./read-vault-pass { inherit python; };
    vaulti = callPackage ./vaulti { };
    inherit pythonProdEnvironment;
  };
in
packages

Vieweing the source i don’t see a way to avoid callPackage calling makeOverridable.

The result is however only the attributes override and overrideDerivation which could be filtered using lib.removeAttrs

nix-repl> callPackage ({ hello }: { asd = "${hello}/bin/hello"; }) {}                        
{
  asd = "/nix/store/3acqrvb06vw0w3s9fa3wci433snbi2bg-hello-2.12.1/bin/hello";
  override = { ... };
  overrideDerivation = «lambda overrideDerivation @ /nix/store/ikdyp8v1qhwkg48x68mxipih5f3vid2v-source/lib/customisation.nix:151:32»;
}

I admit I don’t understand this :slight_smile: