Skip to content

Commit

Permalink
WIP tasks
Browse files Browse the repository at this point in the history
  • Loading branch information
domenkozar committed Aug 16, 2024
1 parent b285601 commit ffb1483
Show file tree
Hide file tree
Showing 6 changed files with 169 additions and 2 deletions.
1 change: 1 addition & 0 deletions docs/.pages
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ nav:
- Basics: basics.md
- Packages: packages.md
- Scripts: scripts.md
- Tasks: tasks.md
- Languages:
- Overview: languages.md
- Supported Languages: supported-languages
Expand Down
59 changes: 59 additions & 0 deletions docs/tasks.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
Tasks allow you to form dependencies between units, executed in parallel.

Under the hood, tasks are implemented using [Taskfile](https://taskfile.dev/).

## Defining tasks

```nix title="devenv.nix"
{ pkgs, ... }:
{
tasks.hello = {
exec = ''echo "Hello, world!"'';
desc = "hello world in bash";
};
}
```

```shell-session
$ devenv shell task hello
• Building shell ...
• Entering shell ...
Hello, world!
$
```

## Using your favourite language

Tasks can also reference scripts and depend on other tasks, for example when entering the shell:

```nix title="devenv.nix"
{ pkgs, lib, config, ... }:
{
scripts.python-hello = {
exec = ''print("Hello world from Python!")'';
expose = false;
package = config.languages.python.package;
description = "hello world in Python";
};
tasks = {
python-hello.exec = config.scripts.python-hello.scriptPackage;
hello = {
exec = "echo 'Hello world from bash!'";
deps = [ "python-hello" ];
};
enterShell.deps = [ "hello" ];
};
}
```

```shell-session
$ devenv shell
• Building shell ...
• Entering shell ...
Hello world from Python!
Hello world from bash!
$
```
11 changes: 9 additions & 2 deletions src/modules/scripts.nix
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ let
description = "The package to use to run the script.";
default = pkgs.bash;
};
expose = lib.mkOption {
type = types.bool;
description = "Whether to expose the script in the environment.";
default = true;
};
binary = lib.mkOption {
type = types.str;
description = "Override the binary name if it doesn't match package name";
Expand Down Expand Up @@ -50,6 +55,8 @@ let
${name}${lib.optionalString (script.description != "") ": ${script.description}"}
${script.scriptPackage}
'';

exposedScripts = lib.filterAttrs (_: script: script.expose) config.scripts;
in
{
options = {
Expand All @@ -61,8 +68,8 @@ in
};

config = {
packages = lib.mapAttrsToList (_: script: script.scriptPackage) config.scripts;
packages = lib.mapAttrsToList (_: script: script.scriptPackage) exposedScripts;

infoSections."scripts" = lib.mapAttrsToList renderInfoSection config.scripts;
infoSections."scripts" = lib.mapAttrsToList renderInfoSection exposedScripts;
};
}
80 changes: 80 additions & 0 deletions src/modules/tasks.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
{ pkgs, lib, config, ... }:
let
types = lib.types;
taskType = types.submodule ({ name, config, ... }: {
options = {
exec = lib.mkOption {
type = types.str;
description = "Bash code to run the process.";
};
script = lib.mkOption {
type = types.package;
internal = true;
default = pkgs.writeShellScript name config.exec;
description = "Path to the script to run.";
};
desc = lib.mkOption {
type = types.str;
default = "";
description = "Description of the task.";
};
deps = lib.mkOption {
type = types.listOf types.str;
description = "List of tasks to run before this task.";
default = [ ];
};
aliases = lib.mkOption {
type = types.listOf types.str;
description = "List of aliases for this task.";
default = [ ];
};
};
});
# ladder is a hack to force Nix into proper indentation
renderTask = name: task: ''
#
${name}:
cmds:
- ${task.script}
desc: ${task.desc}
deps: [${lib.concatStringsSep " " task.deps}]
aliases: [${lib.concatStringsSep " " task.aliases}]
'';
in
{
options.tasks = lib.mkOption {
type = types.attrsOf taskType;
};

options.task.config = lib.mkOption {
type = types.package;
internal = true;
default = pkgs.writeText "tasks.yaml" ''
# auto generated by devenv.nix
version: '3'
tasks:
${lib.concatStringsSep "\n" (lib.mapAttrsToList renderTask config.tasks)}
'';
};

config = {
packages = [ pkgs.go-task ];
info.infoSections.tasks = lib.mapAttrsToList (name: task: "${name}: ${task.desc} ${task.script}") config.tasks;
tasks = {
enterShell = {
desc = "Runs when entering the shell";
exec = "echo";
};
enterTest = {
desc = "Runs when entering the test environment";
exec = "echo";
};
};
enterShell = ''
ln -sf ${config.task.config} Taskfile.yaml
task enterShell
'';
enterTest = "task enterTest";
};
}
1 change: 1 addition & 0 deletions src/modules/top-level.nix
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,7 @@ in
./lib.nix
./tests.nix
./cachix.nix
./tasks.nix
]
++ (listEntries ./languages)
++ (listEntries ./services)
Expand Down
19 changes: 19 additions & 0 deletions tests/tasks/devenv.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
tasks = {
shell.exec = "touch shell";
enterShell.deps = [ "shell" ];
test.exec = "touch test";
};

enterTest = ''
if [ ! -f shell ]; then
echo "shell does not exist"
exit 1
fi
task test
if [ ! -f test ]; then
echo "test does not exist"
exit 1
fi
'';
}

0 comments on commit ffb1483

Please sign in to comment.