Skip to main content

Ad-hoc Approvals

Introduction

While pre-approval workflows provide a structured way to review schema changes during CI/CD, they may not catch every scenario. For example, manual changes to the target database can introduce undetected diffs that aren't part of the version-controlled history.

In such cases, ad-hoc approvals act as a final checkpoint. When the action ariga/atlas-action/schema/apply runs, it performs an additional check to detect any differences and generates a new plan that must be approved before execution.

Enable ad-hoc approval when:

  • Manual changes are made to the database frequently.
  • You need a last-mile check before production rollout.
  • You want to ensure that all changes are explicitly approved before they are applied.

Overview

Using the lint-review configuration, users may control how the ariga/atlas-action/schema/apply action should behave when it encounters a schema change without a pre-approved plan. The possible values for this configuration are:

Description
ALWAYSPauses the migration process and waits for human approval before applying the schema change.
WARNINGAnalyze the proposed schema change and wait for approval if any diagnostics are found.
ERRORAnalyze the proposed schema change and wait for approval if any severe diagnostics (errors) are found.

Guide: Using Ad-hoc Approvals

Step 1: Set up a simple GitHub repo with Atlas

Follow the setup instructions from the pre-approval guide.

Step 2: Modify the pre-approval.yml workflow

After setting up the pre-approval workflow in the previous step, you will have a file named .github/workflows/pre-approval.yml in your repository. This file contains the workflow that runs on every pull request to check for schema changes. We will modify this file to add the ad-hoc approval step.

name: Atlas Declarative Migrations

on:
workflow_dispatch:
push:
branches:
- master
pull_request:
branches:
- master

permissions:
contents: read
pull-requests: write

jobs:
plan:
if: github.event_name == 'pull_request'
name: Plan Migration
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Setup Atlas
uses: ariga/setup-atlas@v0
with:
cloud-token: ${{ secrets.ATLAS_TOKEN }}

- name: Run schema plan
uses: ariga/atlas-action/schema/plan@v1
env:
GITHUB_TOKEN: ${{ github.token }}
with:
from: ${{ secrets.NEON_DB_URL }}
env: "ci"

deploy:
if: github.event_name == 'push' && github.ref == 'refs/heads/master'
name: Deploy Migration
runs-on: ubuntu-latest
env:
GITHUB_TOKEN: ${{ github.token }}
steps:
- uses: actions/checkout@v4

- name: Setup Atlas
uses: ariga/setup-atlas@v0
with:
cloud-token: ${{ secrets.ATLAS_TOKEN }}

- name: Approve the plan
id: plan-approve
uses: ariga/atlas-action/schema/plan/approve@v1
with:
from: ${{ secrets.NEON_DB_URL }}
env: "cd"

- name: Push the schema
id: schema-push
uses: ariga/atlas-action/schema/push@v1
with:
env: "cd"

- name: Apply the schema
id: schema-apply
uses: ariga/atlas-action/schema/apply@v1
with:
url: ${{ secrets.NEON_DB_URL }}
to: ${{ steps.schema-push.outputs.url }}
lint-review: ALWAYS
env: "cd"

In the deploy job, we added the lint-review: ALWAYS option to the ariga/atlas-action/schema/apply step. This option tells the action to pause and wait for human approval if there are any schema changes that are not pre-approved.

Commit the changes and create pull request for changes:

git checkout -b ad-hoc-approval
git add .
git commit -m "Enable ad-hoc-approval"
git push origin ad-hoc-approval

Step 3: Verify the changes

We currently have an open PR that doesn’t include a pre-approval plan, since there are no schema changes. To simulate a diff, we’ll manually modify the Neon database.

  1. Open the Neon SQL editor.
  2. Add a new column by running the following SQL command:
ALTER TABLE users ADD COLUMN created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP;

At this point, there is a difference between the desired schema and the actual state of the target database.

Now, merge the PR. You’ll see that the action/schema/apply step fails:

Visit the link in the failed job output, you’ll see that the plan includes statement about dropping the created_at column:

Conclusion

This guide showed how ad-hoc approvals add a final layer of protection against unplanned schema changes by introducing a manual review step before deployment.