Drake
Drake is a make-like task runner for Deno.
Install / Use
/learn @srackham/DrakeREADME
Drake — a task runner for Deno
Drake is a Make-like task runner for Deno inspired by Make, Rake and Jake.
- Drakefiles (c.f. Makefiles) are Deno TypeScript modules.
- Optional task prerequisites (dependencies).
- File tasks and non-file tasks.
- Drake API functions for defining, registering and running tasks.
- Drake uses conditionally cached file properties to determine whether or not a
file task is out of date (see Task Execution). This
eliminates the dependency errors that programs such as
makeencounter when file system mtimes are used directly (see mtime comparison considered harmful).
Status: Tested with Deno 1.40.3 running on Github CI the following
platforms: ubuntu-latest, macos-latest, windows-latest. See also the
changelog.
Drakefiles
A drakefile is a TypeScript module that:
- Imports the Drake module.
- Defines and registers tasks.
- Runs tasks.
Example drakefile
import { desc, run, task } from "https://deno.land/x/drake@v1.7.0/mod.ts";
desc("Minimal Drake task");
task("hello", [], function () {
console.log("Hello World!");
});
run();
To run the above example, copy and paste it into a file and run it with Deno. For example:
$ deno run -A minimal-drakefile.ts hello
hello started
Hello World!
hello finished (0ms)
The desc() and task() APIs define and register tasks. The run() API
executes the tasks that were specified on the command-line along with their
prerequisite tasks. run() is normally the last statement in the drakefile.
Tasks are executed in the correct dependency order.
-
Use the Drake
--helpoption to list Drake command-line options. For example:deno run -A minimal-drakefile.ts --help -
By convention, a project's drakefile is named
Drakefile.tsand resides in the project's root directory.
Here are some of real-world drakefiles:
- https://github.com/srackham/drake/blob/master/Drakefile.ts
- https://github.com/srackham/rimu/blob/master/Drakefile.ts
Importing Drake
A Drakefile uses Drake APIs imported from the Drake mod.ts module file. The
module can be imported from:
-
deno.land (Deno's third party modules registry). For example:
import { desc, run, task } from "https://deno.land/x/drake@v1.7.0/mod.ts"; -
nest.land (a blockchain based Deno modules registry).
NOTE: Drake version numbers innest.landURLs are not prefixed with a 'v' character:import { desc, run, task } from "https://x.nest.land/drake@1.7.0/mod.ts";
Some Drake APIs are useful in non-drakefiles, use lib.ts (not mod.ts) to
import them into non-drakefile modules.
Tasks
Task types
There are two types of task:
Normal task: A normal task executes unconditionally.
File task: A file task is only executed if it is out of date.
Task types are distinguished by their names. Normal task names can only
contain alphanumeric, underscore and hyphen characters and cannot start with a
hyphen e.g. test, hello-world. File task names are valid file paths. In
cases of ambiguity a file task name should be prefixed with a period and a
path separator e.g. ./hello-world.
Task properties
name: A unique task name.
desc: An optional task description that is set by the desc() API. Tasks
without a description are not displayed by the --list-tasks command-line
option (use the -L option to include hidden tasks and task prerequisites in
the tasks list).
prereqs: An array of prerequisite task names i.e. the names of tasks to be run prior to executing the task action function. Prerequisites can be normal task names, file task names, file paths or globs (wildcards).
action: An optional function that is run if the task is selected for
execution. The action function is bound to the parent task object i.e. the
parent task properties are accessible inside the action function through the
this object e.g. this.prereqs returns the task's prerequisite names array.
Task execution
Task execution is ordered such that prerequisite tasks (direct and indirect) are executed prior to their parent task. The same task is never run twice.
-
The execution directory defaults to the current working directory (this can be changed using the Drake
--directorycommand-line option). -
Task name and prerequisite file paths are normalized at task registration.
-
Prerequisite globs are expanded when the task is registered.
-
Prerequisites are resolved at the time the task is run.
-
All prerequisite files must exist by the time the task executes. An error is thrown if any are missing.
-
A file task is considered to be out of date if:
- The target file does not exist.
- The target file or any of the prerequisite files have changed since the task was last executed successfully.
- The Drake version or the operating system has changed since the task was last executed successfully.
-
A file is considered to have changed if it's current modification time or size no longer matches those recorded immediately after the task last executed successfully.
-
Before exiting Drake saves the target and prerequisite file properties of the tasks that successfully executed:
- File properties are saved to a file named
.drake.cache.jsonin the drakefile execution directory (this file path can be changed using the Drake--cachecommand-line option). - Task target and prerequisite file properties are recorded immediately after successful task execution (if a task fails its properties are not updated).
- A cache file will not be created until at least one file task has successfully executed.
- File properties are saved to a file named
Asynchronous task actions
Normally you will want tasks to execute sequentially i.e. the next task should not start until the current task has finished. To ensure this happens action functions that call asynchronous functions should:
- Be declared
async. - Call asynchronous functions with the
awaitoperator.
For example, the following task does not return until the shell command has successfully executed:
task("shell", [], async function () {
await sh("echo Hello World");
});
Without the await operator sh("echo Hello World") will return immediately
and the action function will exit before the shell command has even started.
Of course you are free to eschew await and use the promises returned by
asynchronous functions in any way that makes sense.
Drakefile execution
A drakefile is executed from the command-line. Use the --help option to view
Drake command-line options and syntax. For example:
$ deno run -A Drakefile.ts --help
NAME
drake - a make-like task runner for Deno.
SYNOPSIS
deno run -A DRAKEFILE [OPTION|VARIABLE|TASK]...
DESCRIPTION
The Drake TypeScript module provides functions for defining and executing
build TASKs on the Deno runtime.
A DRAKEFILE is a TypeScript module file containing Drake task definitions.
Drakefiles are run with the Deno 'run' command.
A Drake VARIABLE is a named string value e.g. 'vers=0.1.0'. Variables are
accessed using the Drake 'env' API e.g. 'env("vers").
OPTIONS
-a, --always-make Unconditionally execute tasks.
--cache FILE Set Drake cache file path to FILE.
-d, --directory DIR Change to directory DIR before running drakefile.
-D, --debug Write debug information to stderr.
-h, --help Display this help message.
-l, -L, --list-tasks List tasks (-L for hidden tasks and prerequisites).
-n, --dry-run Skip task execution.
-q, --quiet Do not log drake messages to standard output.
-v, --verbose Increase verbosity.
--version Display the drake version.
ENVIRONMENT VARIABLES
NO_COLOR Set to disable color (see https://no-color.org/).
SEE ALSO
The Drake user guide: https://github.com/srackham/drake
The --directory option sets the drakefile execution directory and defaults to
the current working directory. The --directory option allows a single
drakefile to be used to build multiple project directories.
If no command-line tasks are given the default task is run (specified by setting
the env API "--default-task" value).
A Drake command-line variable is a named string value that is made available to
the drakefile. Variables are formatted like <name>=<value> e.g. vers=0.1.0.
Variables are accessed within a drakefile using the env API e.g.
env("vers"). Variable names can only contain alphanumeric or underscore
characters and must start with an alpha character.
Drake API
The Drake library module exports the following functions:
abort
function abort(message: string): void;
Write an error message to stderr and terminate execution.
- If the
"--abort-exits"environment option isfalsethrow aDrakeError. - If the
"--debug"environment option istrueinclude the stack trace in the error message.
debug
function debug(title: string, message?: any): void;
Write the title and message to stderr if it is a TTY and the --debug
command-line option was specified or the DRAKE_DEBUG shell environment
variable is set.
desc
function desc(description: string): void;
Set description of next registered task. If a task has no description then it
won't be displayed in the tasks list unless the -L option is used.
env
function env(name?: string, value?: EnvValue): any;
The Drake env API function gets and optionally sets the command-line options,
task names and variables.
Options are
Related Skills
node-connect
333.3kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
frontend-design
82.0kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
Writing Hookify Rules
82.0kThis skill should be used when the user asks to "create a hookify rule", "write a hook rule", "configure hookify", "add a hookify rule", or needs guidance on hookify rule syntax and patterns.
openai-whisper-api
333.3kTranscribe audio via OpenAI Audio Transcriptions API (Whisper).
