Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 66 additions & 0 deletions .github/scripts/check-migrations-and-backup.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
#!/bin/bash
set -euxo pipefail

# Arguments
WORKDIR=$1
SUPABASE_DB_URL=$2

if [ -z "$WORKDIR" ]; then
echo "Error: WORKDIR is required."
exit 1
fi

pushd "$WORKDIR"

if [ -z "$SUPABASE_DB_URL" ]; then
echo "Error: SUPABASE_DB_URL is required."
exit 1
fi

set +u
if [ -z "$GITHUB_OUTPUT" ]; then
echo "GITHUB_OUTPUT is not set. Using /dev/null for local testing."
GITHUB_OUTPUT="/dev/null"
fi
set -u

# Allow dry run mode for testing
DRY_RUN=${DRY_RUN:-false}

echo "Checking for pending migrations..."

# Capture output from dry-run
# pnpm supabase needs to be run where supabase config/migrations are (apps/frontend)
# usage of 2>&1 to capture stderr as well
OUTPUT=$(pnpm supabase db push --dry-run --db-url "$SUPABASE_DB_URL" 2>&1) || true
echo "$OUTPUT"

if echo "$OUTPUT" | grep -q "Remote database is up to date"; then
echo "No migrations needed."
echo "needs_migration=false" >> $GITHUB_OUTPUT
elif echo "$OUTPUT" | grep -q "Would push these migrations"; then
echo "Migrations needed. Proceeding with backup."
echo "needs_migration=true" >> $GITHUB_OUTPUT

# Perform backup
TIMESTAMP=$(date -u +"%Y%m%d%H%M%S")
BACKUP_FILE="${TIMESTAMP}Z_backup.sql.gz"

if [[ "$DRY_RUN" == "true" ]]; then
echo "Dry run enabled, skipping actual backup creation."
echo "backup_file=$BACKUP_FILE" >> $GITHUB_OUTPUT
else
echo "Running pg_dump..."
pg_dump "$SUPABASE_DB_URL" | gzip > "$BACKUP_FILE"
echo "Creating backup file: $BACKUP_FILE"
fi
Comment on lines +52 to +56
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At some point we might need to remove this as it could take a long time. Not for the near future tho.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ya haha. We are at 1G for now. Also, this is conditional atm so I'm hoping this isn't too frustrating.


echo "Backup created at $BACKUP_FILE"
echo "backup_file=$BACKUP_FILE" >> $GITHUB_OUTPUT
else
echo "Error: Unexpected output from dry run."
echo "$OUTPUT"
exit 1
fi

popd
87 changes: 87 additions & 0 deletions .github/workflows/db-migration.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
name: Supabase DB Migration
permissions:
contents: read
id-token: write

# We need to match both pull_request and merge_group events to ensure that
# we stop broken migrations from being merged into main. This ensures that
# we can add this workflow as a required check. Without the pull_request event,
# we, oddly, would not be able to add this as a required check on and the
# merge_group.
on:
pull_request:
branches:
- main
merge_group:
branches:
- main

jobs:
migrate-db:
runs-on: ubuntu-latest
environment: deploy
steps:
- uses: actions/checkout@v3
if: ${{ github.event_name == 'merge_group' }}

- name: Authenticate to Google Cloud
uses: google-github-actions/auth@v2
with:
credentials_json: '${{ secrets.GOOGLE_CREDENTIALS_JSON }}'
if: ${{ github.event_name == 'merge_group' }}

- name: Set up Cloud SDK
uses: google-github-actions/setup-gcloud@v2
with:
version: '>= 363.0.0'
if: ${{ github.event_name == 'merge_group' }}

- name: Setup pnpm
uses: pnpm/action-setup@v4
with:
version: 10
run_install: |
- recursive: true
args: [--frozen-lockfile, --strict-peer-dependencies]
if: ${{ github.event_name == 'merge_group' }}

- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: "22.x"
cache: "pnpm"
if: ${{ github.event_name == 'merge_group' }}

- name: Install postgresql-client
run: |
sudo apt-get update
sudo apt-get install -y postgresql-client
if: ${{ github.event_name == 'merge_group' }}

- name: Check migrations and backup
id: check_migrations
run: |
bash .github/scripts/check-migrations-and-backup.sh "apps/frontend" "$SUPABASE_DB_URL"
env:
SUPABASE_ACCESS_TOKEN: ${{ secrets.SUPABASE_ACCESS_TOKEN }}
SUPABASE_DB_URL: ${{ secrets.SUPABASE_PRODUCTION_DB_URL }}
if: ${{ github.event_name == 'merge_group' }}

- name: Upload backup to GCS
working-directory: apps/frontend
run: |
BACKUP_FILE="${{ steps.check_migrations.outputs.backup_file }}"
echo "Uploading backup ${BACKUP_FILE} to gs://${DB_BACKUP_BUCKET}/${BACKUP_FILE}"
gcloud storage cp "${BACKUP_FILE}" "gs://${DB_BACKUP_BUCKET}/${BACKUP_FILE}"
env:
DB_BACKUP_BUCKET: ${{ secrets.DB_BACKUP_BUCKET }}
if: ${{ github.event_name == 'merge_group' && steps.check_migrations.outputs.needs_migration == 'true' }}

- name: Push Supabase migrations
working-directory: apps/frontend
run: |
pnpm supabase db push --db-url "$SUPABASE_DB_URL"
env:
SUPABASE_ACCESS_TOKEN: ${{ secrets.SUPABASE_ACCESS_TOKEN }}
SUPABASE_DB_URL: ${{ secrets.SUPABASE_PRODUCTION_DB_URL }}
if: ${{ github.event_name == 'merge_group' && steps.check_migrations.outputs.needs_migration == 'true' }}