diff --git a/doc/devshell.md b/doc/devshell.md new file mode 100644 index 00000000..8e8478a5 --- /dev/null +++ b/doc/devshell.md @@ -0,0 +1,17 @@ +# DevShell + +`services-flake` uses [mkShell](https://nixos.org/manual/nixpkgs/stable/#sec-pkgs-mkShell) function to provide a shell with packages of all the enabled services. + +```nix +# Inside `perSystem` +{ + process-compose."my-pc" = { ... }; + devShells.default = pkgs.mkShell { + inputsFrom = [ + config.process-compose."my-pc".services.outputs.devShell; + ]; + # ... + }; +} +``` + diff --git a/doc/guide.md b/doc/guide.md index 269ed11c..0b9c934b 100644 --- a/doc/guide.md +++ b/doc/guide.md @@ -2,4 +2,5 @@ # Guide - [[datadir]]# +- [[devshell]]# - [[custom-service]]# diff --git a/example/share-services/northwind/flake.nix b/example/share-services/northwind/flake.nix index 922eff1b..32589ba4 100644 --- a/example/share-services/northwind/flake.nix +++ b/example/share-services/northwind/flake.nix @@ -18,13 +18,14 @@ ]; flake.processComposeModules.default = import ./services.nix { inherit inputs; }; - perSystem = { self', pkgs, lib, ... }: { + perSystem = { self', pkgs, config, lib, ... }: { process-compose."default" = { config, ... }: { imports = [ inputs.services-flake.processComposeModules.default inputs.self.processComposeModules.default ]; }; + devShells.default = config.process-compose."default".services.outputs.devShell; }; }; } diff --git a/example/share-services/pgweb/flake.nix b/example/share-services/pgweb/flake.nix index 1f6320b2..7cccd617 100644 --- a/example/share-services/pgweb/flake.nix +++ b/example/share-services/pgweb/flake.nix @@ -15,7 +15,7 @@ imports = [ inputs.process-compose-flake.flakeModule ]; - perSystem = { self', pkgs, lib, ... }: { + perSystem = { self', pkgs, config, lib, ... }: { process-compose."default" = { config, ... }: { imports = [ inputs.services-flake.processComposeModules.default @@ -32,6 +32,7 @@ environment.PGWEB_DATABASE_URL = config.services.postgres.northwind.connectionURI { dbName = "sample"; }; }; }; + devShells.default = config.process-compose."default".services.outputs.devShell; }; }; } diff --git a/example/simple/flake.nix b/example/simple/flake.nix index 797e9b35..edc01c5e 100644 --- a/example/simple/flake.nix +++ b/example/simple/flake.nix @@ -16,7 +16,7 @@ imports = [ inputs.process-compose-flake.flakeModule ]; - perSystem = { self', pkgs, lib, ... }: { + perSystem = { self', pkgs, config, lib, ... }: { # `process-compose.foo` will add a flake package output called "foo". # Therefore, this will add a default package that you can build using # `nix build` and run using `nix run`. @@ -61,6 +61,9 @@ }; devShells.default = pkgs.mkShell { + inputsFrom = [ + config.process-compose."default".services.outputs.devShell + ]; nativeBuildInputs = [ pkgs.just ]; }; }; diff --git a/nix/services/default.nix b/nix/services/default.nix index f3b9dc10..e1861d75 100644 --- a/nix/services/default.nix +++ b/nix/services/default.nix @@ -2,10 +2,11 @@ let inherit (import ../lib.nix) multiService; in { - imports = builtins.map multiService [ + imports = (builtins.map multiService [ ./apache-kafka.nix ./clickhouse ./elasticsearch.nix + ./mongodb.nix ./mysql ./nginx ./ollama.nix @@ -23,6 +24,8 @@ in ./weaviate.nix ./searxng.nix ./tika.nix - ./mongodb.nix + ]) ++ [ + ./devshell.nix ]; + } diff --git a/nix/services/devshell.nix b/nix/services/devshell.nix new file mode 100644 index 00000000..c56aafa5 --- /dev/null +++ b/nix/services/devshell.nix @@ -0,0 +1,50 @@ +{ config, pkgs, lib, ... }: +let + inherit (lib) types; +in +{ + options.services.outputs = { + enabledServices = lib.mkOption { + type = types.attrsOf (types.listOf types.str); + readOnly = true; + description = '' + Names of all the enabled service instances, grouped by the service name. + ''; + example = lib.literalExpression '' + { + mysql = [ "m1" "m2" ]; + redis = [ "r1" ]; + } + ''; + }; + devShell = lib.mkOption { + type = types.package; + readOnly = true; + description = '' + The devShell that aggregates packages from all the enabled services. + ''; + }; + }; + + config = { + services.outputs.enabledServices = lib.pipe config.services [ + # `outputs` is a reserved attribute set and is not the name of a service. + (lib.filterAttrs (n: _: n != "outputs")) + + (lib.mapAttrs (_service: instances: + lib.attrNames (lib.filterAttrs (_: v: v.enable) instances))) + ]; + + services.outputs.devShell = pkgs.mkShell { + packages = lib.pipe config.services.outputs.enabledServices [ + (lib.mapAttrsToList (service: instances: + map + (instance: + lib.attrByPath ([ service instance "package" ]) (builtins.throw "${service}.${instance} doesn't define a `package` option") config.services) + instances)) + + lib.flatten + ]; + }; + }; +}