Airplane quickstart guide

Build a multi-step workflow in under 15 minutes
This guide will walk you through how to use Airplane to delete a user and have a temporary archive of their data sent via a link. We'll set up a task and a runbook end-to-end and explore a couple of key Airplane features along the way including adding parameters, deploying code, and referencing outputs.

Our use case

We're going to create a workflow in Airplane that lets non-engineers perform a "delete user" operation. This is a common use case for Airplane. Companies need to delete users due to GDPR or CCPA reasons, and being able to deploy a script to Airplane that performs this operation lets non-engineers perform the task safely.
First, we're going to create a task in Airplane that performs a user deletion. Then, we'll build a runbook that uses that task and also sends out a Slack notification afterwards.

Create a task

We're going to create a GDPR deletion task that deletes a user's data by looking up their email.
Once you sign up for Airplane, you land at the library. From here, click Create a task to reach the new task page and select Node from the options.
In this tutorial, we're going to select Node. For this user deletion task, we want to write a custom JS script that hits a deletion endpoint that we've already defined.

Define your task

The next step is defining our task. Fill in the task definition form with the following values:
  • Name: Delete user by email
  • Description: Permanently deletes a user who has a matching email
  • Folder: Ignore this for now
Since we're using the user's email to determine which user to delete from the system, whoever runs this task will need to input the user's email. Let's add a parameter that represents the user's email. Click Add parameter and enter the following information:
  • Name: User email
  • Description: The email address of the user to be deleted
  • Type: Short text
Once you click the Add button, it will take you back to the task definition screen where you can now see the parameter you just input listed there along with the task name and description.
Once the fields under the task definition screen have been completed, click Continue.

Build your task

Since this is a Node script, we can add in environment variables or select the version of Node that we want to use to run this script. For this tutorial, the default Node version will be sufficient, and we don't need any env vars.

Advanced settings

The next screen displays "Advanced settings". You can set explicit permissions here and assign users and groups to specific roles, such as admin or requestor. Let's leave these as team access for this task and click Create task.
You've created the task but there's no code backing the task yet! Now we'll write and deploy some JavaScript to implement our code.

Using the CLI to deploy your task

After you click Create task, you'll see a short list of instructions on how to deploy the code.
If you haven't yet, first install the Airplane CLI (airplane) by following the installation instructions (2 min action). We'll be using airplane to deploy from the terminal.
Once you've installed and logged in to the CLI, create an empty folder and navigate inside it.
bash
Copied
1
mkdir airplane_test
2
cd airplane_test
From within this directory, you can run the init command shown on the task page:
bash
Copied
1
airplane init --slug delete_user_by_email ./delete_user_by_email.js
You can choose any path you want for where the script is stored. To use TypeScript, use a .ts extension instead of .js.
This creates a script that looks something like this:
javascript
Copied
1
// Linked to https://app.airplane.dev/t/delete_user_by_email [do not edit this line]
2
3
export default async function (params) {
4
console.log("parameters: ", params);
5
}
As noted by the comment in the script, you're welcome to change the script but leave the first line intact. The Airplane CLI uses that line to identify which task your code corresponds to.
For JavaScript (Node) tasks, Airplane looks for the default export function and calls it. The first argument will contain the parameters for the run. When we configured our task, we created a single parameter, "user email". This means that params will be an object that looks like this:
Copied
1
{
2
user_email: "email@example.com"
3
}
We'll modify this code in a bit, but just to test it out, you can deploy the task:
bash
Copied
1
airplane deploy ./delete_user_by_email.js
This will bundle up the source code, build it, and deploy it to Airplane. This can take a couple minutes. Go back to the Library (or reload it), and you should now be able to execute it!
Enter any email and hit Execute task. The task should succeed. At the bottom of the results page is a section that says Output | JSON | Logs. Right now, the Output and JSON sections are blank, but if you click on Logs you will see something like this:
The "params" object containing the "user_email" parameter is getting printed to stdout, as we saw in the default script.

Create a non-trivial task

Now, let's modify our task to do something a bit more interesting. This is a "Delete user by email" task, so we want our script to actually delete the user. In order to do this, we'll make an HTTP request to a sample API endpoint that we've setup for you.
In the directory with our script, let's create an NPM package. If you're using PowerShell on Windows, you'll need to install Node.js.
bash
Copied
1
# This creates a package.json file. Make sure you're not in a directory
2
# that already has one!
3
npm init -y
Next, let's install the airplane SDK as well as node-fetch:
bash
Copied
1
npm install airplane node-fetch
This should have updated your package.json with airplane and node-fetch. The Airplane CLI looks for package.json when deploying and will use it to install dependencies. Both NPM and Yarn lock files are supported.
Update your delete_user_by_email.js script with the following code:
javascript
Copied
1
// Linked to https://app.airplane.dev/t/delete_user_by_email [do not edit this line]
2
3
import airplane from "airplane";
4
import fetch from "node-fetch";
5
6
export default async function (params) {
7
// Send an API request to lookup this user's ID.
8
const getResp = await fetch(
9
`https://demos.airplane.sh/users/get?email=${params.user_email}`
10
);
11
if (getResp.status !== 200) {
12
airplane.setOutput(`Failed to get user: ${getResp.status}`, "error");
13
process.exit(1);
14
}
15
const { user } = await getResp.json();
16
17
// Send another API request to perform the deletion, using the ID from the previous request.
18
const delResp = await fetch(
19
`https://demos.airplane.sh/users/delete?id=${user.id}`,
20
{
21
method: "delete",
22
}
23
);
24
if (delResp.status !== 200) {
25
airplane.setOutput(`Failed to delete user: ${delResp.status}`, "error");
26
process.exit(1);
27
}
28
const { archive_link, status } = await delResp.json();
29
30
// Output results as a structured table
31
airplane.setOutput({
32
email: params.user_email,
33
archive: archive_link,
34
status,
35
});
36
}
After updating your code and saving, redeploy your code:
bash
Copied
1
airplane deploy ./delete_user_by_email.js
Now, navigate back to the Airplane UI in your web browser, and try executing the task again with any sample email. Click Run again to take you back to the option to Execute task. This time, the run results page will look a bit different:
You'll notice that now the output section is no longer blank. We see a structured table that contains the data returned from the HTTP request we made to our sample API endpoint. It shows the following information:
  • email: the email of the user we chose to delete
  • archive: A temporary link to the user's historical data so we can email that to them as part of our deletion process
  • status: a status showing whether the deletion succeeded or failed
If you click on Logs you can still see the raw stdout logs, and if you click on JSON you can see this output table as a raw JSON object.

Runbooks: Add more steps to your task

Now that you've created a task to delete a user by email, let's add on the second step of the workflow. After the deletion process is complete, we also want to automatically be notified with a link to their historical data.
We're going to use a runbook to do this. Runbooks are multi-step operations that can be used to look up information, execute operations, send notifications, and perform other functions all together. The second step we're adding is sending a Slack notification containing the link to the temporary historical data archive.
Let's start by creating a new runbook from the library.

Define your runbook

Similar to the way we defined our task earlier, we're going to define and add parameters for our runbook.
Let's call this runbook "Delete user and send historical data on Slack" where the runbook "permanently deletes a user based on their email and sends a Slack notification with a link to their historical data." Use the following information:
  • Name: Delete user and send link to historical data
  • Description: Permanently deletes a user based on their email and sends notification with historical data link
  • Folder: Ignore this for now
Since we're using the user's email to determine which user to delete from the system, the input will be the user's email. Let's add a runbook parameter that represents the user's email.
Click add parameter and enter the following information:
  • Name: User email
  • Description: The email address of the user to be deleted
  • Type: Short text
Once you click Add it will take you back to the runbook definition screen where you now see the name, description, and parameter you just input listed there.
Once you've defined your runbook, click Continue, which takes you to the "Build Your Runbook" screen.

Build your runbook

Runbooks are comprised of a series of single-operations called blocks. Blocks can be tasks or they can be other functions that take in inputs, perform an operation, and produce an output. All tasks can be used as blocks but you don't necessarily need to save every block you use in your runbook as its own task.
For the first block, let's select our Delete user by email task that we just created. Select the task from the list on the left.
This will complete the same function as the task we created before returning an output table with email, status, message, and archive.
What we want to do now is use a Slack block to automatically send a Slack message with a link to the user's historical data. You'll recall that this was part of the output table when we ran this task previously. But before we add this second step to the runbook, let's pass in our email parameter and test to see that the task is working as expected.

Test blocks

Under Parameters at the top, enter any email. You can pass in the email that you're using by inputing {{params.user_email}} instead of typing "madhura@example.com" in manually. This will make it such that the block Delete user by email will automatically use what you enter in the parameter when it runs.
When you click Test, you'll see a preview of the test block appear. The email that you've entered under the top-level params should be the email that you see in the display box. Click Test again to run the task.
The run should have succeeded with the same output we saw from the previous section.

Add a Slack block

In our output, the column archive has a link to the user's historical data. Now, we want to automatically send a Slack message with this link. To do this, let's add a second block to the runbook: a Slack block. You can do this by clicking the + sign just below the Delete user by email block.
Select Slack from the block types.
You'll need to connect your team's Slack account to use this. It'll take just a couple of minutes to configure Slack by following the prompts below.
You can find more details on our Slack integration in our docs.
Once configured, your runbook builder should look like the below:
There are two fields here: Channel name and message.
For channel name, type the name of the Slack channel you would like to send the message to.

Reference parameters and outputs

We want our Slack message to print out the archive field from our first block, as well as show the email of the user that was deleted. Input the following into the Message box:
Copied
1
User tied to email {{params.user_email}} has successfully been deleted.
2
The user's historical data can be found here:
3
{{delete_user_by_email.output.archive}}
  • {{params.user_email}} refers to the "user_email" top-level runbook parameter. "Params" is a global object that contains all the parameters of a runbook.
  • {{delete_user_by_email.output.archive}} will reference the output of your Delete user by email block and print what's under archive in the structured table.
Click the Test button on this block and you'll see a preview of the Slack message appear. The email that you've entered as your param should be the email that you see in the display box and you should also see the link displayed where you're pulling the archive column of the structured table from your previous task's output. Click Test to run the task and send a Slack message.
You should see that your Slack block succeeded:
Since testing the block executes it, you should also receive a Slack notification with the message that we configured using inputs and outputs from your runbook. You can see that we've successfully referenced the user's email and automatically printed the link to the user's historical data.

Advanced settings

Next, click Continue in the runbook builder to take you to the "Advanced Settings" screen. You'll see a similar screen to when you created your Delete user by email task. You can set explicit permissions here and assign users and groups to specific roles. Let's leave these as team access for now and click Create runbook.

Execute your runbook

Your completed runbook should look something like the below. You can see all tasks and runbooks you've created in the Library section of the Airplane sidebar. When you select the runbook you just created "Delete user and send link to historical data," you'll see a web form with the parameters you configured.
Fill out the user email with any email and click Execute runbook to run it. When the runbook begins running, you'll see each block highlighted in blue if it's currently in progress, green if it's finished, and grey if it hasn't started yet.
That's it! Congrats on creating your first runbook.

More features

This was a quick onboarding guide to walk you through the basic process of creating a task and then a runbook for a real business use case. Airplane has a lot of use cases and features that we didn't cover in this guide. Here are a few other resources that are worth diving into to learn more:
You can see a full list of tutorials and guides in our tutorials library.
Thanks for using Airplane and don't hesitate to reach out at hello@airplane.dev or drop us a message on Intercom (the Help and Support button in the lower-left corner of the app).