doit
Good#
Here are some opinions on writing portable, robust doit
workflows.
Pick good default_tasks
#
A practical convention is that running doit
, without any inputs, should leave the
project in a useful state for development and inspection.
For example, a good default to consider is what one might show on
MyBinder, with the simplest possible postBuild
file like:
#!/usr/bin/env bash
doit
This should leave a project with:
a verified, up-to-date installed runtime and test dependencies
any packages-under-development installed
Get responsive and stable#
A good doit
task tree should be responsive and stable.
A responsive task tree should correctly run all of the tasks in the right order, leaving the correct files on disk. When an important file (or part of it) changes, the right tasks and outputs should be out-of-date.
A stable task tree should ideally only require one command, and running the same task without changing any files, should not do any extra work.
Format all the things#
A key way to get the most stable product is to make liberal use of automated
formatters, with as aggressive-as-possible options. A doit format
task that automates
as much as possible will not only improve the stability and responsiveness of a
doit
task tree, but also lead to cleaner revision control history.
For example, on doitoml
’s own Python code, ssort
and ruff
are used to take as much
guesswork as possible out of line- and token-level syntax choices.
Single sources of truth#
Any time there is a magic number (or other value) that is important to multiple processes, try to store it in exactly one place, and either reuse it from there, or check other files against it.
Hint
For example, in a Python project, storing the package’s version in exactly pyproject.toml#/project/version
and nowhere else ensures that no automation or build
scripts go stale.
Use file_dep
and targets
#
While task_dep
and uptodate
can be useful in a pinch, hash-based comparisons of
well-known files save time and effort.
Hint
Using custom logging is a good way to get predictablly-named file outputs from otherwise hard-to-observe tasks.
One of the key benefits of knowing this dependency tree up-front is being able to use
doit --process=2
(or -n2
). This utilizes modern, multi-core systems without too much
coordination or needless re-work due to long, but avoidable, command errors about
missing files, or worse, incorrect build ordering based on stale data.
Avoid configurable task options#
doit
allows tasks to declare their own options which are propagated to the CLI, and
discoverable with doit help {task-name}
. However, these don’t compose very well
without very careful management of names.
Hint
A useful convention is to make use of environment variables, which are more
conventionally configurable, to set options to specific tasks. Combining these with
skip
metadata provided by doitoml
allows for customizing tasks when being run
in different contexts.