Files
Gabriel Brown 7d1884be41
Build and Deploy Next App / quality (push) Successful in 1m24s
Build and Deploy Next App / convex-deploy (push) Successful in 1m58s
Build and Deploy Next App / build-next (push) Successful in 5m32s
Deploy from CI with Infisical and ship Payload changes as migrations
CI reads Infisical staging as the read-only convexmonorepo-ci machine identity, deploys the Convex functions, builds and pushes the image, and asks the VPS to redeploy. Payload schema changes now ship as migrations that production runs on startup; the baseline matches the production schema and is recorded as applied there. The local stack moves to its own ports and syncs the Convex runtime env, and the scripts pick up Infisical account switching, dev-kill and a cache-safe CI install.
2026-10-01 14:42:55 -04:00

101 lines
4.0 KiB
Bash
Executable File

#!/usr/bin/env bash
set -euo pipefail
SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
ROOT_DIR="$(cd -- "$SCRIPT_DIR/../.." && pwd)"
COMPOSE_FILE="$ROOT_DIR/docker/compose.local.yml"
STATE_FILE="$ROOT_DIR/.local/dev.generated.env"
ENV_FILE=""
info() { printf '▶ %s\n' "$*"; }
die() { printf 'Error: %s\n' "$*" >&2; exit 1; }
if command -v docker >/dev/null 2>&1; then RUNTIME=docker
elif command -v podman >/dev/null 2>&1; then RUNTIME=podman
else die "Docker or Podman is required."; fi
"$RUNTIME" info >/dev/null 2>&1 || die "$RUNTIME is not usable."
mkdir -p "$ROOT_DIR/.local"
cleanup() { [ -z "$ENV_FILE" ] || rm -f "$ENV_FILE"; }
trap cleanup EXIT
refresh_env() {
local next
next="$(mktemp "${TMPDIR:-/tmp}/convex-monorepo-local.XXXXXX.env")"
sh "$ROOT_DIR/scripts/export-env" dev > "$next" || { rm -f "$next"; die "Unable to export Infisical dev."; }
[ -z "$ENV_FILE" ] || rm -f "$ENV_FILE"
ENV_FILE="$next"
set -a
# shellcheck disable=SC1090
source "$ENV_FILE"
set +a
}
dc() { "$RUNTIME" compose --env-file "$ENV_FILE" -f "$COMPOSE_FILE" "$@"; }
upsert_state() {
local key="$1" value="$2" tmp escaped
tmp="$(mktemp "${TMPDIR:-/tmp}/convex-monorepo-state.XXXXXX.env")"
[ ! -f "$STATE_FILE" ] || grep -v "^${key}=" "$STATE_FILE" > "$tmp" || true
escaped="$(printf '%s' "$value" | sed "s/'/'\\\\''/g")"
printf "%s='%s'\n" "$key" "$escaped" >> "$tmp"
mv "$tmp" "$STATE_FILE"
}
refresh_env
info "Starting local Payload Postgres, Convex, and dashboard"
dc up -d
info "Waiting for Payload Postgres"
for i in $(seq 1 30); do
dc exec -T postgres pg_isready -U "${POSTGRES_USER:-convexmonorepo}" >/dev/null 2>&1 && break
[ "$i" -lt 30 ] || die "Postgres did not become ready."
sleep 1
done
info "Waiting for Convex at http://localhost:${BACKEND_PORT:-3240}"
for i in $(seq 1 60); do
curl -fs "http://localhost:${BACKEND_PORT:-3240}/version" >/dev/null 2>&1 && break
[ "$i" -lt 60 ] || die "Convex did not become ready."
sleep 2
done
if [ -z "${CONVEX_SELF_HOSTED_ADMIN_KEY:-}" ]; then
admin_key="$(dc exec -T convex-backend ./generate_admin_key.sh 2>/dev/null | grep -E '.+\|.+' | tail -n1 | tr -d '\r')"
[ -n "$admin_key" ] || die "Unable to generate the Convex admin key."
upsert_state CONVEX_SELF_HOSTED_ADMIN_KEY "$admin_key"
refresh_env
info "Generated the machine-local Convex admin key"
fi
info "Deploying Convex schema and functions"
(cd "$ROOT_DIR/packages/backend" && bun run setup)
# Env sync runs after the deploy: changing deployment env re-analyzes the
# deployed modules, which fails on a fresh volume before the first deploy.
info "Synchronizing the Convex function runtime environment"
sh "$ROOT_DIR/scripts/with-env" dev -- bash "$ROOT_DIR/scripts/sync-local-convex-env"
convex_env_names="$(
sh "$ROOT_DIR/scripts/with-env" dev -- bash -c \
'cd packages/backend && bunx convex env list' 2>/dev/null \
| sed -n 's/^\([A-Za-z_][A-Za-z0-9_]*\)=.*/\1/p'
)"
if ! printf '%s\n' "$convex_env_names" | grep -qx 'JWT_PRIVATE_KEY' \
|| ! printf '%s\n' "$convex_env_names" | grep -qx 'JWKS' \
|| ! printf '%s\n' "$convex_env_names" | grep -qx 'SITE_URL'; then
info "Configuring local Convex Auth keys"
auth_keys="$(node "$ROOT_DIR/scripts/generate-convex-auth-keys.mjs")"
jwt="$(printf '%s\n' "$auth_keys" | sed -n 's/^JWT_PRIVATE_KEY="\(.*\)"$/\1/p')"
jwks="$(printf '%s\n' "$auth_keys" | sed -n 's/^JWKS=//p')"
JWT_VAL="$jwt" JWKS_VAL="$jwks" sh "$ROOT_DIR/scripts/with-env" dev -- bash -c '
cd packages/backend
bunx convex env set "JWT_PRIVATE_KEY=$JWT_VAL" >/dev/null
bunx convex env set "JWKS=$JWKS_VAL" >/dev/null
bunx convex env set "SITE_URL=http://localhost:3000" >/dev/null
'
fi
info "Seeding local Payload from snapshot if needed"
bash "$ROOT_DIR/scripts/db/seed-payload" --yes
printf '\nLocal stack ready:\n App: http://localhost:3000\n Convex: http://localhost:%s\n Dashboard: http://localhost:%s\n Payload Postgres: localhost:%s\n' "${BACKEND_PORT:-3240}" "${DASHBOARD_PORT:-6794}" "${POSTGRES_PORT:-5436}"