Run your tasks with Ease!
  • Simple API and minimal configuration
  • Ability to schedule tasks recurrence
  • Dynamic task definition for complex workflows
  • Fast development with plugins

Ease Task Runner


Ease is a minimal task runner with scheduling capabilities designed to be flexible and easy to work with.

Installation


npm install @chisel/ease -g

Usage


Ease looks for a configuration file named easeconfig.js or easeconfig.ts (in that exact order) inside the current working directory for task and job definitions. If the file was not found, it would look in the parent directories all the way up to the root.

The configuration file must export a function which takes the ease object as its parameter, which can be used to define tasks, jobs, schedules, etc.

easeconfig.js

module.exports = ease => {

  // Use the ease object here

};

easeconfig.ts

import { Ease } from '@chisel/ease';

export default (ease: Ease) => {

  // Use the ease object here

};

API


Task Hooks


The following hooks are available for all tasks which will be defined when appended to the task name in the ease.task() method:

module.exports = ease => {

  ease.task('foo:before', (jobName, suspend) => {

    ease.log('Running before task foo...');

  });

  ease.task('foo', jobName => {

    // Do stuff

  });

  ease.task('foo:error', (jobName, error) => {

    ease.log('Task foo has failed:\n' + error);

  });

};

Job Hooks


Jobs have hooks identical to tasks and are defined using the ease.hook() method, the only difference is the callback arguments in which the jobName is not provided.

module.exports = ease => {

  ease.task('foo', jobName => ease.log('Running foo...'));

  ease.job('job1', ['foo']);

  ease.hook('job1:after', () => ease.log('Job1 has finished.'));

};

Job Execution Options


The following properties are defined on the options object:

Configuration Example


const got = require('got');

module.exports = ease => {

  // Define sync task before hook
  ease
  .task('sync-task:before', (jobName, suspend) => {

    ease.log('Running sync-task:before inside job ' + jobName);
    // Suspend sync-task
    suspend();

  })
  .task('sync-task', jobName => {

    ease.log('Running sync-task'); // Won't run since task was suspended

  })
  // Define async task
  .task('async-task', jobName => {

    return new Promise((resolve, reject) => {

      got.get('https://google.com')
      .then(response => {

        ease.log('Got response');
        resolve();

      })
      .catch(reject);

    });

  })
  // Define async task after hook
  .task('async-task:after', jobName => {

    ease.log('Cleaning up...');
    ease.suspend(jobName); // Suspends the current job, no tasks will be run after this point

  })
  .job('test', ['sync-task', 'async-task', 'sync-task']);
  // Define job error handler
  .hook('test:error', error => {

    ease.log('Caught error: ' + error);

  });

};

Running ease test will execute the following tasks:

  1. sync-task:before (suspends sync-task)
  2. async-task
  3. async-task:after (suspends test job)

Scheduled Job Example


module.exports = ease => {

  ease.task('task1', () => ease.log('Running task 1'));

  // Schedule job to run every Monday at 5 in the afternoon
  ease.job('job1', ['task1'], {
    runImmediately: false,
    schedule: {
      recurrence: 'weekly',
      day: 1,
      time: '17:00:00'
    }
  });

};

Plugins


Tasks can be made into plugins in order to allow reuse and quick development. To install a plugin, follow these steps:

  1. Install the plugin through NPM: npm install ease-task-pluginname --save-dev (replace pluginname with the name of the plugin)

  2. Use the install() method to install and configure the plugin:

     const sass = require('ease-task-sass');
    
     module.exports = ease => {
    
       // Install the plugin as `sass` task
       ease.install('sass', sass, { dir: 'sass', ourDir: 'css', sourceMap: true });
    
       // Use the task in a job
       ease.job('process-sass-files', ['sass']);
    
     };

Available Plugins


These plugins are made by the Chisel team:

If you have written an Ease plugin, let us know and we'll include it here in the list.

Creating Plugins


To create an Ease plugin, write a module that exports a factory function which takes the following arguments and returns a task runner function:

Example:

const fs = require('fs-extra');
const path = require('path');

module.exports = (logger, dirname, config) => {

  // Task runner
  return () => {

    // Async task
    return new Promise((resolve, reject) => {

      const finalPath = path.join(dirname, config.dir);

      logger(`Emptying "${finalPath}"...`);

      // Empty the directory's content
      fs.emptyDir(finalPath, error => {

        if ( error ) reject(error);
        else resolve();

      });

    });

  };

};

When publishing Ease tasks, it's good practice to prefix the plugin name with ease-task-.

Dynamic Job Redefinition


Jobs can be redefined dynamically from within tasks. This can be achieved by calling ease.job() again which would allow redefining the tasks or the schedule for a job.

If a job already exists, calling ease.job() the second time doesn't require the tasks array. This can be used to reschedule a job without affecting it's registered tasks. Example: ease.job('job1', null, { schedule: {...} }).

You can remove a scheduled job by running ease.job('job1', null, { schedule: null }) on an existing job.

You can register new tasks dynamically using ease.job('job1', ease.info('job1').tasks.concat('new-task')).

You can define tasks dynamically, but jobs that are dynamically defined won't run unless scheduled. If you need to run a dynamically defined job right away, you can schedule it to be run the next second and then remove its schedule on the job's after hook.

module.exports = ease => {

  ease.task('foo', () => ease.log('Running task foo'));
  ease.task('bar', () => ease.log('Running task bar'));

  // Defining job "job1" with task "foo"
  ease.job('job1', ['foo']);

  // Dynamically adding task "bar" to job "job1" using a before hook
  ease.hook('job1:before', () => {

    ease.job('job1', ease.info('job1').tasks.concat('bar'));

  });

};

CLI


ease [options] <jobs>

Options:

Example: ease job1 job2

Logs


Logs are stored at ~/.ease/ease.log (or %userprofile%\.ease\ease.log on Windows).

Building


Run npm run build to build the source into the dist directory.