diff --git a/flake.nix b/flake.nix index 9e176d1b..20f5f94c 100644 --- a/flake.nix +++ b/flake.nix @@ -82,25 +82,6 @@ in { inherit lib; - apps = - computedOutputs.apps.${system} - // { - run-test = let - testScript = pkgs.writeShellApplication { - name = "test-templates"; - runtimeInputs = [ - inputs.nickel.packages."${system}".nickel-lang-cli - pkgs.parallel - pkgs.gnused - ]; - text = builtins.readFile ./run-test.sh; - }; - in { - type = "app"; - program = pkgs.lib.getExe testScript; - }; - }; - checks.alejandra = pkgs.runCommand "check-alejandra" {} '' ${pkgs.lib.getExe pkgs.alejandra} --check ${self} touch $out diff --git a/lib/builders.ncl b/lib/builders.ncl index ce90c208..ad3aa96e 100644 --- a/lib/builders.ncl +++ b/lib/builders.ncl @@ -1,4 +1,4 @@ -let { NickelDerivation, Derivation, NixString, .. } = import "contracts.ncl" in +let { NickelDerivation, Derivation, NixString, NullOr, .. } = import "contracts.ncl" in let lib = import "lib.ncl" in @@ -8,6 +8,15 @@ let concat_strings_sep = fun sep values => else std.array.reduce_left (fun acc value => nix-s%"%{acc}%{sep}%{value}"%) values in + +let MutExclusiveWith = fun other name other_name label value => + if value == null && other == null then + std.fail_with "You must specify either %{name} or %{other_name} field" + else if value != null && other != null then + std.fail_with "You can set only one of %{name} or %{other_name} fields" + else + value +in { NickelPkg # we should only need two '%%', but a current Nickel bug (#XXX) bug makes the example being @@ -84,4 +93,75 @@ in structured_env.buildInputs = packages, } | (NickelPkg & { packages | { _ : Derivation } }), + + ShellApplication + | doc m%" + "% + = + { + name, + version | default = "0.0.0", + text | NullOr NixString | MutExclusiveWith file "text" "file" | default = null, + file | NullOr String | default = null, + runtime_inputs | { _ : Derivation } = {}, + shell_binary | NixString | default = nix-s%"%{lib.import_nix "nixpkgs#bash"}/bin/bash"%, + + build_command = { + cmd = nix-s%"%{lib.import_nix "nixpkgs#bash"}/bin/bash"%, + args = [ + "-c", + nix-s%" + set -euo pipefail + source .attrs.sh + PATH="%{lib.import_nix "nixpkgs#coreutils"}/bin:$PATH" + mkdir -p "${outputs[out]}/bin" + target="${outputs[out]}/bin/${name}" + %{if text != null then + m%"cat > "$target" <<<"$script""% + else + m%"(cat <<<"$scriptHeader"; cat "$scriptPath") > "$target""% + } + chmod +x "$target" + "%{shell_binary}" -n -O extglob "$target" + "%{lib.import_nix "nixpkgs#shellcheck"}/bin/shellcheck" "$target" + "% + ], + }, + nix_drv = + let path_line | NixString = + if std.record.is_empty runtime_inputs then + "" + else + let paths = + runtime_inputs + |> std.record.values + |> std.array.map (fun s => nix-s%"%{s}/bin"%) + |> concat_strings_sep ":" + in + nix-s%"export PATH="%{paths}:$PATH""% + in + let script_header | NixString = nix-s%" + #!%{shell_binary} + set -o errexit + set -o nounset + set -o pipefail + %{path_line} + "% + in + if text != null then + # text != null && file == null + { + script | NixString = nix-s%" + %{script_header} + %{text} + "%, + } + else + # file != null && text == null + { + scriptPath | NixString = lib.import_file file, + scriptHeader = script_header, + }, + } + | NickelPkg, } diff --git a/project.ncl b/project.ncl index bdffa328..d8b609f8 100644 --- a/project.ncl +++ b/project.ncl @@ -12,5 +12,21 @@ let import_nix = organist.lib.import_nix in gnused = import_nix "nixpkgs#gnused", }, }, + + flake.apps.run-test = + let testScript | organist.builders.ShellApplication = { + name = "run-test.sh", + file = "./run-test.sh", + runtime_inputs = { + nickel = organist.lib.import_nix "nickel#nickel-lang-cli", + parallel = import_nix "nixpkgs#parallel", + gnused = import_nix "nixpkgs#gnused", + }, + } + in + { + type = "app", + program | organist.contracts.NixString = nix-s%"%{testScript}/bin/run-test.sh"% + }, } | organist.contracts.OrganistExpression