Catch breaking database changes in every pull request. Zero config, zero cost โ add schema diff checks to your Bitbucket pipeline in 60 seconds.
๐ SchemaLens Schema Diff Report
| ๐ข Tables Added | 1 |
| ๐ด Tables Removed | 0 |
| ๐ก Tables Modified | 2 |
| โ ๏ธ Breaking Changes | 1 |
| ๐ Risk Score | 42/100 (Medium) |
Generated Migration
ALTER TABLE users
ADD COLUMN email_verified_at TIMESTAMP;
Generated by SchemaLens Bitbucket Pipelines
Team members can download the full markdown report from the Artifacts tab of any pipeline run. The report includes:
Breaking changes like dropped columns, removed indexes, or altered constraints get flagged before merge โ not after deploy.
Every pull request gets a clear schema diff summary posted as a comment. Reviewers see exactly what changed without leaving Bitbucket.
The full markdown report is attached to every pipeline as an artifact. Download it for compliance docs, audits, or offline review.
Set SKIP_NO_SQL_CHANGE: "true" and the step skips entirely when no .sql files were modified โ saving CI minutes.
No database connections, no CLI installation, no license key. Just point the step at two SQL files.
Set FAIL_ON_BREAKING: "true" and the pipeline fails if any dangerous schema changes are detected.
Each diff gets a 0-100 risk score. High-risk migrations get extra scrutiny in code review.
The free tier includes breaking change detection, risk scoring, PR comments, and artifact reports. No credit card required.
Export your database schema to a SQL file as part of your workflow (e.g., pg_dump --schema-only or commit your schema file to the repo).
The step compares the schema from your target branch against the schema in the PR. Any drift is surfaced instantly.
Enable POST_PR_COMMENT: "true" and add a BITBUCKET_ACCESS_TOKEN repository variable. The step posts a formatted summary directly on the pull request.
| Feature | Free Tier | Pro (optional) |
|---|---|---|
| Schema diff summary | โ | โ |
| Breaking change detection | โ | โ |
| Risk score | โ | โ |
| PR comments | โ | โ |
| Pipeline artifacts | โ | โ |
| Smart skip (no SQL changes) | โ | โ |
| Full migration SQL | First 5 lines | โ Complete script |
| Markdown export | โ | โ |
| JSON export | โ | โ |
| Rate limit | 15/min | 30/min |
# Repository variables (Repository settings โ Repository variables)
BITBUCKET_ACCESS_TOKEN # optional โ OAuth token with pullrequest:write for PR comments
SL_LICENSE_KEY # optional โ SchemaLens Pro license key for full migration output
# Step variables
SCHEMA_PATH "db/schema.sql" # Path to current schema SQL file
DIALECT "postgres" # postgres | mysql | sqlite | mssql | oracle
FAIL_ON_BREAKING "false" # true = fail pipeline on breaking changes
POST_PR_COMMENT "false" # true = post report as PR comment (needs token)
SKIP_NO_SQL_CHANGE "false" # true = skip step when no .sql files changed
# bitbucket-pipelines.yml
image: node:20
pipelines:
pull-requests:
'**':
- step:
name: Schema Diff
image: node:20
variables:
SCHEMA_PATH: "db/schema.sql"
DIALECT: "postgres"
POST_PR_COMMENT: "true"
FAIL_ON_BREAKING: "true"
SKIP_NO_SQL_CHANGE: "true"
script:
- apt-get update && apt-get install -y jq curl
- |
if [ ! -f "$SCHEMA_PATH" ]; then
echo "Schema file not found: $SCHEMA_PATH"
exit 1
fi
- |
if [ "$SKIP_NO_SQL_CHANGE" = "true" ]; then
git fetch origin "$BITBUCKET_PR_DESTINATION_BRANCH"
if git diff --name-only "origin/$BITBUCKET_PR_DESTINATION_BRANCH..$BITBUCKET_COMMIT" | grep -q '\.sql$'; then
echo "Schema files changed โ running diff."
else
echo "No .sql files changed โ skipping schema diff to save CI minutes."
exit 0
fi
fi
- |
git fetch origin "$BITBUCKET_PR_DESTINATION_BRANCH"
git show "origin/$BITBUCKET_PR_DESTINATION_BRANCH:$SCHEMA_PATH" > /tmp/schema_base.sql 2>/dev/null || echo "-- No base schema" > /tmp/schema_base.sql
- |
ENDPOINT="https://schemalens.tech/api/free-diff"
if [ -n "$SL_LICENSE_KEY" ]; then
ENDPOINT="https://schemalens.tech/api/diff"
echo "Using SchemaLens Pro endpoint."
fi
BODY=$(jq -n \
--arg schemaA "$(cat /tmp/schema_base.sql)" \
--arg schemaB "$(cat "$SCHEMA_PATH")" \
--arg dialect "$DIALECT" \
--arg format "markdown" \
'{schemaA: $schemaA, schemaB: $schemaB, dialect: $dialect, format: $format}')
for attempt in 1 2 3; do
HTTP_STATUS=$(curl -s -o /tmp/response.json -w "%{http_code}" -X POST "$ENDPOINT" \
-H "Content-Type: application/json" \
${SL_LICENSE_KEY:+-H "X-License-Key: $SL_LICENSE_KEY"} \
-d "$BODY" || echo "000")
if [ "$HTTP_STATUS" = "200" ]; then break; fi
echo "Attempt $attempt failed ($HTTP_STATUS). Retrying..."
sleep "$((attempt * 2))"
done
if [ "$HTTP_STATUS" != "200" ]; then
echo "SchemaLens API failed after 3 attempts"
exit 1
fi
- jq -r '.markdown // .migrationTeaser' /tmp/response.json > schema_diff_report.md
- cat schema_diff_report.md
- |
if [ "$POST_PR_COMMENT" = "true" ] && [ -n "$BITBUCKET_ACCESS_TOKEN" ]; then
REPORT=$(cat schema_diff_report.md | sed 's/"/\\"/g' | sed ':a;N;$!ba;s/\n/\\n/g')
curl -s -X POST \
-H "Authorization: Bearer $BITBUCKET_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
"https://api.bitbucket.org/2.0/repositories/$BITBUCKET_WORKSPACE/$BITBUCKET_REPO_SLUG/pullrequests/$BITBUCKET_PR_ID/comments" \
-d "{\"content\": {\"raw\": \"$REPORT\"}}" || echo "Warning: failed to post PR comment."
fi
- |
BCOUNT=$(jq -r '(.summary.breakingChangeCount // (.breakingChanges | length) // 0)' /tmp/response.json)
if [ "$FAIL_ON_BREAKING" = "true" ] && [ "$BCOUNT" != "0" ]; then
echo "Breaking changes detected: $BCOUNT"
exit 1
fi
artifacts:
- schema_diff_report.md