Skip to main content

Ad-hoc Approvals for Declarative Schema Migrations Using GitLab CI

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 component schema-apply runs, it performs an additional check to detect any remaining, unapproved differences between the desired and target schemas 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 schema-apply component 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 GitLab repo with Atlas

Follow the setup instructions from the pre-approval guide.

Step 2: Modify the .gitlab-ci.yml pipeline

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

services:
- postgres:latest

variables:
POSTGRES_DB: dev
POSTGRES_USER: postgres
POSTGRES_PASSWORD: pass

stages:
- plan
- deploy

include:
- component: $CI_SERVER_FQDN/arigaio/atlas/schema-plan@~latest
inputs:
stage: plan
env: ci
dev-url: 'postgres://postgres:pass@postgres/dev?sslmode=disable'
atlas-cloud-token: $ATLAS_CLOUD_TOKEN
gitlab-token: $GITLAB_TOKEN
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"

- component: $CI_SERVER_FQDN/arigaio/atlas/schema-plan-approve@~latest
inputs:
stage: deploy
branches:
- main
env: cd
from: $NEON_DB_URL
atlas-cloud-token: $ATLAS_CLOUD_TOKEN
rules:
- if: $CI_COMMIT_BRANCH == "main"

- component: $CI_SERVER_FQDN/arigaio/atlas/schema-push@~latest
inputs:
stage: deploy
branches:
- main
env: cd
atlas-cloud-token: $ATLAS_CLOUD_TOKEN
rules:
- if: $CI_COMMIT_BRANCH == "main"

- component: $CI_SERVER_FQDN/arigaio/atlas/schema-apply@~latest
inputs:
stage: deploy
branches:
- main
url: $NEON_DB_URL
lint-review: ALWAYS
env: cd
atlas-cloud-token: $ATLAS_CLOUD_TOKEN
rules:
- if: $CI_COMMIT_BRANCH == "main"

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

Commit the changes and create merge 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 MR 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 MR. You'll see that the schema-apply component fails and requires approval.

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.