Closed Mikilio closed 1 year ago
I also wanted to add that the only obvious workaround does not work:
{
description = "virtual environments";
inputs.devshell.url = "github:numtide/devshell";
inputs.flake-utils.url = "github:numtide/flake-utils";
inputs.sops-nix = {
url = "github:Mic92/sops-nix";
inputs.nixpkgs.follows = "nixpkgs";
};
outputs = { self, flake-utils, devshell, sops-nix, nixpkgs }:
flake-utils.lib.eachDefaultSystem (system: {
devShell =
let
pkgs = import nixpkgs {
inherit system;
overlays = [ devshell.overlays.default ];
};
extraConfig = { config, lib, pkgs, options, ... }:
with lib;
{
config.devshell = {
startup_env = mkForce (concatStringsSep "\n" [
(concatStringsSep "\n" config.env)
"test=( \"1\" \"2\" \"3\")\nexport TEST=(\"\${test[@]}\")"
]);
packages = [
sops-nix.packages.${system}.sops-import-keys-hook
];
};
};
in pkgs.devshell.mkShell {
imports = [
(pkgs.devshell.importTOML ./devshell.toml)
extraConfig
];
};
});
}
as echo $TEST
prints nothing
On the system level, environment variables can only be expressed as <string>=<string>
.
Bash uses some special encoding to add support for exporting functions and arrays, but it doesn't work unless both the parent and child processes are Bash. So if you have an intermediate tool like direnv, or use another type of shell, it will be lost.
I think I would encode the value as JSON and decode it in the host shell using jq
.
Indeed I'm using both direnv and a different shell (zsh). I think I'll have to encode it in some way. Unfortunately it's very hard for me to find out how to attach shellHooks and where they will run. Having to decode the environment variable myself and then run the script kind of defeats the purpose of my devshell.
Aside from the topic about the workaround I still think that some form of list and attribute set as environment variables for shellHooks should be allowed because that was possible with mkShell and devshell is supposed to replace it.
So I did some research (nix is such a deep hole) and came upon this. It describes how derivation
works
Every attribute is passed as an environment variable to the builder. Attribute values are translated to environment variables as follows:
Strings and numbers are just passed verbatim.
A path (e.g., ../foo/sources.tar) causes the referenced file to be copied to the store; its location in the store is put in the environment variable. The idea is that all sources should reside in the Nix store, since all inputs to a derivation should reside in the Nix store.
A derivation causes that derivation to be built prior to the present derivation; its default output path is put in the environment variable.
Lists of the previous types are also allowed. They are simply concatenated, separated by spaces.
true is passed as the string 1, false and null are passed as an empty string.
This is what I was looking for to provide variables to shellHooks
The derivation for the shell is built here. So to make things backwards compatible we need a way to insert variables there.
Personally I decided to just ditch the packaged shellHooks I want to use and instead just copy the scripts and paste them in config.devshell.startup
.
Maybe better documentation for this would be nice, so people know about this without reading the source.
Also an option to set variables only for the hook would be nice. Example:
[[env]]
name = "foo"
hookOnly = "bar"
I wouldn't want to unset the variables in a script because it would create a discrepancy between what's in the TOML and what's real.
But for me the issue is resolved.
What you can do is execute the devshell directly. Unlike pkgs.mkShell
, devshell.mkShell
also has an entrypoint program that spawns bash if no arguments are passed. The only downside is that the shell is then bash.
The TL;DR is that, for what I wanted to do, the environment variables are not the issue but my inability to set nativeBuildInputs
in the final derivation is.
That is how most packages add shell hooks. They then exist in the same derivation. This means that shellHook
is in scope. This means they can append to it. In devshells everything is kind of done by env.bash
I don't feel entitled to decide if and how this is going to be solved. For now I'll stick to my solution.
Since I decided to port any packages that add hooks to simple executables that I can add to startup, I will conclude this issue as "won't" fix. It is the better design choice anyway because it's less complex and easier to maintain in exchange for being just a bit more tedious to configure for the consumer.
I have a package that would need a list of values as an array in an environment variable. Example
It would be intuitive to me to declare those in TOML like
But what I get is:
it would be nice if arrays were supported.