Skip to content

Commit 3fd3466

Browse files
committed
chore: pre-start Supabase for affected packages in CI (#423)
# Optimize CI by Pre-starting Supabase for Affected Packages This PR improves CI performance by intelligently pre-starting Supabase instances for affected packages. The implementation: 1. Adds a new CI step that pre-starts Supabase for packages that need it 2. Creates a new script `ci-prestart-supabase.sh` that: - Identifies affected packages requiring Supabase - Starts the first instance sequentially (to pull Docker images) - Starts remaining instances in parallel (saving ~1 minute per CI run) 3. Adds `supabase:ci-marker` targets to packages that require Supabase: - core - client - edge-worker This optimization reduces CI time by avoiding redundant Docker image pulls and parallelizing container startup, which typically takes ~28 seconds even with cached images.
1 parent a16bd1e commit 3fd3466

File tree

9 files changed

+171
-4
lines changed

9 files changed

+171
-4
lines changed

.github/workflows/ci.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,9 @@ jobs:
5252
- name: Verify NX_BASE and NX_HEAD are set
5353
run: echo "BASE=$NX_BASE HEAD=$NX_HEAD"
5454

55+
- name: Pre-start Supabase for affected packages
56+
run: ./scripts/ci-prestart-supabase.sh core client
57+
5558
- name: Quality gate (lint + typecheck + test)
5659
run: pnpm nx affected -t lint typecheck test --parallel --configuration=production --base="$NX_BASE" --head="$NX_HEAD"
5760

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

102+
- name: Pre-start Supabase for affected packages
103+
run: ./scripts/ci-prestart-supabase.sh edge-worker
104+
99105
- name: Check if edge-worker e2e tests are affected
100106
id: check-affected
101107
run: |

pkgs/client/project.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@
55
"projectType": "library",
66
"tags": [],
77
"targets": {
8+
"supabase:ci-marker": {
9+
"executor": "nx:noop"
10+
},
811
"build": {
912
"executor": "nx:noop",
1013
"inputs": ["production", "^production"],
@@ -202,7 +205,7 @@
202205
"executor": "nx:run-commands",
203206
"cache": true,
204207
"inputs": ["production", "^production"],
205-
"dependsOn": ["^build"],
208+
"dependsOn": ["^build", "lint"],
206209
"options": {
207210
"cwd": "{projectRoot}",
208211
"command": "pnpm vitest --typecheck.only --run --config vitest.typecheck.config.ts"
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
#!/bin/bash
2+
# Prepares Supabase for client package by copying migrations and seed from core.
3+
# Called automatically by scripts/supabase-start.sh before starting Supabase.
4+
5+
set -e
6+
7+
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
8+
PKG_DIR="$(dirname "$SCRIPT_DIR")"
9+
10+
echo "Preparing Supabase for client..."
11+
mkdir -p "$PKG_DIR/supabase/migrations/"
12+
rm -f "$PKG_DIR/supabase/migrations/"*.sql
13+
cp "$PKG_DIR/../core/supabase/migrations/"*.sql "$PKG_DIR/supabase/migrations/"
14+
cp "$PKG_DIR/../core/supabase/seed.sql" "$PKG_DIR/supabase/"
15+
echo "Migrations and seed copied from core"

pkgs/core/project.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@
1919
]
2020
},
2121
"targets": {
22+
"supabase:ci-marker": {
23+
"executor": "nx:noop"
24+
},
2225
"dump-realtime-schema": {
2326
"executor": "nx:run-commands",
2427
"local": true,
@@ -275,7 +278,7 @@
275278
"executor": "nx:run-commands",
276279
"cache": true,
277280
"inputs": ["production", "^production"],
278-
"dependsOn": ["^build"],
281+
"dependsOn": ["^build", "lint"],
279282
"options": {
280283
"cwd": "{projectRoot}",
281284
"command": "pnpm vitest --typecheck.only --run --config vitest.typecheck.config.ts"

pkgs/dsl/project.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@
4040
"executor": "nx:run-commands",
4141
"cache": true,
4242
"inputs": ["production"],
43-
"dependsOn": [],
43+
"dependsOn": ["lint"],
4444
"options": {
4545
"cwd": "{projectRoot}",
4646
"command": "pnpm vitest --typecheck.only --run --config vitest.typecheck.config.ts"

pkgs/edge-worker/project.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44
"sourceRoot": "pkgs/edge-worker",
55
"projectType": "library",
66
"targets": {
7+
"supabase:ci-marker": {
8+
"executor": "nx:noop"
9+
},
710
"build": {
811
"executor": "nx:noop",
912
"dependsOn": ["^build"]
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
#!/bin/bash
2+
# Prepares Supabase for edge-worker package by copying migrations and seed from core.
3+
# Called automatically by scripts/supabase-start.sh before starting Supabase.
4+
5+
set -e
6+
7+
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
8+
PKG_DIR="$(dirname "$SCRIPT_DIR")"
9+
10+
echo "Preparing Supabase for edge-worker..."
11+
mkdir -p "$PKG_DIR/supabase/migrations/"
12+
rm -f "$PKG_DIR/supabase/migrations/"*.sql
13+
cp "$PKG_DIR/../core/supabase/migrations/"*.sql "$PKG_DIR/supabase/migrations/"
14+
cp "$PKG_DIR/../core/supabase/seed.sql" "$PKG_DIR/supabase/"
15+
echo "Migrations and seed copied from core"

scripts/ci-prestart-supabase.sh

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
#!/bin/bash
2+
# scripts/ci-prestart-supabase.sh
3+
#
4+
# Pre-starts Supabase for affected packages in CI.
5+
# First instance pulls Docker images, rest start in parallel.
6+
#
7+
# Usage: ./scripts/ci-prestart-supabase.sh <package1> [package2] ...
8+
# Example: ./scripts/ci-prestart-supabase.sh core client
9+
# Example: ./scripts/ci-prestart-supabase.sh edge-worker
10+
#
11+
# Env vars:
12+
# NX_BASE - Base ref for affected check (default: origin/main)
13+
# NX_HEAD - Head ref for affected check (default: HEAD)
14+
#
15+
# Optimization: Supabase start has two slow phases:
16+
# 1. Docker image pull (~slow first time, then cached)
17+
# 2. Container startup (~28s even with cached images)
18+
# This script starts the first instance (pulls images), then starts
19+
# the rest in parallel to save ~1 minute on CI runs.
20+
21+
set -euo pipefail
22+
23+
if [ $# -eq 0 ]; then
24+
echo "Usage: $0 <package1> [package2] ..."
25+
echo "Example: $0 core client"
26+
exit 1
27+
fi
28+
29+
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
30+
BASE=${NX_BASE:-origin/main}
31+
HEAD=${NX_HEAD:-HEAD}
32+
33+
# Map packages to their directories
34+
declare -A PKG_DIRS=(
35+
["core"]="pkgs/core"
36+
["client"]="pkgs/client"
37+
["edge-worker"]="pkgs/edge-worker"
38+
["cli"]="pkgs/cli"
39+
)
40+
41+
# Get all affected projects with supabase:ci-marker target
42+
AFFECTED=$(pnpm nx show projects --affected -t supabase:ci-marker --base="$BASE" --head="$HEAD" 2>/dev/null || echo "")
43+
44+
# Filter to only packages specified as arguments
45+
DIRS=()
46+
for pkg in "$@"; do
47+
if [ -z "${PKG_DIRS[$pkg]:-}" ]; then
48+
echo "Warning: Unknown package '$pkg', skipping"
49+
continue
50+
fi
51+
if echo "$AFFECTED" | grep -q "^${pkg}$"; then
52+
DIRS+=("${PKG_DIRS[$pkg]}")
53+
echo "Package '$pkg' is affected"
54+
else
55+
echo "Package '$pkg' is not affected, skipping"
56+
fi
57+
done
58+
59+
if [ ${#DIRS[@]} -eq 0 ]; then
60+
echo "No affected packages need Supabase"
61+
exit 0
62+
fi
63+
64+
echo "Starting Supabase for: ${DIRS[*]}"
65+
66+
LOGDIR=$(mktemp -d)
67+
trap "rm -rf $LOGDIR" EXIT
68+
69+
# First one pulls Docker images (must complete before others)
70+
echo "::group::Starting ${DIRS[0]} (pulling Docker images)"
71+
if ! "$SCRIPT_DIR/supabase-start-locked.sh" "${DIRS[0]}" 2>&1 | tee "$LOGDIR/first.log"; then
72+
echo "::endgroup::"
73+
echo "::error::Failed to start ${DIRS[0]}"
74+
exit 1
75+
fi
76+
echo "::endgroup::"
77+
78+
# Rest in parallel (images cached, ~28s each but concurrent)
79+
if [ ${#DIRS[@]} -gt 1 ]; then
80+
REMAINING=$((${#DIRS[@]} - 1))
81+
echo "Starting $REMAINING more instance(s) in parallel..."
82+
83+
PIDS=()
84+
for dir in "${DIRS[@]:1}"; do
85+
name=$(basename "$dir")
86+
"$SCRIPT_DIR/supabase-start-locked.sh" "$dir" > "$LOGDIR/$name.log" 2>&1 &
87+
PIDS+=("$!:$dir:$name")
88+
done
89+
90+
FAILED=0
91+
for entry in "${PIDS[@]}"; do
92+
pid=${entry%%:*}
93+
rest=${entry#*:}
94+
dir=${rest%%:*}
95+
name=${rest#*:}
96+
if ! wait "$pid"; then
97+
echo "::error::Failed to start $dir"
98+
echo "::group::$name log"
99+
cat "$LOGDIR/$name.log"
100+
echo "::endgroup::"
101+
FAILED=1
102+
else
103+
echo ":: $dir started"
104+
fi
105+
done
106+
107+
if [ $FAILED -eq 1 ]; then
108+
exit 1
109+
fi
110+
fi
111+
112+
echo "All Supabase instances started"

scripts/supabase-start.sh

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,10 @@ set -e
1515
# Behavior:
1616
# 1. Checks if Supabase is already running (fast path)
1717
# 2. If running: exits immediately
18-
# 3. If not running: cleans up stale containers and starts fresh
18+
# 3. If not running:
19+
# a. Runs <project>/scripts/prepare-supabase.sh if it exists (e.g., copy migrations)
20+
# b. Cleans up stale containers
21+
# c. Starts Supabase fresh
1922
#
2023
# Exit codes:
2124
# 0 - Success (Supabase is running)
@@ -58,6 +61,13 @@ fi
5861
# Supabase is not running - need to start it
5962
echo -e "${YELLOW}Supabase is not running. Starting...${NC}"
6063

64+
# Run package-specific preparation if script exists
65+
PREPARE_SCRIPT="$PROJECT_DIR/scripts/prepare-supabase.sh"
66+
if [ -x "$PREPARE_SCRIPT" ]; then
67+
echo -e "${YELLOW}Running prepare-supabase.sh...${NC}"
68+
"$PREPARE_SCRIPT"
69+
fi
70+
6171
# Clean up any stale containers first
6272
# This prevents errors from previous incomplete shutdowns
6373
echo -e "${YELLOW}Cleaning up any stale containers...${NC}"

0 commit comments

Comments
 (0)