Airlock
Guides

Custom Workflows

Create workflow files with branch filtering, parallel jobs, and approval gates.

Airlock reads workflow files from .airlock/workflows/*.yml. You can create multiple workflow files — each one matches pushes based on branch patterns.

Creating a Workflow File

Create a new file in .airlock/workflows/:

# .airlock/workflows/feature.yml
name: Feature Branch Pipeline

on:
  push:
    branches:
      - 'feature/**'
      - 'fix/**'

jobs:
  validate:
    name: Validate
    steps:
      - name: lint
        uses: airlock-hq/airlock/defaults/lint@main
        apply-patch: true
      - name: test
        uses: airlock-hq/airlock/defaults/test@main

  ship:
    name: Ship
    needs: validate
    steps:
      - name: push
        uses: airlock-hq/airlock/defaults/push@main
      - name: create-pr
        uses: airlock-hq/airlock/defaults/create-pr@main

Branch Filtering

The on.push.branches field accepts glob patterns to control which pushes trigger this workflow. If multiple workflow files match a branch, all of them run. See the Workflow YAML Schema for all supported patterns.

Parallel Jobs

Split your workflow into parallel jobs using the needs keyword:

jobs:
  lint:
    name: Lint
    steps:
      - name: lint
        uses: airlock-hq/airlock/defaults/lint@main
        apply-patch: true

  test:
    name: Test
    needs: [lint]
    steps:
      - name: test
        uses: airlock-hq/airlock/defaults/test@main

  describe:
    name: Describe
    needs: [lint]
    steps:
      - name: describe
        uses: airlock-hq/airlock/defaults/describe@main

  ship:
    name: Ship
    needs: [test, describe]
    steps:
      - name: push
        uses: airlock-hq/airlock/defaults/push@main
      - name: create-pr
        uses: airlock-hq/airlock/defaults/create-pr@main

In this example, test and describe run in parallel after lint completes. ship waits for both to finish.

Approval Gates

The recommended approach is to use the default gate step, which performs an AI-driven risk assessment and pauses when the risk meets or exceeds your threshold:

- name: review
  uses: airlock-hq/airlock/defaults/gate@main
  env:
    AIRLOCK_RISK_THRESHOLD: medium # never, low, medium, or high

Set AIRLOCK_RISK_THRESHOLD to control sensitivity — low pauses for almost everything, high only pauses for high-risk changes, and never disables approval entirely.

Custom Approval Logic

For full control, use airlock exec await in a step script to pause based on your own conditions:

- name: gate
  run: |
    verdict=$(cat "$AIRLOCK_ARTIFACTS/test_result.json" | airlock exec json verdict)
    if [ "$verdict" != "pass" ]; then
      airlock exec await "Tests failed, please review"
    fi

The step exits 0 normally, and the executor detects the marker and transitions to Awaiting Approval status. You review the results in the desktop app and click Approve to continue.

You can also use require-approval: true for unconditional pausing:

- name: review
  run: 'true'
  require-approval: true

Continue on Error

Allow a step to fail without stopping the workflow:

- name: optional-check
  run: npm run typecheck
  continue-on-error: true

The step is marked as failed in the Activity tab, but the workflow continues.

Shell Selection

By default, steps run in your login shell ($SHELL -l), which sources your profile files and gives full access to your environment — API keys, version managers, PATH entries, etc.

To use a specific shell instead, set the shell property:

- name: build
  run: |
    nvm use
    npm run build
  shell: bash

Available shells: sh, bash, zsh. When shell is omitted, the user's login shell is used with the -l flag for full environment inheritance.