{ writeTextFile, lib, shellcheck-minimal, stdenv, runtimeShell, }: { /* The name of the script to write. Type: String */ name, /* The shell script's text, not including a shebang. Type: String */ text, /* Inputs to add to the shell script's `$PATH` at runtime. Type: [String|Derivation] */ runtimeInputs ? [ ], /* Extra environment variables to set at runtime. Type: AttrSet */ runtimeEnv ? null, /* `stdenv.mkDerivation`'s `meta` argument. Type: AttrSet */ meta ? { }, /* `stdenv.mkDerivation`'s `passthru` argument. Type: AttrSet */ passthru ? { }, /* The `checkPhase` to run. Defaults to `shellcheck` on supported platforms and `bash -n`. The script path will be given as `$target` in the `checkPhase`. Type: String */ checkPhase ? null, /* Checks to exclude when running `shellcheck`, e.g. `[ "SC2016" ]`. See for a list of checks. Type: [String] */ excludeShellChecks ? [ ], /* Extra command-line flags to pass to ShellCheck. Type: [String] */ extraShellCheckFlags ? [ ], /* Bash options to activate with `set -o` at the start of the script. Defaults to `[ "errexit" "nounset" "pipefail" ]`. Type: [String] */ bashOptions ? [ "errexit" "nounset" "pipefail" ], /* Extra arguments to pass to `stdenv.mkDerivation`. :::{.caution} Certain derivation attributes are used internally, overriding those could cause problems. ::: Type: AttrSet */ derivationArgs ? { }, /* Whether to inherit the current `$PATH` in the script. Type: Bool */ inheritPath ? true, shell ? runtimeShell, }: writeTextFile { inherit name meta passthru derivationArgs ; executable = true; destination = "/bin/${name}"; allowSubstitutes = true; preferLocalBuild = false; text = '' #!${shell} ${lib.concatMapStringsSep "\n" (option: "set -o ${option}") bashOptions} '' + lib.optionalString (runtimeEnv != null) ( lib.concatStrings ( lib.mapAttrsToList (name: value: '' ${lib.toShellVar name value} export ${name} '') runtimeEnv ) ) + lib.optionalString (runtimeInputs != [ ]) '' export PATH="${lib.makeBinPath runtimeInputs}${lib.optionalString inheritPath ":$PATH"}" '' + '' ${text} ''; checkPhase = let excludeFlags = lib.optionals (excludeShellChecks != [ ]) [ "--exclude" (lib.concatStringsSep "," excludeShellChecks) ]; # GHC (=> shellcheck) isn't supported on some platforms (such as risc-v) # but we still want to use writeShellApplication on those platforms shellcheckCommand = lib.optionalString shellcheck-minimal.compiler.bootstrapAvailable '' # use shellcheck which does not include docs # pandoc takes long to build and documentation isn't needed for just running the cli ${lib.getExe shellcheck-minimal} ${ lib.escapeShellArgs (excludeFlags ++ extraShellCheckFlags) } "$target" ''; in if checkPhase == null then '' runHook preCheck ${stdenv.shellDryRun} "$target" ${shellcheckCommand} runHook postCheck '' else checkPhase; }