Build a runbook

Since Runbooks launched, a number of Tasks features shipped that bring Tasks to parity with Runbooks. For many use-cases, you may prefer to use a Task over a Runbook. To learn more, see Migrate to Tasks.
Airplane makes it incredibly easy to incrementally build apps that you and your teammates can use. Runbooks are a kind of app that allow you to run multi-step processes, where each step might call an existing task, send a Slack message, or perform some other operation.
In this guide, we'll create a runbook to scan for fraudulent behavior and send a Slack message if anything suspicious is found.

Before you begin

This guide will use the tasks you created in Build a SQL task. Be sure to create the Search users task first.
We'll create a runbook to search for an account, return relevant transactions, and send a Slack notification to alert a channel that the data was accessed.

Create a new runbook

You can create a new runbook from the UI by clicking the + button from the sidebar:
Select Runbook from the dialog and enter in basic runbook information under the Define step.
For this guide, give your runbook a name—e.g. "Scan for fraud"—and one parameter, the Account name to search for:
Select Continue to move to the Build step.

Add a Task block

The Build step is where we construct the logic of the runbook. A runbook is a series of blocks, where each block can be:
  • An existing Task in your Library
  • An operation using builtin functionality (SQL query, REST request, Slack message, and more)
  • A Form block where you can prompt users for additional input and confirmation before proceeding
  • A Note that is presenting basic user information.
For our first block, you can add a task block that uses the Search users task. Click the + button and select the task.
Enter {{params.account_name}} for Query. This allows us to template in the parameter to the task we created earlier, using the parameter passed to the runbook.
This block takes the Account name passed to the runbook and looks for users who match that account name.
Try clicking the Test... button to run the block. You'll likely need to enter in a team name in the Parameters section at the top of the page.

Add a SQL block

If you don't have an existing task, you can quickly add custom logic like a SQL call using the SQL block. In this example, let's take the results of the task block and look up transactions from those users. (Recall we created a Demo DB with users and transactions tables.)
sql
Copied
1
SELECT * FROM transactions
2
JOIN users ON users.id = transactions.sender_id
3
WHERE users.id IN (
4
{{search_users.output.Q1.map(row => row.id).join(",")}}
5
)
Note that we use the previous block's output: its slug is search_users (shown next to the block name), and search_users.output.Q1 contains the list of results from running the first task. We grab the id field from each row and join them with , to form an IN clause. The expression is interpolated into the SQL query via {{ }} - this is using syntax for JS templates.
sql
Copied
1
-- Example query once templates are evaluated:
2
SELECT * FROM transactions
3
JOIN users ON users.id = transactions.sender_id
4
WHERE users.id IN (
5
1,2,3
6
)

Add a Slack and Note block

Now that we've done a search for transactions, let's add a Note block to render data back to the user and a Slack block to notify our security channel that data was accessed.
The Note block supports markdown rendering, so you can render a table with the transactions that were found:
Copied
1
Recent user transactions:
2
3
| user | account | amount |
4
| ---- | ------- | ------ |
5
{{
6
sql.output.Q1.map(r => `| ${r.email} | ${r.account_id} | ${r.amount_dollars} |`)
7
.join("\n")
8
}}
And you can add a Slack block that notifies a channel that sensitive data was accessed:
Copied
1
:rotating_light: {{session.creator.email}} ran {{runbook.name}} and fetched data on {{sql.output.Q1.length}} transactions.
Using the Slack block requires that you first connect Slack to your Airplane team. You may need a Slack admin to do this.

Add a start condition

Lastly, we want to only render a Note and Slack notification if there were transactions. To do this, we can use Start conditions to conditionally execute the block.
In this case, we want to use the following condition:
javascript
Copied
1
sql.output.Q1.length > 0;
The sql block is where we queried for transactions, and Q1 is the first/only query. This skips starting the block if there are 0 transactions.

Save and execute the runbook

Click Create runbook to finish creating the runbook. Try executing the runbook with walmart for the account name:

Wrapping up

That's it! In this guide, you've created a runbook that makes use of other tasks, runs a SQL query directly, and then concludes with a Note and a Slack message.
For futher details, see: