Joe Davidson

Introducing the XC README task runner

productivitydocumentation

An introduction to the XC README task runner [0], why I built it and how to use it.

The problem #

The concept for xc [1] came out of a conversation I had with Adrian Hesketh [2] whilst programming.
We are currently working on a system split into multiple microservices, growing in numbers. So, documentation is key to keeping everyone on the same page.

One example of this is having some useful commands one may use frequently whilst working on a service.
These commands include very frequently used commands like go run main.go or go test ./... and some maybe less frequently used commands that are still useful to know.

Our solution for this was make [3], and using this as a task runner is not really what it was built for. And it can quickly become hard to understand what a task is doing if someone who knows make well is writing it.

This looked something like the following:

get:
go get ./...

setup-private:
go env -w GOPRIVATE=github.com/joerdav

build: setup-private
cd api && go build ./...
cd cdk && go build

run-dynamodb-local:
./run-dynamodb-local.sh

test: setup-private
cd api && go test ./...

cover: setup-private
cd api && go test ./... --cover

deploy: setup-private
cd cdk && cdk deploy

Looking at alternatives there's npm run which is meant primarily for Node applications;
There's go-task [4] which seems to be a great, well supported task runner, it just involved writing YAML and isn't too accessible or usable when someone doesn't have go-task installed on their machine.

The first solution that came to mind was to create shell files for each task in the project root, most OSs have a way to run a shell script, so anyone can run it.

But my main concern around that idea was sign-posting. Yes, you could link the scripts in the README but this could easily become out of date, and also if someone want's to view these useful commands then it involves a certain degree of digging.

The shell solution also promotes the temptation to make overly complicated tasks, just like with make.

The solution #

I had the bright idea to put useful commands in the README, this means they are easily findable by anyone, even if they don't have the means to run the tasks.
And to define a syntax of writing these commands so they were easily ran by a command for convenience.

So I began building and the following is what I came up with: XC [5].

To get started simply create a Tasks heading in your README.md and add some titles of commands with code blocks defining the command:

## Tasks

### run
```
go run main.go
```


### test
```
go test ./...
```


### say-something
```
echo hello
```

And of course this will be extremely readable once rendered:


Tasks

run

go run main.go

test

go test ./...

say-something

echo hello

Install XC (requires Go, and requires $GOBIN to be in your $PATH).

go install github.com/joerdav/xc/cmd/xc@v0.0.20

Now you can list and run the tasks with XC.

$ xc
tasks:
run

test

say-something

$ xc say-something
.: echo hello
hello

Some other features currently implemented are:

Descriptions

README:

## Tasks

### other-task
Could run the tests?
```
echo hello
```


### say-something
Just an example.
```
echo hello
```

Output:

xc
tasks:
other-task Could run the tests?

say-something Just an example.

Dependencies

README:

## Tasks

### other-task
```
echo other
```


### say-something
Requires: other-task
```
echo hello
```

Output:

$ xc
tasks:
other-task

say-something Requires: other-task

$ xc say-something
.: echo other
other
.: echo hello
hello

Environment Variables

README:

## Tasks

### say-something
Env: MESSAGE=hello
```
printenv MESSAGE
```

Output:

$ xc say-something
.: printenv MESSAGE
hello

Execution Directories

README:

## Tasks

### printdir
Directory: ./otherdir
```
pwd
```

Output:

$ xc printdir
./otherdir: pwd
/Users/joe.davidson/src/repo/otherdir

Compound Commands

README:

## Tasks

### task1
```
echo task1
```

### task2
```
echo task2
```

### both
Requires: task1, task2

Output:

$ xc both
.: echo task1
task1
.: echo task2
task2

Summary #

In summary, I've built a README task runner called XC. Please do make your way onto the GitHub page [6] and make suggestions/contributions.