On GitHub, start with the official DBLift Action (uses: dblift/action@v1). It installs the pip package and runs migrate, validate, or info. Other runners stay pip install plus a DBLift command.
The Action does not start a database. Every command needs a reachable one — these recipes supply an ephemeral Postgres service and pass the connection through DBLIFT_DB_URL.
oss · migrate · validate · info
GitHub Actions
dblift/action — command is migrate, validate, or info (ignored when args is set). args is raw CLI passthrough and overrides command. extras defaults to postgresql. Python defaults to 3.11.
.github/workflows/dblift.yml
name: Database migrations
on: pull_request
jobs:
migrate:
runs-on: ubuntu-latest
env:
DBLIFT_DB_URL: postgresql+psycopg://dblift:dblift@localhost:5432/dblift
services:
postgres:
image: postgres:16
env:
POSTGRES_USER: dblift
POSTGRES_PASSWORD: dblift
POSTGRES_DB: dblift
ports:
- 5432:5432
options: >-
--health-cmd "pg_isready -U dblift -d dblift"
--health-interval 10s
--health-timeout 5s
--health-retries 5
steps:
- uses: actions/checkout@v5
- uses: dblift/action@v1
with:
command: migrate
extras: postgresql
Applying the migrations to the ephemeral Postgres service above is the check: dblift's migrate validates before it applies, so a bad checksum or a broken ordering fails the job rather than being written to the database.
Set pr-comment: true to post the pending migration plan as a pull request comment. That needs permissions: pull-requests: write on the workflow or job. On fork PRs the token is read-only, so the Action falls back to the job's step summary. The plan is rendered before the command runs, so command: migrate with pr-comment: true comments the pending set at job start, then applies it. args suppresses the pr-comment plan render.
sql is populated only when pr-comment: true and args is empty. pending-count is empty when args is set or the pending probe fails. Reading exit-code from a later step requires continue-on-error: true on the Action step; otherwise a non-zero dblift status fails the job immediately and later steps never see the output.
Validate on pull requests that touch migrations
on:
pull_request:
paths:
- 'migrations/**'
jobs:
validate:
runs-on: ubuntu-latest
env:
DBLIFT_DB_URL: postgresql+psycopg://dblift:dblift@localhost:5432/dblift
services:
postgres:
image: postgres:16
env:
POSTGRES_USER: dblift
POSTGRES_PASSWORD: dblift
POSTGRES_DB: dblift
ports:
- 5432:5432
options: >-
--health-cmd "pg_isready -U dblift -d dblift"
--health-interval 10s
--health-timeout 5s
--health-retries 5
steps:
- uses: actions/checkout@v5
- uses: dblift/action@v1
with:
command: validate
validate still needs a reachable database. The Action does not start one.
Without the Action
Pip-install on the runner when you are not using the Action:
name: dblift
on:
pull_request:
paths: ["migrations/**"]
jobs:
validate:
runs-on: ubuntu-latest
services:
postgres:
image: postgres:16
env:
POSTGRES_USER: dblift
POSTGRES_PASSWORD: dblift
POSTGRES_DB: dblift
ports: ["5432:5432"]
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
env:
DBLIFT_DB_URL: postgresql+psycopg://dblift:dblift@localhost:5432/dblift
steps:
- uses: actions/checkout@v5
- uses: actions/setup-python@v5
with:
python-version: "3.11"
cache: pip
- run: pip install "dblift[postgresql]"
- run: dblift migrate
- run: dblift validate
- run: dblift info
GitLab CI
.gitlab-ci.yml
stages: [validate]
validate-migrations:
stage: validate
image: python:3.11
services:
- name: postgres:16
alias: postgres
variables:
POSTGRES_USER: dblift
POSTGRES_PASSWORD: dblift
POSTGRES_DB: dblift
DBLIFT_DB_URL: "postgresql+psycopg://dblift:dblift@postgres:5432/dblift"
rules:
- changes: [migrations/**/*]
script:
- pip install "dblift[postgresql]"
- dblift migrate
- dblift validate
- dblift info
[!NOTE] One config, many stages
Rather than exporting a different DBLIFT_DB_URL per stage, declare the stages once under environments: in dblift.yaml and select with --env, DBLIFT_ENV, or a branch mapping under resolve.branch_map.
Pre-commit
.pre-commit-config.yaml
repos:
- repo: https://github.com/dblift/dblift
rev: v3.8.0 # pin to a released tag
hooks:
- id: dblift-validate
additional_dependencies: ["dblift[postgresql]"]
- id: dblift-info
additional_dependencies: ["dblift[postgresql]"]
Because the hooks use language: python, pre-commit builds an isolated environment holding only the base package. Name the driver extra in additional_dependencies for the database you connect to, or the hook will have no driver. The same applies to pre-commit try-repo, locally and in CI.
[!NOTE] No database-free lint in OSS
The hooks need a configured dblift.yaml or DBLIFT_DB_URL and a reachable database — typically the local dev database from your docker-compose.yml. Offline SQL linting is validate-sql, which is Pro.