Tasks are a project-level feature to define a project command system backed by shell scripts. Tasks are used to implement development workflows and are accessible through the projen CLI as subcommands.
The following example defines a task named βhelloβ which executes the shell
command echo hello, world!
:
const hello = project.addTask('hello');
hello.exec('echo hello, world!');
Run pj
and the task will be available in the CLI:
$ projen hello
π€ hello | echo hello, world!
hello, world!
You can also define some metadata and the first exec step declaratively:
const projen = require('projen');
const hello = project.addTask('hello', {
description: 'say hello',
category: projen.tasks.TaskCategory.TEST,
exec: 'echo hello, world!'
});
Tasks can include any number of steps:
hello.exec('echo step number 2');
// a name can be added to a step if desired
hello.exec('echo foo bar', { name: 'print the text "foo bar"' });
The --inspect
option can be used to display the contents of a task:
$ projen hello --inspect
echo hello, world!
echo step number 2
echo foo bar
If a step fails, the task will fail and all subsequent steps will not be executed.
You can also add steps to the beginning of a task:
const hello = project.addTask('hello');
hello.exec('echo hello');
hello.prepend('echo world');
Then:
$ projen hello 2> /dev/null
world
hello
Tasks can also spawn sub-tasks as a step:
const world = project.addTask('world');
world.exec('echo world!');
const hello = project.addTask('hello');
hello.exec('echo hello');
hello.spawn(world);
The output will be:
$ projen hello
π€ hello | echo hello
hello
π€ hello Β» world | echo world!
world!
$ projen hello --inspect
echo hello
world:
echo world!
Environment variables can be defined at the project level (for all tasks), the task level, or the task step level:
project.tasks.addEnvironment('FOO', 'hello');
const hello = project.addTask('hello');
hello.env('BAR', 'beautiful');
hello.exec('echo $FOO, $BAR $BAZ!', { env: { BAZ: 'world' } });
Then:
$ projen hello
π€ hello | echo $FOO, $BAR $BAZ!
hello, beautiful world!
You can also evaluate environment variable values from a shell command:
const hello = project.addTask('hello');
hello.env('TIME', '$(date)');
hello.exec('echo current time is $TIME');
Then:
$ projen hello
π€ hello | echo current time is $TIME
current time is Tue Dec 1 09:32:33 IST 2020
The condition
option includes a command that determines if the task is
executed. If the command exits successfully (with a zero exit code), steps will
be executed. Otherwise, the task will be skipped (successfully).
const hello = project.addTask('hello', {
condition: '[ -n "$CI" ]', // only execute if the CI environment variable is defined
exec: 'echo running in a CI environment'
});
Then:
$ projen hello
π€ hello | condition: [ -n "$CI" ]
π€ hello | condition exited with non-zero - skipping
$ CI=1 projen hello
π€ hello | condition: [ -n "$CI" ]
π€ hello | echo running in a CI environment
running in a CI environment
The condition
option can also be specified on individual task steps, for more
granular control over task execution behavior:
const hello = project.addTask('hello', {
steps: [
{ exec: 'running in a CI environment', condition: '[ -n "$CI" ]' },
{ exec: 'not running in a CI environment', condition: '[ ! -n "$CI" ]' }
]
});
Then:
$ projen hello
π€ hello | condition: [ -n "$CI" ]
π€ hello | condition exited with non-zero - skipping
π€ hello | condition: [ ! -n "$CI" ]
π€ hello | echo not running in a CI environment
not running in a CI environment
$ CI=1 projen hello
π€ hello | condition: [ -n "$CI" ]
π€ hello | echo running in a CI environment
running in a CI environment
π€ hello | condition: [ ! -n "$CI" ]
π€ hello | condition exited with non-zero - skipping
By default, npm scripts in NodeProject
s (or derivatives) are implemented by delegating the
command to the projen CLI:
{
"scripts": {
"compile": "npx projen compile"
}
}
This means that when yarn compile
or npm run compile
are executed, the
projen CLI will be invoked and the task will be executed.
You can see a list of all steps in a task from the command line by passing
the --inspect
flag, e.g. yarn compile --inspect
.