-
Notifications
You must be signed in to change notification settings - Fork 437
flake.nix: Add flakeModule #360
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,164 @@ | ||
| `devenv` can be used without the `devenv` CLI by integrating into [Nix Flakes](https://www.tweag.io/blog/2020-05-25-flakes/), if you're more familiar with the Nix language/ecosystem. | ||
|
|
||
| Some usecases for using devenv configuration inside flakes is for projects that want to define other Nix flake features, apart from the development shell. | ||
| These include a Nix package for the project, NixOS and home-manager modules related to the project. | ||
| Usually you want to use the same lock file for the development shell as well as the Nix package and others, so that everything is based on the same nixpkgs. | ||
|
|
||
| A Nix flake includes the inputs from `devenv.yaml` as well as the devenv configuration that you'd usually find in `devenv.nix`. `flake.lock` is the lock file for Nix flakes, the equivalent to `devenv.lock`. | ||
|
|
||
| ## Getting started | ||
|
|
||
| To quickly set a project up with Nix flakes, use of `nix flake init`, like: | ||
|
|
||
| ```console | ||
| $ nix flake init --template github:cachix/devenv#flake-parts | ||
| ``` | ||
|
|
||
| This will create a `flake.nix` with devenv configuration, as well as a `.envrc` direnv configuration. | ||
|
|
||
| Open the devenv shell using: | ||
|
|
||
| ```console | ||
| $ nix develop | ||
| ``` | ||
|
|
||
| This will create a lock file and open up a new shell that adheres to the devenv configuration stated in `flake.nix`. | ||
|
|
||
| ## flake.nix | ||
|
|
||
| A minimal flake.nix that includes devenv is for example: | ||
|
|
||
| ```nix | ||
| { | ||
| inputs = { | ||
| nixpkgs.url = "github:NixOS/nixpkgs/nixos-22.11"; | ||
| devenv.url = "github:cachix/devenv"; | ||
| }; | ||
|
|
||
| outputs = inputs@{ flake-parts, ... }: | ||
| flake-parts.lib.mkFlake { inherit inputs; } { | ||
| imports = [ | ||
| inputs.devenv.flakeModule | ||
| ]; | ||
| systems = [ "x86_64-linux" "aarch64-darwin" ]; | ||
|
|
||
| perSystem = { config, self', inputs', pkgs, system, ... }: { | ||
| # Per-system attributes can be defined here. The self' and inputs' | ||
| # module parameters provide easy access to attributes of the same | ||
| # system. | ||
|
|
||
| # Equivalent to inputs'.nixpkgs.legacyPackages.hello; | ||
| packages.default = pkgs.hello; | ||
|
|
||
| devenv.shells.default = { | ||
| # https://devenv.sh/reference/options/ | ||
| packages = [ config.packages.default ]; | ||
|
|
||
| enterShell = '' | ||
| hello | ||
| ''; | ||
| }; | ||
| }; | ||
| }; | ||
| } | ||
| ``` | ||
|
|
||
| Here a single shell is defined. It is defined for all listed systems. The shell includes a single devenv configuration module. | ||
| Inside the module is where you put the devenv configuration, the one you usually will find in `devenv.nix`. See https://devenv.sh/reference/options/ for the possible options to use here. | ||
|
|
||
| ## direnv | ||
|
|
||
| To make use of `direnv` in your Nix flake project, you'll need [nix-direnv](https://github.com/nix-community/nix-direnv). | ||
|
|
||
| To configure `direnv` in your project make sure you have a file called `.envrc` that includes the following line: | ||
|
|
||
| ```text | ||
| nix flake --impure | ||
| ``` | ||
|
|
||
| In normal `nix flake` projects, `--impure` is not needed. When using `devenv` in your flake, you _do_ need this option. | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Out of curiosity, why does There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I've also been curiously wondering about this. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Related: #330
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Unclear to me too, but this is just inherited from the existing flake integration. |
||
|
|
||
| ## Multiple shells | ||
|
|
||
| Defining multiple development shells using flakes can be useful depending on your projects structure. We will handle 2 use-cases here. | ||
|
|
||
| ### Single project with multiple shells | ||
|
|
||
| Some projects lend themselves to define multiple development shells. For instance, a mono-repo where you want to define multiple development shells in a central flake.nix in the root of the repository. There you can centrally define the development shells for the different sub-projects in the repository. | ||
|
|
||
| In this case you want to define a `flake.nix` file that contains multiple `devShells`. For example: | ||
|
|
||
| ```nix | ||
| # inside perSystem | ||
|
|
||
| devenv.shells.projectA = { | ||
| # https://devenv.sh/reference/options/ | ||
| packages = [ config.packages.default ]; | ||
|
|
||
| enterShell = '' | ||
| echo this is project A | ||
| hello | ||
| ''; | ||
| }; | ||
|
|
||
| devenv.shells.projectB = { | ||
| # https://devenv.sh/reference/options/ | ||
| packages = [ config.packages.default ]; | ||
|
|
||
| enterShell = '' | ||
| echo this is project A | ||
| hello | ||
| ''; | ||
| }; | ||
|
|
||
| # If you'd like to pick a default | ||
| devShells.default = config.devShells.projectA; | ||
| ``` | ||
|
|
||
| Here you can see that there are 2 shells defined. Each one with a devenv configuration with differently defined `enterShell`. | ||
|
|
||
| To enter the shell of `projectA`: | ||
|
|
||
| ```console | ||
| $ nix develop .#projectA | ||
| this is project A | ||
| (devenv) $ | ||
| ``` | ||
|
|
||
| To enter the shell of `projectB`: | ||
|
|
||
| ```console | ||
| $ nix develop .#projectB | ||
| this is project B | ||
| (devenv) $ | ||
| ``` | ||
|
|
||
| The last line makes `projectA` the default shell: | ||
|
|
||
| ```console | ||
| $ nix develop . | ||
| this is project A | ||
| (devenv) $ | ||
| ``` | ||
|
|
||
| ### Projects with an external flake | ||
|
|
||
| Whenever you have projects where you cannot (or don't want to) add a flake.nix to its repository, you can refer to external flakes. | ||
|
|
||
| You can create a repository with a flake.nix like the one above. However, in a different project you can now refer to this flake using: | ||
|
|
||
| ```console | ||
| $ nix develop file:/path/to/central/flake#projectA | ||
| this is project A | ||
| (devenv) $ | ||
| ``` | ||
|
|
||
| You can also add this to the `direnv` configuration of the project. Just make sure the following line is in `.envrc`: | ||
|
|
||
| ```text | ||
| nix flake --impure file:/path/to/central/flake#projectA | ||
| ``` | ||
|
|
||
| Note that instead of referring to a directory on local file system that includes the `flake.nix`, like `/path/to/central/flake`, it is also possible to use different references to a flake. For instance `github:` or `git:`. See [Nix flake references](https://nixos.org/manual/nix/stable/command-ref/new-cli/nix3-flake.html#flake-references) for more information. | ||
|
|
||
| One big caveat with this method is that there is no lock file. It is not 100% clear which version of the flake is used when referring to it this way. A local project flake file will give more control which version of the flake is used. | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,58 @@ | ||
| devenvFlake: { flake-parts-lib, lib, inputs, ... }: { | ||
| options.perSystem = flake-parts-lib.mkPerSystemOption ({ config, pkgs, system, ... }: | ||
|
|
||
| let | ||
| devenvType = (devenvFlake.lib.mkEval { | ||
| inherit inputs pkgs; | ||
| modules = [{ | ||
| config = { | ||
| # Add flake-parts-specific config here if necessary | ||
| }; | ||
| }]; | ||
| }).type; | ||
|
|
||
| shellPrefix = shellName: if shellName == "default" then "" else "${shellName}-"; | ||
| in | ||
|
|
||
| { | ||
| options.devenv.shells = lib.mkOption { | ||
| type = lib.types.lazyAttrsOf devenvType; | ||
| description = '' | ||
| The [devenv.sh](https://devenv.sh) settings, per shell. | ||
|
|
||
| Each definition `devenv.shells.<name>` results in a value for | ||
| [`devShells.<name>`](flake-parts.html#opt-perSystem.devShells). | ||
|
|
||
| Define `devenv.shells.default` for the default `nix develop` | ||
| invocation - without an argument. | ||
| ''; | ||
| example = lib.literalExpression '' | ||
| { | ||
| # create devShells.default | ||
| default = { | ||
| # devenv settings, e.g. | ||
| languages.elm.enable = true; | ||
| }; | ||
| } | ||
| ''; | ||
| default = { }; | ||
| }; | ||
| config.devShells = lib.mapAttrs (_name: devenv: devenv.shell) config.devenv.shells; | ||
|
|
||
| config.packages = | ||
| lib.concatMapAttrs | ||
| (shellName: devenv: | ||
| lib.concatMapAttrs | ||
| (containerName: container: | ||
| { "${shellPrefix shellName}container-${containerName}" = container.derivation; } | ||
| ) | ||
| devenv.containers | ||
| ) | ||
| config.devenv.shells; | ||
| }); | ||
|
|
||
| # the extra parameter before the module make this module behave like an | ||
| # anonymous module, so we need to manually identify the file, for better | ||
| # error messages, docs, and deduplication. | ||
| _file = __curPos.file; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,46 @@ | ||
| { | ||
| description = "Description for the project"; | ||
|
|
||
| inputs = { | ||
| nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; | ||
| devenv.url = "github:cachix/devenv"; | ||
| nix2container.url = "github:nlewo/nix2container"; | ||
| nix2container.inputs.nixpkgs.follows = "nixpkgs"; | ||
| mk-shell-bin.url = "github:rrbutani/nix-mk-shell-bin"; | ||
| }; | ||
|
|
||
| outputs = inputs@{ flake-parts, ... }: | ||
| flake-parts.lib.mkFlake { inherit inputs; } { | ||
| imports = [ | ||
| inputs.devenv.flakeModule | ||
| ]; | ||
| systems = [ "x86_64-linux" "i686-linux" "x86_64-darwin" "aarch64-linux" "aarch64-darwin" ]; | ||
|
|
||
| perSystem = { config, self', inputs', pkgs, system, ... }: { | ||
| # Per-system attributes can be defined here. The self' and inputs' | ||
| # module parameters provide easy access to attributes of the same | ||
| # system. | ||
|
|
||
| # Equivalent to inputs'.nixpkgs.legacyPackages.hello; | ||
| packages.default = pkgs.hello; | ||
|
|
||
| devenv.shells.default = { | ||
| name = "my-project"; | ||
|
|
||
| # https://devenv.sh/reference/options/ | ||
| packages = [ config.packages.default ]; | ||
|
|
||
| enterShell = '' | ||
| hello | ||
| ''; | ||
| }; | ||
|
|
||
| }; | ||
| flake = { | ||
| # The usual flake attributes can be defined here, including system- | ||
| # agnostic ones like nixosModule and system-enumerating ones, although | ||
| # those are more easily expressed in perSystem. | ||
|
|
||
| }; | ||
| }; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When using
devenvvia the flake module, assuming that thedevenvCLI isn't available, how would I run processes/services defined in configuration?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On that note, it would be pretty amazing to expose the process runners and/or the direct commands they execute via
flake.appsThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Bad assumption -- I just checked out this branch (after rebasing onto
main) and I see that the CLI is available. However, when I rundevenv up:There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I accidentally shadowed the shim by adding the whole devenv package to the packages. That was old code from before the shim existed. Now the module is on par with the existing flake integration.