Approvals

Create custom approvals flows on-the-fly.
Workflows support two ways to model approval flows:
  1. Before running: Restrict who can execute a workflow and require others to issue an execution request. To learn more, see Permissions.
  2. While running: Dynamically require approvals at runtime via prompt reviewers.

Prompt reviewers

With Prompts, you can gather input from operators through parameter forms. By default, anyone who can access the associated run can also respond to the prompt, but this can be locked down using the optional reviewers field.
To give an example, you could enforce that someone from the eng-managers group approves a high-risk deployment:
typescript
Copied
1
const confirm = await airplane.prompt.boolean("Continue?", {
2
description: "Deploying change to the **production** cluster.",
3
default: true,
4
reviewers: {
5
groups: ["eng-managers"],
6
// Also accepts a list of users:
7
// users: ["jill@company.com", "jack@company.com"],
8
},
9
});
10
if (confirm) {
11
// perform the deployment...
12
}
This will render a prompt within the run's UI:
Groups are referenced by their slug which can be found in-app within the groups page. Users are referenced by their email address.

Self approvals

If you need to prevent a user from approving prompts created by a workflow they executed, you can disable self-approvals.
This allows us to modify the example above such that an engineering manager cannot approve their own deployment without the approval of another engineering manager.
typescript
Copied
1
const confirm = await airplane.prompt.boolean("Continue?", {
2
description: "Deploying change to the *production* cluster.",
3
default: true,
4
reviewers: {
5
allowSelfApprovals: false,
6
groups: ["eng-managers"],
7
// Also accepts a list of users:
8
// users: ["jill@company.com", "jack@company.com"],
9
},
10
});
11
if (confirm) {
12
// perform the deployment...
13
}

Conditional approvals

Approvals can be made conditional by wrapping them in an if clause. For example, you could model a support team's refund workflow where support is empowered to issue refunds immediately if the amount is below a certain threshold:
typescript
Copied
1
import airplane from "airplane";
2
3
export default airplane.workflow(
4
{
5
slug: "issue_refund_conditionally",
6
parameters: { transactionID: "string" },
7
},
8
async (params) => {
9
const transaction = await getTransaction(params.transactionID);
10
11
// If this refund is above a certain threshold, ensure we get a manager's approval
12
// before issuing it. For documentation purposes, the manager must also provide a
13
// reason for approving the refund.
14
let reason = "";
15
if (transaction.amount > 30) {
16
reason = await airplane.prompt.text("Refund reason", {
17
description: "This refund must be approved by a manager with an explanation.",
18
reviewers: {
19
groups: ["managers"],
20
},
21
});
22
}
23
24
await airplane.execute("issue_refund", {
25
transaction,
26
reason,
27
});
28
}
29
);