Files
skills/lib/mk-skill.nix

67 lines
2.0 KiB
Nix

# Builds a skill source directory into a derivation, `SKILL.md` at the `$out` root.
{
pkgs,
src,
name ? builtins.baseNameOf (toString src),
commands ? [ ],
}:
let
lib = pkgs.lib;
patchEnvDefault = command: envName: value:
let
marker = "# mkSkill:${envName}";
replacement = '': "''${${envName}:=${value}}" ${marker}'';
in
''
if ! awk -v marker=${lib.escapeShellArg marker} -v replacement=${lib.escapeShellArg replacement} '
index($0, marker) { print replacement; found = 1; next }
{ print }
END { if (!found) exit 42 }
' "$_mkskill_command" > "$_mkskill_command.tmp"; then
rm -f "$_mkskill_command.tmp"
echo "mkSkill: command '${command.path}' has no ${marker} marker" >&2
exit 1
fi
mv "$_mkskill_command.tmp" "$_mkskill_command"
chmod +x "$_mkskill_command"
'';
patchCommand = command:
let
env = command.env or { };
in
''
_mkskill_command="$out/${command.path}"
test -f "$_mkskill_command" \
|| { echo "mkSkill: command '${command.path}' does not exist" >&2; exit 1; }
test -x "$_mkskill_command" \
|| { echo "mkSkill: command '${command.path}' is not executable" >&2; exit 1; }
${lib.concatStringsSep "\n" (lib.mapAttrsToList (patchEnvDefault command) env)}
'';
patchCommands = lib.concatStringsSep "\n" (map patchCommand commands);
in
pkgs.stdenvNoCC.mkDerivation {
inherit name src;
# A skill is just files to copy, with nothing to unpack, configure, or build.
dontUnpack = true;
dontConfigure = true;
dontBuild = true;
installPhase = ''
runHook preInstall
mkdir -p "$out"
cp -R "$src"/. "$out/"
test -f "$out/SKILL.md" \
|| { echo "mkSkill: skill '${name}' has no SKILL.md at its root" >&2; exit 1; }
${patchCommands}
runHook postInstall
'';
# The name as an eval-time attribute, readable without building `$out`
# (no import-from-derivation).
passthru.skillName = name;
}