Skip to content
Closed
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
6 changes: 6 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,9 @@ jobs:
- name: Verify NX_BASE and NX_HEAD are set
run: echo "BASE=$NX_BASE HEAD=$NX_HEAD"

- name: Pre-start Supabase for affected packages
run: ./scripts/ci-prestart-supabase.sh core client

- name: Quality gate (lint + typecheck + test)
run: pnpm nx affected -t lint typecheck test --parallel --configuration=production --base="$NX_BASE" --head="$NX_HEAD"

Expand Down Expand Up @@ -96,6 +99,9 @@ jobs:
- name: Verify NX_BASE and NX_HEAD are set
run: echo "BASE=$NX_BASE HEAD=$NX_HEAD"

- name: Pre-start Supabase for affected packages
run: ./scripts/ci-prestart-supabase.sh edge-worker

- name: Check if edge-worker e2e tests are affected
id: check-affected
run: |
Expand Down
5 changes: 4 additions & 1 deletion pkgs/client/project.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
"projectType": "library",
"tags": [],
"targets": {
"supabase:ci-marker": {
"executor": "nx:noop"
},
"build": {
"executor": "nx:noop",
"inputs": ["production", "^production"],
Expand Down Expand Up @@ -202,7 +205,7 @@
"executor": "nx:run-commands",
"cache": true,
"inputs": ["production", "^production"],
"dependsOn": ["^build"],
"dependsOn": ["^build", "lint"],
"options": {
"cwd": "{projectRoot}",
"command": "pnpm vitest --typecheck.only --run --config vitest.typecheck.config.ts"
Expand Down
15 changes: 15 additions & 0 deletions pkgs/client/scripts/prepare-supabase.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#!/bin/bash
# Prepares Supabase for client package by copying migrations and seed from core.
# Called automatically by scripts/supabase-start.sh before starting Supabase.

set -e

SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
PKG_DIR="$(dirname "$SCRIPT_DIR")"

echo "Preparing Supabase for client..."
mkdir -p "$PKG_DIR/supabase/migrations/"
rm -f "$PKG_DIR/supabase/migrations/"*.sql
cp "$PKG_DIR/../core/supabase/migrations/"*.sql "$PKG_DIR/supabase/migrations/"
Copy link
Contributor

Choose a reason for hiding this comment

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

The wildcard *.sql will cause the script to fail if no SQL migration files exist in the core package. Since the script uses set -e, the cp command will exit with an error when the wildcard doesn't match any files, breaking the CI pipeline.

Fix: Add a check before copying or use a glob pattern that won't fail:

if ls "$PKG_DIR/../core/supabase/migrations/"*.sql 1> /dev/null 2>&1; then
  cp "$PKG_DIR/../core/supabase/migrations/"*.sql "$PKG_DIR/supabase/migrations/"
fi

Or use shopt -s nullglob to make unmatched globs expand to nothing.

Suggested change
cp "$PKG_DIR/../core/supabase/migrations/"*.sql "$PKG_DIR/supabase/migrations/"
if ls "$PKG_DIR/../core/supabase/migrations/"*.sql 1> /dev/null 2>&1; then
cp "$PKG_DIR/../core/supabase/migrations/"*.sql "$PKG_DIR/supabase/migrations/"
fi

Spotted by Graphite Agent

Fix in Graphite


Is this helpful? React 👍 or 👎 to let us know.

cp "$PKG_DIR/../core/supabase/seed.sql" "$PKG_DIR/supabase/"
echo "Migrations and seed copied from core"
5 changes: 4 additions & 1 deletion pkgs/core/project.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@
]
},
"targets": {
"supabase:ci-marker": {
"executor": "nx:noop"
},
"dump-realtime-schema": {
"executor": "nx:run-commands",
"local": true,
Expand Down Expand Up @@ -275,7 +278,7 @@
"executor": "nx:run-commands",
"cache": true,
"inputs": ["production", "^production"],
"dependsOn": ["^build"],
"dependsOn": ["^build", "lint"],
"options": {
"cwd": "{projectRoot}",
"command": "pnpm vitest --typecheck.only --run --config vitest.typecheck.config.ts"
Expand Down
2 changes: 1 addition & 1 deletion pkgs/dsl/project.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
"executor": "nx:run-commands",
"cache": true,
"inputs": ["production"],
"dependsOn": [],
"dependsOn": ["lint"],
"options": {
"cwd": "{projectRoot}",
"command": "pnpm vitest --typecheck.only --run --config vitest.typecheck.config.ts"
Expand Down
3 changes: 3 additions & 0 deletions pkgs/edge-worker/project.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
"sourceRoot": "pkgs/edge-worker",
"projectType": "library",
"targets": {
"supabase:ci-marker": {
"executor": "nx:noop"
},
"build": {
"executor": "nx:noop",
"dependsOn": ["^build"]
Expand Down
15 changes: 15 additions & 0 deletions pkgs/edge-worker/scripts/prepare-supabase.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#!/bin/bash
# Prepares Supabase for edge-worker package by copying migrations and seed from core.
# Called automatically by scripts/supabase-start.sh before starting Supabase.

set -e

SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
PKG_DIR="$(dirname "$SCRIPT_DIR")"

echo "Preparing Supabase for edge-worker..."
mkdir -p "$PKG_DIR/supabase/migrations/"
rm -f "$PKG_DIR/supabase/migrations/"*.sql
cp "$PKG_DIR/../core/supabase/migrations/"*.sql "$PKG_DIR/supabase/migrations/"
cp "$PKG_DIR/../core/supabase/seed.sql" "$PKG_DIR/supabase/"
echo "Migrations and seed copied from core"
112 changes: 112 additions & 0 deletions scripts/ci-prestart-supabase.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
#!/bin/bash
# scripts/ci-prestart-supabase.sh
#
# Pre-starts Supabase for affected packages in CI.
# First instance pulls Docker images, rest start in parallel.
#
# Usage: ./scripts/ci-prestart-supabase.sh <package1> [package2] ...
# Example: ./scripts/ci-prestart-supabase.sh core client
# Example: ./scripts/ci-prestart-supabase.sh edge-worker
#
# Env vars:
# NX_BASE - Base ref for affected check (default: origin/main)
# NX_HEAD - Head ref for affected check (default: HEAD)
#
# Optimization: Supabase start has two slow phases:
# 1. Docker image pull (~slow first time, then cached)
# 2. Container startup (~28s even with cached images)
# This script starts the first instance (pulls images), then starts
# the rest in parallel to save ~1 minute on CI runs.

set -euo pipefail

if [ $# -eq 0 ]; then
echo "Usage: $0 <package1> [package2] ..."
echo "Example: $0 core client"
exit 1
fi

SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
BASE=${NX_BASE:-origin/main}
HEAD=${NX_HEAD:-HEAD}

# Map packages to their directories
declare -A PKG_DIRS=(
["core"]="pkgs/core"
["client"]="pkgs/client"
["edge-worker"]="pkgs/edge-worker"
["cli"]="pkgs/cli"
)

# Get all affected projects with supabase:ci-marker target
AFFECTED=$(pnpm nx show projects --affected -t supabase:ci-marker --base="$BASE" --head="$HEAD" 2>/dev/null || echo "")

# Filter to only packages specified as arguments
DIRS=()
for pkg in "$@"; do
if [ -z "${PKG_DIRS[$pkg]:-}" ]; then
echo "Warning: Unknown package '$pkg', skipping"
continue
fi
if echo "$AFFECTED" | grep -q "^${pkg}$"; then
DIRS+=("${PKG_DIRS[$pkg]}")
echo "Package '$pkg' is affected"
else
echo "Package '$pkg' is not affected, skipping"
fi
done

if [ ${#DIRS[@]} -eq 0 ]; then
echo "No affected packages need Supabase"
exit 0
fi

echo "Starting Supabase for: ${DIRS[*]}"

LOGDIR=$(mktemp -d)
trap "rm -rf $LOGDIR" EXIT

# First one pulls Docker images (must complete before others)
echo "::group::Starting ${DIRS[0]} (pulling Docker images)"
if ! "$SCRIPT_DIR/supabase-start-locked.sh" "${DIRS[0]}" 2>&1 | tee "$LOGDIR/first.log"; then
echo "::endgroup::"
echo "::error::Failed to start ${DIRS[0]}"
exit 1
fi
echo "::endgroup::"

# Rest in parallel (images cached, ~28s each but concurrent)
if [ ${#DIRS[@]} -gt 1 ]; then
REMAINING=$((${#DIRS[@]} - 1))
echo "Starting $REMAINING more instance(s) in parallel..."

PIDS=()
for dir in "${DIRS[@]:1}"; do
name=$(basename "$dir")
"$SCRIPT_DIR/supabase-start-locked.sh" "$dir" > "$LOGDIR/$name.log" 2>&1 &
PIDS+=("$!:$dir:$name")
done

FAILED=0
for entry in "${PIDS[@]}"; do
pid=${entry%%:*}
rest=${entry#*:}
dir=${rest%%:*}
name=${rest#*:}
if ! wait "$pid"; then
echo "::error::Failed to start $dir"
echo "::group::$name log"
cat "$LOGDIR/$name.log"
echo "::endgroup::"
FAILED=1
else
echo ":: $dir started"
fi
done

if [ $FAILED -eq 1 ]; then
exit 1
fi
fi

echo "All Supabase instances started"
12 changes: 11 additions & 1 deletion scripts/supabase-start.sh
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,10 @@ set -e
# Behavior:
# 1. Checks if Supabase is already running (fast path)
# 2. If running: exits immediately
# 3. If not running: cleans up stale containers and starts fresh
# 3. If not running:
# a. Runs <project>/scripts/prepare-supabase.sh if it exists (e.g., copy migrations)
# b. Cleans up stale containers
# c. Starts Supabase fresh
#
# Exit codes:
# 0 - Success (Supabase is running)
Expand Down Expand Up @@ -58,6 +61,13 @@ fi
# Supabase is not running - need to start it
echo -e "${YELLOW}Supabase is not running. Starting...${NC}"

# Run package-specific preparation if script exists
PREPARE_SCRIPT="$PROJECT_DIR/scripts/prepare-supabase.sh"
if [ -x "$PREPARE_SCRIPT" ]; then
echo -e "${YELLOW}Running prepare-supabase.sh...${NC}"
"$PREPARE_SCRIPT"
fi

# Clean up any stale containers first
# This prevents errors from previous incomplete shutdowns
echo -e "${YELLOW}Cleaning up any stale containers...${NC}"
Expand Down