---
# System prepended metadata

title: Chaingang - Task Automation Framework

---

# Chaingang - Task Automation Framework

## The Problem

Task Runners are a common pattern for automated testing. Retries, logging, and ease of debugging, make dealing with testing complex applications easier. What if that same ease and pattern could be leveraged for CI scripting?

Currently, most scripts that perform tasks like compiling scripts, writing log files or publishing builds create side effects during execution. Those tasks may have various points of failure, or even different modes of failure depending on outside factors, the environment they're running in, or the inputs provided. Side-effects created from bad runs are hard to track, and harder to roll back, especially in cases where those runs are reaching out to resources that the script doesn't control, like package managers or content delivery networks.

## The Solution

Enter `chaingang`, a task runner that aims to provide run-time reporting of side effects, provide a powerful, task-aware logging interface, and transactionally-driven retries, reducing the headache with developing, debugging, and maintaining CI/CD scripts and other automated tasks.

Ex:

```js=
import { warden, chain } from 'chaingang';

warden.watch(chain.start(chain => {
    // execute tasks sequentially with await
    await chain.do('synchronous task', chain => {
        chain.setup(({ done, log }) => {
            // defers chain.do execution until this setup is complete
            log('setup complete');
            done();
        });
        chain.do('then some secondary task', ({ done, log }) => {
            log('first task complete');
            done();
        });
        chain.do('then another task in parallel', ({ done, log }) => {
            log('second task complete');
            done();
        });
    });
    // do file-system interactions using the observed fs wrapper
    await chain.do('fs tasks', chain => {
        await chain.fs.writeFile('test.txt', 'Hello World!');
    });
    // do network requests with the observed fetch wrapper
    await chain.do('network requests', chain => {
        await chain.fetch('http://your-server.example', {
            method: 'POST'
        }, 'some side-effect-y request');
    });
}));

warden.on(chain.FAILURE, sideEffects => {
    // log what side effects the script failure produced
    sideEffects.forEach(console.log);
});

warden.run();
```