Skip to content

anies1212/supabase-diff-action

Repository files navigation

Supabase Diff Action

GitHub release License: MIT GitHub Actions

A GitHub Action that detects differences between Supabase environments and reports them as Pull Request comments.

Supports 2-environment (dev/prd) or 3-environment (dev/stg/prd) comparison.

Catch deployment discrepancies and environment inconsistencies early to maintain production stability.

Features

  • Edge Functions - Detect existence and version differences
  • RLS Policies - Detect Row Level Security policy definition differences
  • SQL Functions - Detect PostgreSQL function definition differences
  • Schemas - Detect table structure differences (columns, indexes, constraints)
  • Multi-environment support - Compare dev→prd or dev→stg→prd
  • Post readable Markdown-formatted comments to Pull Requests
  • Option to fail CI when differences are detected

Limitations

Edge Functions

Edge Functions comparison is limited to metadata only (name, version, status). The Supabase Management API does not expose the function source code, so we cannot compare the actual implementation.

What we can compare What we cannot compare
Function existence Source code
Version number Function logic
Status Dependencies

Note: Different version numbers indicate different deployment counts, not necessarily different code. If you need source code comparison, manage your Edge Functions in your Git repository and use standard diff tools.

Quick Start

1. Configure Secrets

In your repository's Settings > Secrets and variables > Actions, add:

Secret Name Description How to Get
SUPABASE_ACCESS_TOKEN Management API token Supabase Dashboard
SUPABASE_DEV_PROJECT_REF Dev environment project ref Project Settings > General
SUPABASE_DEV_DB_URL Dev environment DB connection URL See Database URL Format below
SUPABASE_STG_PROJECT_REF Staging environment project ref (optional) Project Settings > General
SUPABASE_STG_DB_URL Staging environment DB connection URL (optional) See Database URL Format below
SUPABASE_PRD_PROJECT_REF Prod environment project ref Project Settings > General
SUPABASE_PRD_DB_URL Prod environment DB connection URL See Database URL Format below

Note: If you provide both stg_project_ref and stg_db_url, the action will compare dev→stg and stg→prd. Otherwise, it compares dev→prd directly.

Database URL Format

⚠️ Important: You must use the Session Pooler connection URL. The legacy db.[project-ref].supabase.co format is deprecated and will not work.

How to get the correct URL:

  1. Go to your Supabase project dashboard
  2. Click the "Connect" button (green button in the top right)
  3. Select "Session Pooler" (port 5432)
  4. Copy the connection string

Correct format:

postgresql://postgres.[PROJECT-REF]:[PASSWORD]@aws-0-[REGION].pooler.supabase.com:5432/postgres

Example:

postgresql://postgres.abcdefghijklmnop:[email protected]:5432/postgres

Why Session Pooler?

  • GitHub Actions runners only support IPv4 connections
  • Session Pooler is IPv4 compatible, while Transaction Pooler requires an IPv4 add-on
  • Session Pooler supports PREPARE statements (required by some PostgreSQL clients)
  • The legacy direct connection (db.[ref].supabase.co) may not resolve
Connection Type Port IPv4 PREPARE Recommendation
Session Pooler 5432 ✅ Compatible ✅ Supported Recommended
Transaction Pooler 6543 ❌ Requires add-on ❌ Not supported Not recommended
Direct Connection 5432 ❌ May not resolve ✅ Supported Local development only

2. Create Workflow File

.github/workflows/supabase-diff.yml:

name: Supabase Diff Check

on:
  pull_request:
    branches: [main]

jobs:
  diff-check:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: anies1212/supabase-diff-action@v1
        with:
          supabase_access_token: ${{ secrets.SUPABASE_ACCESS_TOKEN }}
          dev_project_ref: ${{ secrets.SUPABASE_DEV_PROJECT_REF }}
          dev_db_url: ${{ secrets.SUPABASE_DEV_DB_URL }}
          prd_project_ref: ${{ secrets.SUPABASE_PRD_PROJECT_REF }}
          prd_db_url: ${{ secrets.SUPABASE_PRD_DB_URL }}
          github_token: ${{ secrets.GITHUB_TOKEN }}

Inputs

Required Inputs

Input Description
supabase_access_token Supabase Management API access token
dev_project_ref Dev environment project reference
dev_db_url Dev environment PostgreSQL connection URL
prd_project_ref Prod environment project reference
prd_db_url Prod environment PostgreSQL connection URL
github_token GitHub Token (for PR comments)

Optional Inputs

Input Default Description
stg_project_ref - Staging environment project reference
stg_db_url - Staging environment PostgreSQL connection URL
check_edge_functions true Check Edge Functions
check_rls_policies true Check RLS Policies
check_sql_functions true Check SQL Functions
check_schemas true Check Schemas
fail_on_diff false Fail the action if differences are found
excluded_schemas (※1) Comma-separated list of schemas to exclude

※1: Default excluded schemas: pg_catalog, information_schema, extensions, pg_toast, pgsodium, vault, graphql, graphql_public

Outputs

Output Description
has_diff Whether differences were found (true/false)
diff_summary Diff summary (JSON)
edge_functions_diff Edge Functions diff (JSON)
rls_policies_diff RLS Policies diff (JSON)
sql_functions_diff SQL Functions diff (JSON)
schemas_diff Schemas diff (JSON)

Using Outputs

- uses: anies1212/supabase-diff-action@v1
  id: diff
  with:
    # ... inputs

- name: Handle differences
  if: steps.diff.outputs.has_diff == 'true'
  run: echo "Differences found between environments"

PR Comment Example

When differences are detected, a comment like this is posted to the PR:


Supabase Environment Diff

Differences detected between dev and prod environments.

Edge Functions

Function dev prod Status
send-email v3 v2 version: 3 → 2
new-feature v1 - Only in dev

RLS Policies

Table Policy dev prod Status
public.users select_own qual: definition differs

SQL Functions

Schema Function dev prod Status
public calculate_total(integer) definition: differs

Schemas

Schema Table dev prod Status
public orders Has differences
Diff Details
public.orders
  • column "discount" data_type: numeric → integer
  • index "orders_user_id_idx": only in dev

Advanced Usage

3-Environment Comparison (dev → stg → prd)

- uses: anies1212/supabase-diff-action@v1
  with:
    supabase_access_token: ${{ secrets.SUPABASE_ACCESS_TOKEN }}
    dev_project_ref: ${{ secrets.SUPABASE_DEV_PROJECT_REF }}
    dev_db_url: ${{ secrets.SUPABASE_DEV_DB_URL }}
    stg_project_ref: ${{ secrets.SUPABASE_STG_PROJECT_REF }}
    stg_db_url: ${{ secrets.SUPABASE_STG_DB_URL }}
    prd_project_ref: ${{ secrets.SUPABASE_PRD_PROJECT_REF }}
    prd_db_url: ${{ secrets.SUPABASE_PRD_DB_URL }}
    github_token: ${{ secrets.GITHUB_TOKEN }}

When staging environment is configured, the action compares:

  • Dev → Stg: Detect items only in dev, only in stg, or different between dev and stg
  • Stg → Prd: Detect items only in stg, only in prd, or different between stg and prd

Run Specific Checks Only

- uses: anies1212/supabase-diff-action@v1
  with:
    # ... required inputs
    check_edge_functions: 'true'
    check_rls_policies: 'true'
    check_sql_functions: 'false'  # Skip SQL Functions
    check_schemas: 'false'         # Skip Schemas

Fail CI on Differences

- uses: anies1212/supabase-diff-action@v1
  with:
    # ... required inputs
    fail_on_diff: 'true'

Exclude Specific Schemas

- uses: anies1212/supabase-diff-action@v1
  with:
    # ... required inputs
    excluded_schemas: 'pg_catalog,information_schema,extensions,my_internal_schema'

Development

Requirements

  • Node.js 20.x
  • npm

Setup

# Clone the repository
git clone https://github.com/anies1212/supabase-diff-action.git
cd supabase-diff-action

# Install dependencies
npm install

# Build
npm run build

# Type check
npm run typecheck

# Test
npm run test

Directory Structure

supabase-diff-action/
├── action.yml              # GitHub Action definition
├── src/
│   ├── index.ts            # Entry point
│   ├── types.ts            # Type definitions
│   ├── supabase/
│   │   ├── functions.ts    # Edge Functions fetcher
│   │   ├── rls.ts          # RLS Policies fetcher
│   │   ├── sql-functions.ts # SQL Functions fetcher
│   │   └── schemas.ts      # Table schemas fetcher
│   ├── diff/
│   │   └── compare.ts      # Diff comparison logic
│   └── github/
│       └── comment.ts      # PR comment posting
└── dist/                   # Built files

Contributing

Contributions are welcome! See CONTRIBUTING.md for details.

Security

If you discover a security vulnerability, please see SECURITY.md.

License

MIT License

Related Links

About

Detect differences between Supabase environments (Edge Functions, RLS, SQL Functions, Schemas)

Resources

License

Contributing

Security policy

Stars

Watchers

Forks

Packages

 
 
 

Contributors