Approvals

Create custom approval flows on-the-fly.
Tasks support two ways to model approval flows:
  1. Before running: Restrict who can execute a task 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
await airplane.prompt.confirm({
2
description: "Deploying change to the **production** cluster.",
3
reviewers: {
4
groups: ["eng-managers"],
5
// Also accepts a list of users:
6
// users: ["jill@company.com", "jack@company.com"],
7
},
8
});
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 task 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
await airplane.prompt.confirm({
2
description: "Deploying change to the *production* cluster.",
3
reviewers: {
4
allowSelfApprovals: false,
5
groups: ["eng-managers"],
6
// Also accepts a list of users:
7
// users: ["jill@company.com", "jack@company.com"],
8
},
9
});

Conditional approvals

Approvals can be made conditional by wrapping them in an if clause. For example, you could model a support team's refund task where support is empowered to issue refunds immediately if the amount is below a certain threshold:
typescript
Copied
1
export default airplane.task(
2
{
3
slug: "issue_refund_conditionally",
4
parameters: {
5
transaction_id: "shorttext",
6
},
7
},
8
async (params) => {
9
const transaction = await getTransaction(params.transaction_id);
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(
17
{
18
reason: {
19
type: "shorttext",
20
name: "Refund reason",
21
description: "This refund must be approved by a manager with an explanation.",
22
},
23
},
24
{
25
reviewers: {
26
groups: ["managers"],
27
},
28
},
29
));
30
}
31
32
await airplane.execute("issue_refund", {
33
transaction,
34
reason,
35
});
36
},
37
);

Slack support

Airplane's Slack integration supports approving execution requests via Slack. For more information, see Slack integration.

SDK reference

See Prompt SDK reference for more information.