cURL the Badger

Using Task Badger with nothing more than your wits and cURL.

Badger on the Beach

Task Badger can be used in many environments but the shell is one of the most basic. In some way this makes it the simplest, most uncomplicated environment, but it also requires more manual steps and attention to detail.

In this article we are going to explore how Task Badger's APIs can be used on the command line and in Bash scripts using cURL.

To start out let's see the raw commands that are needed to create and update a task using the API. In this article we will be using cURL to interact with the API and jq for JSON processing.

API Basics

Creating a task is very simple, we make an HTTP POST request to the API. Here we'll just provide the task name and leave the rest as default values:

$ curl -X POST \
"https://taskbadger.net/api/${ORGANIZATION}/${PROJECT}/tasks/" \
 -H "Authorization: Bearer ${AUTH_TOKEN}" \
 -H "Content-Type: application/json" \
 -d '{"name": "shell task"}' | jq

{
  "id": "7122sHGxTQw4pr4HoCW3qBjnrV",
  "organization": "demo_or",
  "project": "project_a",
  "name": "shell task",
  "status": "pending",
  "value": null,
  "value_max": 100,
  "value_percent": null,
  "data": null,
  "created": "...",
  "updated": "...",
}

If we just want to extract the task ID we can use jq:

... | jq '.id' --raw-output

Updating the task is equally simple using an PATCH request to the API:

$ curl -X PATCH \
"https://taskbadger.net/api/${ORGANIZATION}/${PROJECT}/tasks/${TASK_ID}/" \
 -H "Authorization: Bearer ${AUTH_TOKEN}" \
 -H "Content-Type: application/json" \
 -d '{"status": "processing"}'

Take a look at our docs for full API details.

Using it in a script

Running these commands in the terminal is not very useful on its own so let's see how we can put them in a script.

To start with we'll assume that we already have a script that is performing a task. Here is the script we'll use for this example:

#!/usr/bin/env bash

# Imagine this is doing something more useful
for i in $(seq 1 10); do
    echo $i
    sleep 0.1
done

Let's modify our script a bit to add some basic error handling and some placeholders for where we'll need to call the Task Badger APIs.

#!/usr/bin/env bash

# Placeholder: Register task

(
  for i in $(seq 1 10); do
    echo $i
    sleep 0.1
  done
)

if [ "$?" -ne 0 ]; then
  # Placeholder: Update task failure
else
  # Placeholder: Update task success
fi

We've moved our task execution code into a subshell so that we can execute it safely and get the exit code. We could also have moved it to a separate script which we call from this script. Now we need to add in the calls to the Task Badger API.

We're going to add some functions to replace the placeholders in the script which will register the task and update it upon completion of the task.

#!/usr/bin/env bash

set -o pipefail

ORGANIZATION="demo"
PROJECT="demo"
AUTH_TOKEN="secret"

#### Utility functions

function callAPI {
  # Call the Task Badger API with a payload to create or update a task.
  # Arguments:
  #    1: JSON payload
  #    2: (optional) ID of task to update
  PAYLOAD=$1
  TASK_ID=$2
  URL="https://taskbadger.net/api/${ORGANIZATION}/${PROJECT}/tasks/"
  METHOD=POST
  if [ -n "$TASK_ID" ]; then
    # Append the task ID to the URL if it's present and adjust the HTTP method
    URL="${URL}${TASK_ID}/"
    METHOD="PATCH"
  fi
  curl -X $METHOD $URL \
    -H "Authorization: Bearer ${AUTH_TOKEN}" -H "Content-Type: application/json" \
    -d "$PAYLOAD" --fail --silent
}

function registerTask {
  # Register task in Task Badger
  # Arguments:
  #   1. Task name
  NAME="$1"
  PAYLOAD=$(jq -n --arg name "$NAME" '{"name": $name, "status": "processing"}')
  TASK_ID=$(callAPI "$PAYLOAD" | jq '.id' --raw-output)
  # Display an error message if the task was not created
  test $? -ne 0 && echo "[WARN] Unable to create task" 1>&2 && return 1
  echo "$TASK_ID"
}

function updateTaskStatus {
  # Update task status
  # Arguments:
  #   1. Task name
  #   2. Task status
  TASK_ID="$1"
  # Exit early if the task ID is empty
  test -z "$TASK_ID" && return 1
  STATUS="$2"
  PAYLOAD=$(jq -n --arg status "$STATUS" '{"status": $status}')
  callAPI "$PAYLOAD" "$TASK_ID"

  # Display an error message if the task update failed
  test $? -ne 0 && echo "Unable to update task status" 1>&2;
}

#### End utility functions

TASK_ID=$(registerTask "demo task 1")

# Perform the actual task in a subshell
(
  for i in $(seq 1 10); do
      echo $i
  done
)

if [ "$?" -ne 0 ]; then
  updateTaskStatus "$TASK_ID" "error"
else
  updateTaskStatus "$TASK_ID" "success"
fi

Conclusion

As you can see, the full script has a lot of code just to communicate with the API.

This code could be extracted into a utilities file and imported into the main script which would make things much cleaner.

You can download the full script and other examples from our Github repository.

Next time we'll look at two ways we can use the CLI which will greatly simplify things.

Subscribe for Updates

Sign up to get notified when we publish new articles.

We don't spam and you can unsubscribe anytime.