Skip to content

CI/CD Integration

Run migrations and database operations in CI/CD pipelines with dbward’s approval workflow.

  • Exit code 2 = approval pending (pipeline can wait or notify)
  • --idempotency-key = prevent duplicate requests on retry
  • --format json = machine-readable output
  • API tokens = no interactive login needed
name: Deploy
on:
push:
branches: [main]
jobs:
migrate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install dbward
run: |
VERSION=$(curl -s https://api.github.com/repos/dbward-dev/dbward/releases/latest | grep -o '"tag_name": "v[^"]*"' | cut -d'"' -f4 | sed 's/^v//')
curl -sL "https://github.com/dbward-dev/dbward/releases/latest/download/dbward-v${VERSION}-x86_64-unknown-linux-gnu.tar.gz" | tar xz
chmod +x dbward
sudo mv dbward /usr/local/bin/
- name: Run migrations
env:
DBWARD_TOKEN: ${{ secrets.DBWARD_TOKEN }}
run: |
cat > dbward.toml << EOF
default_database = "app"
[server]
url = "${{ vars.DBWARD_SERVER_URL }}"
token = "${DBWARD_TOKEN}"
[databases.app]
EOF
dbward --environment production migrate up \
--idempotency-key "deploy-${{ github.sha }}" \
--ticket "${{ github.server_url }}/${{ github.repository }}/commit/${{ github.sha }}" \
--repo "${{ github.repository }}"
- name: Run migrations
id: migrate
continue-on-error: true
run: dbward --environment production migrate up --idempotency-key "deploy-${{ github.sha }}"
- name: Wait for approval if pending
if: steps.migrate.outcome == 'failure'
run: |
# Exit code 2 = pending approval
REQUEST_ID=$(dbward --environment production migrate status --format json | jq -r '.pending_request_id // empty')
if [ -n "$REQUEST_ID" ]; then
echo "⏳ Waiting for approval: $REQUEST_ID"
echo "Approve with: dbward request approve $REQUEST_ID"
# Optionally: poll until approved (with timeout)
# dbward request resume $REQUEST_ID
fi

Create a dedicated CI token with appropriate permissions:

Terminal window
dbward token create \
--subject "github-actions" \
--role developer \
--expires 90d

Store the token as a repository secret (DBWARD_TOKEN).

CodeMeaningCI action
0SuccessContinue pipeline
1Error (auth failure, network, etc.)Fail pipeline
2Pending approvalWait or notify

Use --idempotency-key to safely retry failed CI jobs:

Terminal window
dbward --environment production migrate up --idempotency-key "deploy-${GITHUB_SHA}"

If the request already exists (same key), dbward returns the existing request status instead of creating a duplicate.

Use --format json for machine-readable output:

Terminal window
dbward --format json --environment production migrate status
{
"migrations": [
{"name": "20260501_create_users", "status": "applied"},
{"name": "20260502_add_index", "status": "pending"}
]
}

Configure workflows to auto-approve non-production environments:

dbward-server.toml
[[workflows]]
database = "*"
environment = "staging"
# No steps = auto-approve

This lets CI deploy to staging without waiting, while production still requires human approval.

Combine with webhooks so approvers are notified immediately:

[[webhooks]]
url = "${SLACK_WEBHOOK_URL}"
events = ["request_created"]
format = "slack"

When CI creates a migration request, the team gets a Slack message with the SQL and an approve prompt.

  • Migrations — Migration file management
  • Workflows — Configure auto-approve for specific environments